Compare commits

...

304 Commits

Author SHA1 Message Date
Andrey Breslav
15dbfa7184 ++ android-ide-plugin module extracted 2014-10-08 18:23:51 +04:00
Andrey Breslav
b0196ac1ad ++ Logic related to command-line options moved to android-compiler-plugin 2014-10-08 18:18:29 +04:00
Andrey Breslav
0e07cb9872 ++ Expression codegen extension: receiver passed through 2014-10-07 23:58:38 +04:00
Andrey Breslav
0c6622489b ~ read actions added here and there 2014-10-01 16:43:01 +04:00
Andrey Breslav
a4bbf9b3ec Artifact for Android extensions plugin 2014-10-01 16:43:00 +04:00
Andrey Breslav
bb0141b85f Missing public added 2014-10-01 16:43:00 +04:00
Andrey Breslav
abc17943d7 Find Usages extension extracted 2014-10-01 16:42:59 +04:00
Andrey Breslav
5f209d4351 ExpressionCodegenExtension extracted 2014-10-01 16:42:59 +04:00
Andrey Breslav
a1989dc5e0 ExternalDeclarationsProvider introduced 2014-10-01 16:42:58 +04:00
Andrey Breslav
da32f47d2a android-ide-plugin module extracted 2014-10-01 16:42:58 +04:00
Andrey Breslav
78b3613cf5 Logic related to command-line options moved to android-compiler-plugin 2014-10-01 16:42:56 +04:00
Andrey Breslav
eae40ab965 Compiler plugins can provide extra command line parameters in JPS 2014-10-01 16:42:56 +04:00
Andrey Breslav
18ff58e4e7 CommandLineProcessor infrastructure added 2014-10-01 16:42:55 +04:00
Andrey Breslav
2d6ec5bd5d frontend.android renamed to android-compiler-plugin 2014-10-01 16:42:55 +04:00
Andrey Breslav
50ec0d7f8d Plugin component registrar introduced
CompilerConfiguration moved to plugin-api
2014-09-30 21:52:52 +04:00
Andrey Breslav
01b22a1dd1 plugin-api module introduced 2014-09-30 21:52:52 +04:00
Mikhail Mutcianko
73c2db8f44 fix android jps build test case
- add proper way of setting up android sdk for jps
- add missing android plugin runtime library
2014-09-30 21:52:51 +04:00
Mikhail Mutcianko
84690dd9ee add android bytecode persistence test 2014-09-30 21:52:51 +04:00
Mikhail Mutcianko
7402cf8356 add android find usages test 2014-09-30 21:52:50 +04:00
Mikhail Mutcianko
5a3186a7f8 fix find usage handler not returning android property as secondary element 2014-09-30 21:52:50 +04:00
Mikhail Mutcianko
9e75390895 add reverse renaming to android rename tests 2014-09-30 21:52:49 +04:00
Mikhail Mutcianko
0c180275f1 add android rename tests 2014-09-30 21:52:49 +04:00
Mikhail Mutcianko
06d173ca44 eliminate idToXml cache leftovers from android resource manger 2014-09-30 21:52:48 +04:00
Mikhail Mutcianko
f8dcbd8477 fix kotlin property renamer npe
- fix npe when element usage has no reference(e.g. xml cross usage)
2014-09-30 21:52:48 +04:00
Mikhail Mutcianko
cc6a9d5183 factor base android test case
- move common initialization code to base class
2014-09-30 21:52:47 +04:00
Mikhail Mutcianko
67a3932615 add all goto tests
- fix base test case failing when no res directory present
- get rid of JetProperty -> XmlAttr caching
2014-09-30 21:52:47 +04:00
Mikhail Mutcianko
b934402b55 fix android kotlin test framework
- fix android jars not indexed by java indexer
- fix goto test
2014-09-30 21:52:46 +04:00
Mikhail Mutcianko
1e25af94c0 add android jps builder test stub
wtf
2014-09-30 21:52:46 +04:00
Mikhail Mutcianko
ab7177e251 add android goto declaration test stub 2014-09-30 21:52:45 +04:00
Mikhail Mutcianko
52e0bf88f7 regenerate android tests after rebase 2014-09-30 21:52:45 +04:00
Mikhail Mutcianko
bbd4cb93ed fix android resource path arguments after rebase 2014-09-30 21:52:44 +04:00
Mikhail Mutcianko
4866168a21 fix android cross parser tests
- reorganize tests folder structure
- fix class attribute ignored in ide xml parser
2014-09-30 21:52:44 +04:00
Mikhail Mutcianko
fd125e07b6 refactor android kotlin fixture test
- move more setup code to base class
2014-09-30 21:52:43 +04:00
Mikhail Mutcianko
74b1017fcf delete obsolete android test 2014-09-30 21:52:42 +04:00
Mikhail Mutcianko
c3a668c8ca fix R class field resolving
- resolve by class name and package defined in AndroidManifest.xml
2014-09-30 21:52:42 +04:00
Mikhail Mutcianko
f20731548d add android completion tests
- add android plugin test classes as test library
- add base android test cases for kotlin, setting up android facet and sdk
2014-09-30 21:52:41 +04:00
Mikhail Mutcianko
b9b3575eb4 add android properties box tests 2014-09-30 21:52:41 +04:00
dedoz
28b8c8b5d6 add generated tests 2014-09-30 21:52:40 +04:00
Mikhail Mutcianko
8eba35cd76 optimize imports
tmp

stmp
2014-09-30 21:52:40 +04:00
Mikhail Mutcianko
530d6caa47 minor refactorings 2014-09-30 21:52:39 +04:00
Mikhail Mutcianko
6211485143 update android synthetic properties completion test
- add missing android classes as text into fixture
2014-09-30 21:52:39 +04:00
Mikhail Mutcianko
82cfb218e0 fix android plugin libs dependencies 2014-09-30 21:52:38 +04:00
Mikhail Mutcianko
9deea1caad fix cli argument tests 2014-09-30 21:52:38 +04:00
Mikhail Mutcianko
ca701f40e9 fix android plugin dependencies not unpacked 2014-09-30 21:52:37 +04:00
dedoz
e92f26123f add kotlin gradle plugin integration 2014-09-30 21:52:37 +04:00
dedoz
785a2d4200 add android xml to properties completion test 2014-09-30 21:52:36 +04:00
Mikhail Mutcianko
6554258166 add configuration key to pass android manifest file 2014-09-30 21:52:36 +04:00
Mikhail Mutcianko
7a06c8176e add android layout file searching to kotlin jps plugin 2014-09-30 21:52:35 +04:00
Mikhail Mutcianko
f582159d72 delegate android resource and manifest reading in ide to android support plugin 2014-09-30 21:52:35 +04:00
Mikhail Mutcianko
a84b3e82e6 correct interpretation of android id usage mixed with id declarations 2014-09-30 21:52:34 +04:00
Mikhail Mutcianko
7834423136 implement find usages action for android synthetic properties 2014-09-30 21:52:34 +04:00
Mikhail Mutcianko
aef7523b79 add android xml reference and rename handling to JetSimpleNameReference 2014-09-30 21:52:33 +04:00
Mikhail Mutcianko
b516cdffa8 android goto declaration handler reference fix
- goto handler now utilizes full featured reference resolving instead of simple name based resolving
2014-09-30 21:52:33 +04:00
Mikhail Mutcianko
7857302c47 fix excess xml parsing when renaming resources
- rebuild resource name -> xml attribute mappings same time as rebuilding synthetic properties
- update mappings during rename
2014-09-30 21:52:32 +04:00
Mikhail Mutcianko
b6bc9a92d6 add synthetic property renaming by renaming R light class field 2014-09-30 21:52:32 +04:00
Mikhail Mutcianko
ffd3d1ffa3 add bound property renaming by renaming xml attribute value 2014-09-30 21:52:31 +04:00
Mikhail Mutcianko
a18c97e6c5 refactor AndroidResourceManager
- move more common methods from xml processor implementations to resource manager
- optimize imports, reformat code
2014-09-30 21:52:31 +04:00
Mikhail Mutcianko
89908524ab fix double renaming issue
- rebuild resource mapping cache on external layout file changes
- move duplicated code to AndroidResourceManager
2014-09-30 21:52:31 +04:00
Mikhail Mutcianko
f3875cfde6 add missing android plugin dependency 2014-09-30 21:52:30 +04:00
Mikhail Mutcianko
c5d412e496 move android rename handler out of kotlin property renamer, extract resource manager class 2014-09-30 21:52:30 +04:00
Mikhail Mutcianko
c5689f5c26 reformat code, optimize imports 2014-09-30 21:31:12 +04:00
Mikhail Mutcianko
70253a61b6 revert cli converter to stream parsing 2014-09-30 21:31:12 +04:00
Mikhail Mutcianko
6e7c27d9fd add goto declaration support for synthetic android properties 2014-09-30 21:31:11 +04:00
Mikhail Mutcianko
5a994db798 rename android synthetic id property also renames respective xml resource 2014-09-30 21:31:08 +04:00
Mikhail Mutcianko
d959d4dbd0 add android synthetic element detecting helpers 2014-09-30 21:30:17 +04:00
dedoz
7a8bbccda3 replace sax with psi based android ui xml parsing in plugin 2014-09-30 21:30:17 +04:00
Mikhail Mutcianko
795177ca80 fix xml resolving
- replace VirtualFileListener based approach with direct PsiFile reading
2014-09-30 21:30:16 +04:00
Mikhail Mutcianko
8a191bb1a2 check if android metadata is present before inlining property 2014-09-30 21:30:16 +04:00
Mikhail Mutcianko
b7308b9b7c fix compiler argument tests 2014-09-30 21:30:15 +04:00
Mikhail Mutcianko
cc31520089 insert missing copyrights, move ByteArrayClassLoader up 2014-09-30 21:30:14 +04:00
dedoz
80547cf292 add android xml bridge invocation test 2014-09-30 21:30:14 +04:00
Mikhail Mutcianko
2a0a03e011 add byte code generation 2014-09-30 21:30:13 +04:00
Mikhail Mutcianko
ffbe0a3e4e add android manifest support 2014-09-30 21:30:12 +04:00
Mikhail Mutcianko
8a7bc4fa71 fix R class not resolved in dummy file 2014-09-30 21:30:12 +04:00
Mikhail Mutcianko
a682a1d208 refactor XmlHandler, optimize imports, remove unused files 2014-09-30 21:30:11 +04:00
Mikhail Mutcianko
d955cc87dc add missing module and build dependencies 2014-09-30 21:30:04 +04:00
Mikhail Mutcianko
cb1da3b07b add writePackage to KotlinWriter 2014-09-30 21:29:08 +04:00
Mikhail Mutcianko
e2ef7efcb4 refactor converter initialization
- push lazyInit() down to IDE and Cli implementations
- no file listeners created in cli implementation anymore
- fix tests
2014-09-30 21:29:07 +04:00
Mikhail Mutcianko
ee46064f02 event based file processing
- use VirtualFileListener to wait for ui xml file updates
- optimize imports
2014-09-30 21:29:07 +04:00
Mikhail Mutcianko
770a732449 suppress xml errors in converter
- simply ignore malformed layouts, xml editor in ide will highlight them anyway
2014-09-30 21:29:06 +04:00
Mikhail Mutcianko
03732ac606 add converter output caching
- add two level caching: per xml conversion result and complete resulting JetFile,
  so that only modified xmls are actually converted, and if no change has been
  made to any of those, last successfully built psi file is returned
- merge AndroidUIXmlPathProvider and AndroidUIXmlParser
- update tests
2014-09-30 21:29:05 +04:00
Mikhail Mutcianko
9683bc385a fix ant build
- add frontend.android content to sources path
2014-09-30 21:29:05 +04:00
Mikhail Mutcianko
e35cb603f9 add compiler key for providing android resources path 2014-09-30 21:29:04 +04:00
Mikhail Mutcianko
71edc602c8 fix npe when layout xml search path does not exist 2014-09-30 21:29:04 +04:00
Mikhail Mutcianko
958ea49978 obey android project structure when searching for ui xmls
- search for android layout xmls in ProjectRoot/res/layout/ when using IDEPathProvider
2014-09-30 21:29:03 +04:00
Mikhail Mutcianko
86b2a3e5a5 missing files handling in converter
- silently continue if no files were found to convert
2014-09-30 21:29:02 +04:00
Mikhail Mutcianko
de56576d15 ide analyzer integration stub
- add android ui xml path providers/stubs
- add generated file injection during analysis
2014-09-30 21:29:02 +04:00
Mikhail Mutcianko
a5d1936393 auto cast widget to its original type
- change property return type signatures from View to actual widget type
- simplify and update tests
2014-09-30 21:29:01 +04:00
Mikhail Mutcianko
c63281f91a add converted result compilation test 2014-09-30 21:29:01 +04:00
Mikhail Mutcianko
f4c83d88eb android UI xml bridge initial
- add frontend.android module
- add xml ids to kotlin extension properties converter
- add converter basic functional test
2014-09-30 21:29:00 +04:00
Alexey Sedunov
4ca39e8f9a Create From Usage: Quick-fix for local variables 2014-09-30 19:55:46 +04:00
Alexey Sedunov
e85d34b445 Create From Usage: Add ability to select val/var when creating property 2014-09-30 19:55:45 +04:00
Alexey Sedunov
e9b16f3e1b Create Function From Usage: Use Any if error type is inferred 2014-09-30 19:55:44 +04:00
Alexey Sedunov
854962a139 Create Function From Usage: Fix availability condition 2014-09-30 19:55:43 +04:00
Alexey Sedunov
a6ba3a569d Create From Usage: Move "Create function"-related tests to separate directory 2014-09-30 19:55:43 +04:00
Alexey Sedunov
0f43d4d07c Create From Usage: Move callable builder to separate package 2014-09-30 19:55:41 +04:00
Alexey Sedunov
be211d7cda Create From Usage: Generalize function builder for both functions and properties 2014-09-30 19:55:40 +04:00
Natalia Ukhorskaya
9032a6166e Fix Android tests 2014-09-30 17:48:40 +04:00
Valentin Kipyatkov
35ebbab733 Fixed smart completion not working when parameter has default value 2014-09-30 15:29:10 +04:00
Valentin Kipyatkov
267aabae12 Smart completion: multiple arguments at once 2014-09-30 15:29:10 +04:00
Natalia Ukhorskaya
a04efad059 Fix error message for missing propertyDelegated method in IDE 2014-09-30 15:00:30 +04:00
Natalia Ukhorskaya
6179b4889b Debugger: fix className for properties in class objects 2014-09-30 15:00:29 +04:00
Natalia Ukhorskaya
4994e771d0 Evaluate expression: support EE for shared vars 2014-09-30 15:00:28 +04:00
Natalia Ukhorskaya
8ad18df3fa Evaluate expression: switch off breakpoints during eval4j run 2014-09-30 15:00:27 +04:00
Nikolay Krasko
e1c7ad50d6 More changes after replacing config directory
- Plugin auto-enable script updated
 - Don't drop configured folder in update-dependencies
 - Drop test config and system folders in update-dependencies
2014-09-30 13:02:02 +04:00
Alexey Tsvetkov
0af291091e KT-5673: always write val property to backing field 2014-09-29 21:35:30 +04:00
Alexey Tsvetkov
b70466f9f3 KT-5673: added tests 2014-09-29 21:35:30 +04:00
Alexey Tsvetkov
ed14f86957 KT-4773: use receiver for delegated extension property 2014-09-29 21:35:30 +04:00
Alexey Tsvetkov
3424142b65 KT-4773: added tests 2014-09-29 21:35:30 +04:00
Alexey Tsvetkov
f8968c2f77 JS backend minor: added @NotNull annotation to getArguments() 2014-09-29 21:35:30 +04:00
Zalim Bashorov
916cfb7051 Regenerate testData for reservedWords after take was fixed. 2014-09-29 19:47:49 +04:00
Zalim Bashorov
2352085391 Improve testData generator for reserved words.
Cashing iterator in CyclicStream.
Detect generating unexpected testdata file(e.g. may caused because of bug in stdlib).
2014-09-29 19:47:49 +04:00
Michael Nedzelsky
098b4c170f JS backend: fix KT-4297 PrimitiveHashMap returns wrong keys (string instead of original type) 2014-09-29 17:46:33 +04:00
Denis Zharkov
f1d9d11590 Store stack values before inlines. #KT-5634 Fixed
Inlining code violates JIT assumptions for OSR in Java 8 in case of
starting with non-empty and containing cycles.

Fix is to mark each inlined block with markers and then store/restore
stack state before and after inlined body.
2014-09-29 17:16:58 +04:00
Michael Bogdanov
469db95662 Inline markers added 2014-09-29 17:16:57 +04:00
Nikolay Krasko
e035fc3219 Minor: fix some dictionary suggestions 2014-09-29 14:03:09 +04:00
Nikolay Krasko
b79b7554ff Refactoring: move application utility methods from refactoring utility to common place 2014-09-29 14:03:02 +04:00
Nikolay Krasko
89f0c8dc87 Rewrite ApplicationUtils.java to Kotlin 2014-09-29 13:55:47 +04:00
Nikolay Krasko
0a97469ff4 Make special config folder for IDEA to keep separate settings for tests 2014-09-29 13:55:46 +04:00
Alexey Sedunov
ff29e581db Create Function From Usage: Add empty lines when inserting new function 2014-09-29 01:27:28 +04:00
Alexey Sedunov
afd8809ff5 Create Function From Usage: Wrap build() function in try-finally 2014-09-29 01:27:26 +04:00
Alexey Sedunov
6043c6d0a7 Create Function From Usage: Quick-fix for functions invoked via call expressions 2014-09-29 01:27:25 +04:00
Alexey Sedunov
22e3557895 Extract utility functions from ExtractKotlinFunctionHandler 2014-09-29 01:27:24 +04:00
Alexey Sedunov
67df2b448f Create Function From Usage: Quick-fix for invoke convention 2014-09-29 01:27:23 +04:00
Alexey Sedunov
cf59af6c7a Create Function From Usage: Quick-fix for unary operations 2014-09-29 01:27:22 +04:00
Alexey Sedunov
0582cf5db1 Create Function From Usage: Quick-fix for binary operations 2014-09-29 01:27:20 +04:00
Alexey Sedunov
ae69bea543 Create Function From Usage: Refactor the function builder 2014-09-29 01:27:19 +04:00
Alexey Sedunov
d9318fdc57 Create Function From Usage: Make ClassCandidateListCellRenderer nested class 2014-09-29 01:27:18 +04:00
Alexey Sedunov
06ab4e1c9a Name Validator: Add filtering to collecting validator 2014-09-29 01:27:17 +04:00
Alexey Sedunov
2c3f0f8c29 Name Validator: Translate JetNameValidator to Kotlin 2014-09-29 01:27:16 +04:00
Alexey Sedunov
8ec2b5a973 Name Validator: Remove unused fields and parameters 2014-09-29 01:27:15 +04:00
Alexey Sedunov
5d7a07456d Create Function From Usage: Move type utilities to separate file 2014-09-29 01:27:14 +04:00
Alexey Sedunov
34632f46f6 Create Function From Usage: Translate ClassCandidateListCellRenderer to Kotlin 2014-09-29 01:27:13 +04:00
Alexey Sedunov
d1e43d6482 Create Function From Usage: Move "Create function from usage"-related classes to separate package 2014-09-29 01:27:12 +04:00
Alexey Sedunov
08e3a6a9de Create Function From Usage: Move action factories to top level 2014-09-29 01:27:11 +04:00
Alexey Sedunov
9573c739ea Create From Usage: Move classes to separate package 2014-09-29 01:27:10 +04:00
Alexey Sedunov
23ea43fde5 Create From Usage: Translate base class to Kotlin 2014-09-29 01:27:09 +04:00
Michael Nedzelsky
9d49089041 JS backend: tests for char type 2014-09-28 19:51:58 +04:00
Michael Nedzelsky
6aff9803c4 JS backend: support for char type 2014-09-28 19:51:54 +04:00
Michael Nedzelsky
2e4e5c5d1d JS backend: tests for Long type support 2014-09-28 19:51:51 +04:00
Michael Nedzelsky
dca6e31519 JS backend: add support for Long type 2014-09-28 19:51:48 +04:00
Michael Nedzelsky
d1d722546e JS backend: prepare long.js for use in translator 2014-09-28 19:51:43 +04:00
Michael Nedzelsky
f42d7319a5 JS backend: original long.js from closure-library 2014-09-28 19:51:40 +04:00
Nikolay Krasko
1239d37cb9 Update to EAP 138.2458.8 2014-09-27 18:18:49 +04:00
Pavel V. Talanov
54799b1a34 Internal visibility works the same as public
Fix test data
This change is needed to preserve old behaviour for M9
isFriend() utilities become unused after this change
2014-09-26 22:06:32 +04:00
Alexander Udalov
cd0551078c Support static method references
#KT-5123 Fixed
2014-09-26 18:48:43 +04:00
Alexander Udalov
19497262b3 Don't lookup built-in classes by invalid names
#KT-5869 Fixed
2014-09-26 18:48:43 +04:00
Pavel V. Talanov
2227b87ca3 Do not store psi in CopiedCode
It is transferable and can exist even if project is closed
2014-09-26 18:21:12 +04:00
Pavel V. Talanov
ec7d294fcc Minor: remove some redundant not null assertions from Kotlin code 2014-09-26 18:21:12 +04:00
Pavel V. Talanov
477378fab7 Minor: convert CopiedCode to Kotlin 2014-09-26 18:21:11 +04:00
Pavel V. Talanov
f292c554cb Cache result of getAllPossiblePackageClasses()
Move this utility from IDELightClassGenerationSupport to PackageIndexUtil
2014-09-26 18:21:11 +04:00
Pavel V. Talanov
9219616bb8 Minor: rename and refactor PackageIndexUtil#containsAny() 2014-09-26 18:21:10 +04:00
Pavel V. Talanov
4370577457 Minor: Convert PackageIndexUtil to Kotlin 2014-09-26 18:21:10 +04:00
Pavel V. Talanov
649a6f12bb Compute builtins directory url only once 2014-09-26 18:21:09 +04:00
Pavel V. Talanov
6127af97a5 Manually implement scopes for ModuleSourceInfo
This allows for a faster contains(VirtualFile) check
2014-09-26 18:21:09 +04:00
Michael Bogdanov
b3e075173b KT-5863: Inlined try/catch/finally block with non-local return doesn't work properly
#KT-5863 Fixed
2014-09-26 17:08:58 +04:00
Ilya Ryzhenkov
bf368b2bc2 Restore accidentally removed String.getBytes() and mark as deprecated (discouraged). 2014-09-26 16:28:08 +04:00
Valentin Kipyatkov
028520956f Fixed tests 2014-09-26 15:20:46 +04:00
Denis Zharkov
da159c1e53 Simple version of redundant GOTO's removing 2014-09-26 12:37:33 +04:00
Denis Zharkov
e1c2fbaec0 Minor refactoring: use array of MethodTransformers
instead of delegation
2014-09-26 12:37:32 +04:00
Denis Zharkov
35cda83c8f Refined merging logic #KT-5844 Fixed
If merging primitives of different integral types (e.g. I and Z) return
INT.
Else return UNINITIALIZED_VALUE
2014-09-26 12:37:04 +04:00
Alexander Udalov
96308aa14e Increase ABI version
After changes to package part names and top level closure names
2014-09-26 10:23:21 +04:00
Alexander Udalov
80a7c64369 Prepend zeros to package part hash code 2014-09-26 10:23:14 +04:00
Alexander Udalov
e2273a3d85 Update JetExceptionFilter behavior for top level closures
Now JetExceptionFilter can determine the source file looking at the class FQ
name for sure
2014-09-26 10:22:28 +04:00
Alexander Udalov
43c26d0947 Update JetExceptionFilter to the latest API, fix warnings 2014-09-26 10:22:28 +04:00
Alexander Udalov
8f92141137 Minor, exclude tinyApp test classes output from IDEA indices 2014-09-26 10:22:28 +04:00
Alexander Udalov
49e5b950ce Workaround package part hash codes in tests on JetPositionManager 2014-09-26 10:22:27 +04:00
Alexander Udalov
b5832d2656 Refactor and generate tests on JetPositionManager 2014-09-26 10:22:27 +04:00
Alexander Udalov
9f7979d0ce Workaround package part hash codes in OuterClassGenTest 2014-09-26 10:22:26 +04:00
Alexander Udalov
4d055d5ab4 Check header on package part classes in MethodInliner 2014-09-26 10:22:26 +04:00
Alexander Udalov
c30aa7db84 Include package part name to top level closure names
#KT-4234 Fixed
 #KT-4496 Fixed
2014-09-26 10:22:25 +04:00
Alexander Udalov
7b374b9509 Refactor CodegenBinding
- store source element in synthetic descriptor for easier debugging and lesser
  amount of needed method parameters everywhere
- simplify methods which calculate necessary information for MutableClosure
2014-09-26 10:22:24 +04:00
Alexander Udalov
7d6da551d1 Minor, inline one of CodegenBinding#registerClassNameForScript 2014-09-26 10:22:24 +04:00
Alexander Udalov
4194f1c418 Minor, simplify old code in ImplementationBodyCodegen 2014-09-26 10:22:24 +04:00
Alexander Udalov
2ba9856a85 Calculate inner class access flags accurately 2014-09-26 10:22:23 +04:00
Alexander Udalov
806d79caba Minor, strip package name from class for script
This is done to be able to construct a FqName of this class. Currently it's not
possible because the name contains '/' and FqName validation fails.

This name is only used for debugging and even the ClassDescriptor is used only
as a key in binding context to store the internal name of the script class
2014-09-26 10:22:23 +04:00
Alexander Udalov
4cb9fbc026 Move CodegenBinding#computeAsmType() to JetTypeMapper, make private 2014-09-26 10:22:23 +04:00
Alexander Udalov
232ab0b065 Refactor when by enum switch codegen
Invoke getAsmType() later, not in the process of annotating the file
2014-09-26 10:22:22 +04:00
Alexander Udalov
d4a845da01 Refactor CodegenBinding#getAsmType()
- make it return the ASM_TYPE slice value and assert it is there
- move all the computation to the separate method "computeAsmType"
- only call getAsmType() in those places where the type must be recorded at
  slice ASM_TYPE, otherwise call JetTypeMapper#mapType(), which will check the
  slice and call computeAsmType
2014-09-26 10:22:22 +04:00
Alexander Udalov
c1125402bd Store FqName in LightClassDataForKotlinClass rather than a String
It was also mistakenly named "jvmInternalName" while in fact it was holding the
result of Type#getClassName() which is not an internal name
2014-09-26 10:22:21 +04:00
Alexander Udalov
c57441b51b Use '$' instead of '-' in package part class names
Otherwise some tools break (e.g. CheckMethodAdapter in ASM, used in generic
signature writer) because they expect class names to be Java identifiers.

Some tests fixed, some will be fixed in future commits
2014-09-26 10:22:20 +04:00
Alexander Udalov
e3876624d8 Minor improvements to inline tests 2014-09-26 10:22:19 +04:00
Ilya Ryzhenkov
fabdc1fd32 Add Typography constants. 2014-09-26 01:55:08 +04:00
Ilya Ryzhenkov
350d446031 Make UTF-8 default for delegated java.lang.util functions. Convert getBytes() to toByteArray() to make it clear of copy operation. 2014-09-26 01:55:07 +04:00
Ilya Ryzhenkov
7616d3e18a Unify charset-related APIs to use Charsets.UTF_8 as default. (Manual merge of PR#491)
Minor cleanup.
2014-09-26 01:55:07 +04:00
Ilya Ryzhenkov
7c61c36746 Rename encoding to charset for consistency 2014-09-26 01:55:06 +04:00
Ilya Ryzhenkov
4cdcadef9f Add 6 standard charsets. 2014-09-26 01:55:06 +04:00
Ilya Ryzhenkov
ea8977c5b5 Minor: code formatting 2014-09-26 01:55:05 +04:00
Ilya Ryzhenkov
3e4cc87c87 Add more tests on streams and move relevant code from old iterators tests. 2014-09-26 01:33:51 +04:00
Ilya Ryzhenkov
c5c1ecf6c0 Improve Streams implementation for performance and validity (based on JMH research) 2014-09-26 01:33:51 +04:00
Zalim Bashorov
5a5c4145f2 JS backend: added tests for reserved words. 2014-09-26 00:57:09 +04:00
Zalim Bashorov
e91e724469 JS backend: mangling JS reserved words. 2014-09-26 00:57:09 +04:00
Zalim Bashorov
ef60a7f776 JS backend: fixed crash when use lambda or local function inside enum method. 2014-09-26 00:57:09 +04:00
Ilya Ryzhenkov
878ebb9575 Add ProGuard exceptions for dokka using Grammar-Kit. 2014-09-25 21:38:32 +04:00
Evgeny Gerashchenko
d44926ffde Made some navigation tests independent on stdlib. 2014-09-25 17:38:15 +04:00
Alexander Udalov
e53aca5496 Minor, fix warnings and formatting 2014-09-25 17:14:59 +04:00
Denis Zharkov
de6a5dd6dc fix KT-5866. Moved classes into inlines package
Also copy-pasted static-initializer of asm.Frame.OPCODES
 because it package-protected
2014-09-25 17:14:59 +04:00
valentin
6e7e13d320 Fixed KT-5826 Keyword completion shouldn't kick in in comments
#KT-5826 Fixed
2014-09-25 17:10:28 +04:00
valentin
b4909cc849 Smart completion: item preference by name works for more cases 2014-09-25 17:10:27 +04:00
Valentin Kipyatkov
0462d152eb Smart completion: prefer items matching by name 2014-09-25 17:10:27 +04:00
Valentin Kipyatkov
56978c4e16 Dropped unused file 2014-09-25 17:10:26 +04:00
Valentin Kipyatkov
7d6542854b Minor code refactoring 2014-09-25 17:10:26 +04:00
Valentin Kipyatkov
f4924299dd Extract method 2014-09-25 17:10:26 +04:00
Valentin Kipyatkov
19fb090f28 Do not autopopup completion in name of generic function or property too 2014-09-25 17:10:25 +04:00
Valentin Kipyatkov
e6ea0537c8 More correct completion testing + fixed small bug in keyword completion 2014-09-25 17:10:25 +04:00
Valentin Kipyatkov
afbd1aeffc KT-4027 No type name completion in an incomplete generic extension function declaration
KT-2940 No completion in the receiver type argument position

 #KT-4027 Fixed
 #KT-2940 Fixed
2014-09-25 17:10:24 +04:00
Valentin Kipyatkov
93d8791df1 No completion auto-popup after dot in float literal (but one test start to fail!) 2014-09-25 17:10:24 +04:00
Valentin Kipyatkov
3fcf0f7340 Fixed KT-5808 Code completion auto-popup does not appear after typing "?."
#KT-5808 Fixed
2014-09-25 17:10:24 +04:00
Valentin Kipyatkov
94c9338e3c Fixed KT-3807 Wrong completion for class/trait with extesion function
#KT-3807 Fixed
2014-09-25 17:10:23 +04:00
Valentin Kipyatkov
e30998d3c1 Moved an utility method 2014-09-25 17:10:23 +04:00
Valentin Kipyatkov
7df65d595c Infix calls supported in smart completion too 2014-09-25 17:10:22 +04:00
Valentin Kipyatkov
2bb553612c Dealing with infix calls in completion
#KT-4846 Fixed
2014-09-25 17:10:22 +04:00
Valentin Kipyatkov
9961a5ff16 Minor 2014-09-25 17:10:21 +04:00
Valentin Kipyatkov
16809bc1c6 Minor 2014-09-25 17:10:21 +04:00
Valentin Kipyatkov
427b3c80bc Filtered out incorrect suggestion of extension methods in smart completion 2014-09-25 17:10:21 +04:00
Valentin Kipyatkov
f43a9968ba Minor code refactorings in TipsManager 2014-09-25 17:10:20 +04:00
Valentin Kipyatkov
726f49b3f8 Converted TipsManager to Kotlin 2014-09-25 17:10:20 +04:00
Valentin Kipyatkov
34aada75eb Fixed KT-5795 Do not suggest member extension functions with wrong implicit reciever
#KT-5795 Fixed
2014-09-25 17:10:19 +04:00
Michael Nedzelsky
6ed57f5e7a JS backend: fix KT-5221 Invalid JS code generated for dec() and inc()
#KT-5221 Fixed
2014-09-25 15:12:44 +04:00
max-kammerer
86d598677d Merge pull request #506 from bintree/max-stack-calc-refining
Refining calculation of max stack size. #KT-5548 Fixed
2014-09-25 10:00:37 +04:00
Natalia Ukhorskaya
0dfc793a45 Merge pull request #515 from dmekhanikov/master
Introduce propertyDelegated method in delegates
2014-09-24 18:50:56 +04:00
Denis Zharkov
7de406991a Refining conditions if method can be optimized 2014-09-24 18:04:33 +04:00
Denis Zharkov
e32f307960 Refining calculation of max stack size. #KT-5548 Fixed
It used for inline and optimization

Added new MethodVisitor's decorator within objectweb.asm package because
there are a lot of usages of package-protected members

Large portion of MaxStackFrameSizeCalculator is carefully copy-pasted from
MethodWriter parts that are relevant to max stack size calculation
2014-09-24 18:04:33 +04:00
Ilya Ryzhenkov
c074b4317e Cleanup concurrent 2014-09-24 17:39:47 +04:00
Ilya Ryzhenkov
3ab1901f06 Rename Serializable test file 2014-09-24 17:39:47 +04:00
Ilya Ryzhenkov
7b77229638 Cleanup Serializable test 2014-09-24 17:39:47 +04:00
Ilya Ryzhenkov
a6d2624807 Cleanup test helpers. 2014-09-24 17:39:47 +04:00
Ilya Ryzhenkov
f2b9b370e1 Clean Dom and Dom tests. 2014-09-24 17:39:46 +04:00
Michael Bogdanov
cde74504d4 Test for obsolete kt5307 2014-09-24 17:12:27 +04:00
Evgeny Gerashchenko
cb58d19e29 Minor. Clarified "compiled file" as "file to compile". 2014-09-24 16:31:48 +04:00
Evgeny Gerashchenko
060796997e Fixed clearing incremental cache for removed source files.
For writing system-dependent paths were used, for deleting were system-independent. That's why cache was not cleared on Windows.
2014-09-24 16:31:48 +04:00
Evgeny Gerashchenko
f9b33c4137 Fixed opening file and not closing it.
This led to impossibility to delete file during incremental compilation.
2014-09-24 16:31:47 +04:00
Evgeny Gerashchenko
b435904d7f Fix: not loading ancestor packages from incremental cache. 2014-09-24 16:31:47 +04:00
Evgeny Gerashchenko
9af1c3e4dc Added automatic backup for debugging incremental compilation. 2014-09-24 16:31:47 +04:00
Denis Zharkov
36b50a25f9 Changed generating logic for named functions
Generate it as a sequence of statements when it's possible
2014-09-24 15:59:49 +04:00
Denis Zharkov
78cde5c740 Generate blocks-statements through CodegenStatementVisitor 2014-09-24 15:59:49 +04:00
Denis Zharkov
4ed744428b Generate substatements as statements too
Preventing pushing on stack redundant Unit instances

 #KT-5667 fixed
2014-09-24 15:51:43 +04:00
Denis Zharkov
081d2cf95c Minor, extracted generateLoopBody 2014-09-24 15:51:43 +04:00
Denis Mekhanikov
c4bfa0edca Introduce propertyDelegated method in delegates 2014-09-24 15:34:12 +04:00
Pavel V. Talanov
9e38d207f2 Add hack for failing js completion tests 2014-09-23 15:56:38 +04:00
Pavel V. Talanov
187a3f0b9f Implement separate service which tracks modification in libraries
ProjectRootModificationTracker tracks root changes but not content modification
2014-09-23 15:56:38 +04:00
Pavel V. Talanov
8a5239f794 Correctly place decompiled kotlin files under LibrarySourceInfo
This check doesn't work for java (and other) decompiled sources, but we assume that we never deal with them in this code
2014-09-23 15:56:37 +04:00
Pavel V. Talanov
8a44325327 Log when libraries cache is dropped because of ProcessCanceledException
Hope it can give insight on how often this happens
2014-09-23 15:56:37 +04:00
Pavel V. Talanov
8d89ac897a Create composite exception tracker when delegating ModuleResolverProvider
Avoid dropping delegate caches when exception (i.e. ProcessCancelled) is thrown in delegating provider
2014-09-23 15:56:36 +04:00
Pavel V. Talanov
68201c3e86 Delegate to global cache when building ModuleResolverProvider for synthetic files 2014-09-23 15:56:36 +04:00
Pavel V. Talanov
5847c3559b Implement ModuleSourceInfo.getDependentModules() 2014-09-23 15:56:35 +04:00
Pavel V. Talanov
bf546c83fb Introduce ModuleSourceInfo 2014-09-23 15:56:35 +04:00
Pavel V. Talanov
fe136b500a Libraries cache drops only on roots change 2014-09-23 15:56:34 +04:00
Pavel V. Talanov
67c9a2323c Synthetic files cache delegates to libraries cache 2014-09-23 15:56:34 +04:00
Pavel V. Talanov
8368689af8 Split global cache in KotlinCacheService into separate caches for libraries and for modules 2014-09-23 15:56:33 +04:00
Pavel V. Talanov
faa9f4bb14 Reuse both storage manager and exception tracker when delegating to ModuleResolverProvider 2014-09-23 15:56:33 +04:00
Pavel V. Talanov
c0657320f5 Allow to provide delegate ModuleResolverProvider when computing resolve sessions for bodies 2014-09-23 15:56:32 +04:00
Pavel V. Talanov
ec02734a30 Minor: extract property in KotlinResolveCache 2014-09-23 15:56:32 +04:00
Pavel V. Talanov
563119ffc7 Minor: fix typo in file name 2014-09-23 15:56:31 +04:00
Pavel V. Talanov
bb87377457 Allow to provide precomputed analyzers when creating ResolverForProject 2014-09-23 15:56:31 +04:00
Michael Nedzelsky
e6a17cbd78 JS backend: tests for KT-5772 2014-09-23 14:50:20 +04:00
Michael Nedzelsky
bdca7e0e37 JS backend: fix KT-5772 wrong code generated when <,<=,>,>= are used with explicit Comparable type
#KT-5772 Fixed
2014-09-23 14:50:17 +04:00
Michael Nedzelsky
1d71016097 JS backend: refactoring support for binary intrinsic operations 2014-09-23 14:50:15 +04:00
Michael Nedzelsky
07a4d0e77e JS backend: convert NumberConversionFIF to Kotlin 2014-09-23 14:50:13 +04:00
Michael Nedzelsky
32f391aa51 JS backend: minor improve in NamePredicate: replace list with set 2014-09-23 14:50:09 +04:00
Alexey Sedunov
a48fbacbd9 Minor: Fix warnings 2014-09-23 12:50:48 +04:00
Alexey Sedunov
da004cf104 Minor: Add @NotNull annotation 2014-09-23 12:50:47 +04:00
Alexey Sedunov
735fd6c626 Move: Fix detection of imported declarations and processing of extension usages
#KT-5787 Fixed
 #KT-4959 Fixed
2014-09-23 12:50:46 +04:00
Natalia Ukhorskaya
b14e979d70 Android tests: skip txt files in box folder 2014-09-23 10:46:40 +04:00
Natalia Ukhorskaya
2b388ed308 Evaluate Expression: fix function call from base class on object with subtype 2014-09-23 10:33:06 +04:00
Nikolay Krasko
b5f738db07 Fix test runner for the case when rerun of failed test filters out some classes completely 2014-09-22 14:02:32 +04:00
Nikolay Krasko
f178356bf0 More memory for dist task 2014-09-22 14:02:04 +04:00
Nikolay Krasko
f5ee68064f Don't generate ValueParameter annotations in light class mode 2014-09-22 14:02:02 +04:00
Michael Bogdanov
432ec31daf Support returns in nested finallies 2014-09-19 17:14:17 +04:00
max.kammerer
9564eaa6fd Support finnaly blocks from inline fun in non-local returns 2014-09-19 17:14:17 +04:00
Evgeny Gerashchenko
309329afd0 Shared incremental compilation tests. For running locally and on teamcity. 2014-09-19 16:43:00 +04:00
Alexander Udalov
90c09762e3 Find usages: only collect those descriptors which resolve to callables
Fix failing test on the buildserver
2014-09-19 16:29:00 +04:00
Alexey Sedunov
5a0b786cb9 Extract Function: Fix syntax error in test 2014-09-19 13:50:38 +04:00
Alexey Sedunov
40761dfc4c Extract Function: Generate named argument for extracted lambda (when necessary) 2014-09-19 13:50:38 +04:00
Alexey Sedunov
6a76ca1066 PSI Pattern Patching: Use precomputed context for matching of substitution parameters 2014-09-19 13:50:37 +04:00
Alexey Sedunov
98eed5cb0e Minor: Remove unused function added in earlier commit 2014-09-19 13:50:36 +04:00
Alexander Udalov
04bb43e907 Fix navigation to data class copy function 2014-09-19 11:45:22 +04:00
Nikolay Krasko
bf7a295ace Regenerate for testCompilationErrorThenFixed test 2014-09-18 20:30:35 +04:00
Nikolay Krasko
2ae1286515 Remove lazy base test - there won't be lazy and eager mode soon 2014-09-18 17:58:25 +04:00
Nikolay Krasko
fbd09911f3 Refactoring: Extract filter for skipping built-ins packages 2014-09-18 17:58:24 +04:00
Nikolay Krasko
e796f88b38 Regenerate test data with constructed descriptors for diagnostics tests 2014-09-18 17:58:23 +04:00
Nikolay Krasko
de61456725 Compare constructed descriptors in diagnostics tests 2014-09-18 17:58:20 +04:00
Evgeny Gerashchenko
2a9005b466 Fixed IAE because of compiler bug. 2014-09-18 16:50:20 +04:00
Evgeny Gerashchenko
853def0a10 Not clearing incremental cache on compilation error. 2014-09-18 16:50:20 +04:00
Zalim Bashorov
040d1693e8 Minor: revert semicolons after package declaration for java parts inside kt file. 2014-09-18 16:00:45 +04:00
Michael Nedzelsky
1b60f39959 JS backend: test for KT-4381: JS: fails to iterate over Double range
#KT-4381 obsolete
2014-09-18 15:01:11 +04:00
Alexey Sedunov
741e5f61e9 Extract Function: Implement duplicate search 2014-09-18 13:28:30 +04:00
Alexey Sedunov
03e2b4d516 PSI Pattern Matching: Add support of weak matching 2014-09-18 13:28:29 +04:00
Alexey Sedunov
07a257b1fe Drop JetPsiMatcher class and use JetPsiUnifier instead. Drop AbstractJetPsiMatcherTest 2014-09-18 13:28:28 +04:00
Alexey Sedunov
855ed81c11 Introduce Variable: Use expression unifier to find duplicates 2014-09-18 13:28:27 +04:00
Alexey Sedunov
f1c18d0e3f PSI Pattern Matching: Add equivalence tests for JetPsiUnifier 2014-09-18 13:28:26 +04:00
Alexey Sedunov
a3758f9fa3 PSI Pattern Matching: Implement expression unifier 2014-09-18 13:28:24 +04:00
Alexander Udalov
c0a8e8a4fc Fix safe call on a static method in JVM back-end
#KT-5796 Fixed
2014-09-18 11:13:30 +04:00
Alexander Udalov
9434114c45 Make DescriptorRenderer escape names with dollars and other characters
#KT-5791 Fixed
2014-09-18 10:42:48 +04:00
Alexander Udalov
483232a3e5 Minor, add test for obsolete issue
#KT-5159 Obsolete
2014-09-17 21:20:57 +04:00
Alexander Udalov
af01c0ff94 Update to IDEA EAP 138.2210 2014-09-17 21:19:09 +04:00
Zalim Bashorov
08c3bb35b2 Merge pull request #514 from chashnikov/rr/nik
JS run configuration: use default implementation of ExecutionResult instead of implementing...
2014-09-17 18:56:26 +04:00
nik
92e962eced JS run configuration: use default implementation instead of implementing interface from IDEA API to simplify code and avoid compatibility problems 2014-09-17 18:06:32 +04:00
Natalia Ukhorskaya
88a2612348 Regenerate tests 2014-09-17 14:21:34 +04:00
Natalia Ukhorskaya
3dcfae4a81 Debugger: delegated property should be visible in debugger
#KT-4699 In Progress
 #KT-3582 Fixed
2014-09-17 13:59:53 +04:00
Natalia Ukhorskaya
655682ac97 Move regression tests from stdlib to compiler
#KT-5770 FIxed
2014-09-17 13:59:52 +04:00
Valentin Kipyatkov
d5f509580f Minor fix in completion 2014-09-17 13:24:56 +04:00
Valentin Kipyatkov
a4613ec4a0 Changed completion logic: include non-imported declarations on second press even when prefix is empty 2014-09-17 13:24:56 +04:00
Valentin Kipyatkov
75f7f296aa Non-imported extension functions and properties in smart completion + adding import on completing of non-imported property 2014-09-17 13:24:56 +04:00
3268 changed files with 104346 additions and 6834 deletions

2
.idea/ant.xml generated
View File

@@ -4,7 +4,7 @@
<buildFile url="file://$PROJECT_DIR$/grammar/buildGrammarLexer.xml" />
<buildFile url="file://$PROJECT_DIR$/compiler/frontend/buildLexer.xml" />
<buildFile url="file://$PROJECT_DIR$/build.xml">
<maximumHeapSize value="512" />
<maximumHeapSize value="1024" />
</buildFile>
<buildFile url="file://$PROJECT_DIR$/update_dependencies.xml" />
<buildFile url="file://$PROJECT_DIR$/TeamCityBuild.xml">

View File

@@ -0,0 +1,18 @@
<component name="ArtifactManager">
<artifact name="KotlinAndroidExtensionsPlugin">
<output-path>$PROJECT_DIR$/out/artifacts/KotlinAndroidExtensionsPlugin</output-path>
<root id="root">
<element id="directory" name="lib">
<element id="archive" name="kotlin-android-extensions-plugin.jar">
<element id="module-output" name="android-compiler-plugin" />
<element id="module-output" name="android-idea-plugin" />
</element>
<element id="directory" name="jps">
<element id="archive" name="kotlin-android-extensions-jps.jar">
<element id="module-output" name="android-jps-plugin" />
</element>
</element>
</element>
</root>
</artifact>
</component>

View File

@@ -31,6 +31,8 @@
<element id="module-output" name="eval4j" />
<element id="module-output" name="idea-analysis" />
<element id="module-output" name="ide-lazy-resolve" />
<element id="module-output" name="android-compiler-plugin" />
<element id="module-output" name="android-idea-plugin" />
</element>
<element id="library" level="project" name="javax.inject" />
<element id="directory" name="jps">

View File

@@ -3,9 +3,15 @@
<words>
<w>accessors</w>
<w>goto</w>
<w>gradle</w>
<w>kdoc</w>
<w>kompiler</w>
<w>memoize</w>
<w>memoized</w>
<w>multiline</w>
<w>preload</w>
<w>preloader</w>
<w>preloading</w>
<w>preprocess</w>
<w>redeclarations</w>
<w>subclassed</w>

38
.idea/libraries/android.xml generated Normal file
View File

@@ -0,0 +1,38 @@
<component name="libraryTable">
<library name="android">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/android.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/jps/android-jps-plugin.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/android-common.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/jps/android-gradle-jps.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/manifest-merger.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/builder-model-0.12.0.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/commons-compress-1.0.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/layoutlib-api.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/common.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/sdklib.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/resources_en.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/sdk-tools.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/jarutils.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/lib/android-rt.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/rt/src" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/gen" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/src" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/common/src" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/common/testSrc" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/testSrc" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/ultimate/src" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/guiTestSrc" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/jps-plugin/src" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/jps-plugin/testSrc" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/android-gradle-jps/src" />
<root url="jar://$PROJECT_DIR$/ideaSDK/plugins/android/android-src.zip!/android-gradle-jps/testSrc" />
</SOURCES>
</library>
</component>

9
.idea/libraries/android_tests.xml generated Normal file
View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="android_tests">
<CLASSES>
<root url="jar://$PROJECT_DIR$/dependencies/android_tests.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

4
.idea/modules.xml generated
View File

@@ -3,6 +3,9 @@
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Kotlin.iml" filepath="$PROJECT_DIR$/Kotlin.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/android-compiler-plugin/android-compiler-plugin.iml" filepath="$PROJECT_DIR$/plugins/android-compiler-plugin/android-compiler-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/android-idea-plugin/android-idea-plugin.iml" filepath="$PROJECT_DIR$/plugins/android-idea-plugin/android-idea-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/android-jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/android-jps-plugin/android-jps-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/android-studio/android-studio.iml" filepath="$PROJECT_DIR$/android-studio/android-studio.iml" group="ide" />
<module fileurl="file://$PROJECT_DIR$/compiler/android-tests/android-tests.iml" filepath="$PROJECT_DIR$/compiler/android-tests/android-tests.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/backend/backend.iml" filepath="$PROJECT_DIR$/compiler/backend/backend.iml" group="compiler/java" />
@@ -37,6 +40,7 @@
<module fileurl="file://$PROJECT_DIR$/js/js.tests/js.tests.iml" filepath="$PROJECT_DIR$/js/js.tests/js.tests.iml" group="compiler/js" />
<module fileurl="file://$PROJECT_DIR$/js/js.translator/js.translator.iml" filepath="$PROJECT_DIR$/js/js.translator/js.translator.iml" group="compiler/js" />
<module fileurl="file://$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" filepath="$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" group="ide/jps" />
<module fileurl="file://$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" filepath="$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/preloader.iml" filepath="$PROJECT_DIR$/compiler/preloader/preloader.iml" group="compiler/cli" />
<module fileurl="file://$PROJECT_DIR$/core/reflection/reflection.iml" filepath="$PROJECT_DIR$/core/reflection/reflection.iml" group="core" />
<module fileurl="file://$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" filepath="$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" group="core" />

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Android Studio" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<option name="VM_PARAMETERS" value="-Didea.paths.selector=AndroidStudioPreview -Didea.platform.prefix=AndroidStudio -Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=450m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system -Didea.config.path=../config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin" />
<option name="VM_PARAMETERS" value="-Didea.paths.selector=AndroidStudioPreview -Didea.platform.prefix=AndroidStudio -Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=450m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/android-studio/sdk/bin" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="IDEA" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<option name="VM_PARAMETERS" value="-Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=450m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true" />
<option name="VM_PARAMETERS" value="-Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=450m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin:$PROJECT_DIR$/out/artifacts/KotlinAndroidExtensionsPlugin -Dkotlin.internal.mode.enabled=true" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="IDEA (No ProcessCanceledException)" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
<option name="VM_PARAMETERS" value="-Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=250m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Didea.ProcessCanceledException=disabled -Dkotlin.internal.mode.enabled=true" />
<option name="VM_PARAMETERS" value="-Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=250m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin:$PROJECT_DIR$/out/artifacts/KotlinAndroidExtensionsPlugin -Didea.ProcessCanceledException=disabled -Dkotlin.internal.mode.enabled=true" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />

View File

@@ -0,0 +1,35 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Incremental Compilation Tests" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="jps-plugin" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
<option name="PACKAGE_NAME" value="org.jetbrains.jet.jps.build" />
<option name="MAIN_CLASS_NAME" value="org.jetbrains.jet.jps.build.IncrementalJpsTestGenerated" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Xmx512m -XX:MaxPermSize=320m -Dkotlin.incremental.compilation=true" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs>
<env name="kotlin.tests.actually.compile" value="false" />
</envs>
<patterns />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="" />
<option name="TRANSPORT" value="0" />
<option name="LOCAL" value="true" />
</RunnerSettings>
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/build.xml" target="dist_quick_compiler_only" />
</method>
</configuration>
</component>

View File

@@ -27,6 +27,7 @@
<patterns>
<pattern testClass="org.jetbrains.jet.completion.JvmSmartCompletionTestGenerated" />
<pattern testClass="org.jetbrains.jet.completion.handlers.SmartCompletionHandlerTestGenerated" />
<pattern testClass="org.jetbrains.jet.completion.handlers.SmartCompletionMultifileHandlerTest" />
</patterns>
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="" />

View File

@@ -8,7 +8,9 @@
<excludeFolder url="file://$MODULE_DIR$/android.tests.dependencies" />
<excludeFolder url="file://$MODULE_DIR$/dependencies" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
<excludeFolder url="file://$MODULE_DIR$/ideaSDK/androidSDK" />
<excludeFolder url="file://$MODULE_DIR$/ideaSDK/config" />
<excludeFolder url="file://$MODULE_DIR$/ideaSDK/config-idea" />
<excludeFolder url="file://$MODULE_DIR$/ideaSDK/system" />
<excludeFolder url="file://$MODULE_DIR$/ideaSDK/system-idea" />
<excludeFolder url="file://$MODULE_DIR$/libraries/.idea" />

View File

@@ -6,6 +6,10 @@
name='com.intellij.codeInsight.NullableNotNullManager com.intellij.codeInsight.NullableNotNullManager getInstance(com.intellij.openapi.project.Project)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.PsiEquivalenceUtil com.intellij.psi.PsiElement[] getFilteredChildren(com.intellij.psi.PsiElement, com.intellij.openapi.util.Condition&lt;com.intellij.psi.PsiElement&gt;, boolean)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.codeInsight.NullableNotNullManager java.util.List&lt;java.lang.String&gt; getNotNulls()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>

View File

@@ -0,0 +1,10 @@
<root>
<item
name='com.intellij.codeInsight.folding.CodeFoldingManager com.intellij.codeInsight.folding.CodeFoldingManager getInstance(com.intellij.openapi.project.Project)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.folding.CodeFoldingManager com.intellij.openapi.editor.FoldRegion[] getFoldRegionsAtOffset(com.intellij.openapi.editor.Editor, int)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,10 @@
<root>
<item
name='com.intellij.codeInsight.folding.impl.CodeFoldingManagerImpl com.intellij.openapi.editor.FoldRegion[] getFoldRegionsAtOffset(com.intellij.openapi.editor.Editor, int)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.folding.impl.FoldingUtil com.intellij.openapi.editor.FoldRegion[] getFoldRegionsAtOffset(com.intellij.openapi.editor.Editor, int)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,6 @@
<root>
<item
name='com.intellij.codeInsight.highlighting.HighlightManager com.intellij.codeInsight.highlighting.HighlightManager getInstance(com.intellij.openapi.project.Project)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,6 @@
<root>
<item
name='com.intellij.debugger.ui.impl.watch.NodeManagerImpl java.util.Comparator&lt;com.intellij.debugger.ui.tree.DebuggerTreeNode&gt; getNodeComparator()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,10 @@
<root>
<item
name='com.intellij.debugger.ui.tree.NodeManager com.intellij.debugger.ui.tree.DebuggerTreeNode createMessageNode(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.debugger.ui.tree.NodeManager com.intellij.debugger.ui.tree.DebuggerTreeNode createNode(com.intellij.debugger.ui.tree.NodeDescriptor, com.intellij.debugger.engine.evaluation.EvaluationContext)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,10 @@
<root>
<item
name='com.intellij.debugger.ui.tree.render.ChildrenRenderer void buildChildren(com.sun.jdi.Value, com.intellij.debugger.ui.tree.render.ChildrenBuilder, com.intellij.debugger.engine.evaluation.EvaluationContext) 1'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.debugger.ui.tree.render.ChildrenRenderer void buildChildren(com.sun.jdi.Value, com.intellij.debugger.ui.tree.render.ChildrenBuilder, com.intellij.debugger.engine.evaluation.EvaluationContext) 2'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -1,4 +1,7 @@
<root>
<item name='com.intellij.lang.ASTNode com.intellij.lang.ASTNode[] getChildren(com.intellij.psi.tree.TokenSet)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.lang.ASTNode java.lang.String getText()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>

View File

@@ -26,4 +26,8 @@
name='com.intellij.openapi.roots.ProjectFileIndex.SERVICE com.intellij.openapi.roots.ProjectFileIndex getInstance(com.intellij.openapi.project.Project)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.openapi.roots.ProjectRootModificationTracker com.intellij.openapi.roots.ProjectRootModificationTracker getInstance(com.intellij.openapi.project.Project)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,8 @@
<root>
<item name='com.intellij.psi.codeStyle.NameUtil java.lang.String[] nameToWords(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.psi.codeStyle.NameUtil java.util.List&lt;java.lang.String&gt; nameToWordsLowerCase(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -0,0 +1,8 @@
<root>
<item name='com.intellij.psi.impl.source.tree.CompositeElement com.intellij.lang.ASTNode[] getChildren(com.intellij.psi.tree.TokenSet)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.psi.impl.source.tree.LeafElement com.intellij.lang.ASTNode[] getChildren(com.intellij.psi.tree.TokenSet)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -10,7 +10,10 @@
name='com.intellij.psi.stubs.AbstractStubIndex java.util.Collection&lt;Psi&gt; get(Key, com.intellij.openapi.project.Project, com.intellij.psi.search.GlobalSearchScope) 2'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
<item name='com.intellij.psi.stubs.StubIndex com.intellij.psi.stubs.StubIndex getInstance()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.psi.stubs.StubIndex java.util.Collection&lt;Psi&gt; get(com.intellij.psi.stubs.StubIndexKey&lt;Key,Psi&gt;, Key, com.intellij.openapi.project.Project, com.intellij.psi.search.GlobalSearchScope)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>

View File

@@ -3,7 +3,11 @@
name='com.intellij.psi.util.CachedValueProvider.Result com.intellij.psi.util.CachedValueProvider.Result&lt;T&gt; create(T, java.lang.Object...)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
<item
name='com.intellij.psi.util.CachedValueProvider.Result com.intellij.psi.util.CachedValueProvider.Result&lt;T&gt; create(T, java.util.Collection&lt;?&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.psi.util.CachedValuesManager com.intellij.psi.util.CachedValue&lt;T&gt; createCachedValue(com.intellij.psi.util.CachedValueProvider&lt;T&gt;, boolean)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>

View File

@@ -8,7 +8,10 @@
<item name='com.intellij.refactoring.BaseRefactoringProcessor myProject'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
<item name='com.intellij.refactoring.BaseRefactoringProcessor void performRefactoring(com.intellij.usageView.UsageInfo[]) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException java.util.Collection&lt;java.lang.String&gt; getMessages()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>

View File

@@ -0,0 +1,6 @@
<root>
<item
name='com.intellij.refactoring.move.moveClassesOrPackages.CommonMoveUtil com.intellij.refactoring.util.NonCodeUsageInfo[] retargetUsages(com.intellij.usageView.UsageInfo[], java.util.Map&lt;com.intellij.psi.PsiElement,com.intellij.psi.PsiElement&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>

View File

@@ -14,10 +14,16 @@
<item name='com.sun.jdi.Method java.util.List&lt;com.sun.jdi.Type&gt; argumentTypes()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.ReferenceType com.sun.jdi.ClassObjectReference classObject()'>
<item name='com.sun.jdi.ObjectReference com.sun.jdi.ReferenceType referenceType()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.ReferenceType com.sun.jdi.ClassObjectReference classObject()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.ReferenceType java.util.List&lt;com.sun.jdi.Location&gt; allLineLocations()'>
<item name='com.sun.jdi.ReferenceType java.util.List&lt;com.sun.jdi.Field&gt; allFields()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.ReferenceType java.util.List&lt;com.sun.jdi.Location&gt; allLineLocations()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.ReferenceType java.util.List&lt;com.sun.jdi.Method&gt; methodsByName(java.lang.String, java.lang.String)'>
@@ -41,7 +47,10 @@
<item name='com.sun.jdi.TypeComponent com.sun.jdi.ReferenceType declaringType()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.Value com.sun.jdi.Type type()'>
<item name='com.sun.jdi.TypeComponent java.lang.String name()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.Value com.sun.jdi.Type type()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.sun.jdi.VirtualMachine com.sun.jdi.BooleanValue mirrorOf(boolean)'>

View File

@@ -63,6 +63,7 @@
<include name="core/serialization/src"/>
<include name="core/descriptor.loader.java/src"/>
<include name="compiler/frontend.java/src"/>
<include name="compiler/frontend.android/src"/>
<include name="core/serialization.java/src"/>
<include name="compiler/backend-common/src"/>
<include name="compiler/backend/src"/>
@@ -86,6 +87,7 @@
<include name="serialization/**"/>
<include name="descriptor.loader.java/**"/>
<include name="frontend.java/**"/>
<include name="frontend.android/**"/>
<include name="serialization.java/**"/>
<include name="backend/**"/>
<include name="backend-common/**"/>
@@ -251,6 +253,7 @@
<file name="kotlin_lib_ecma5.js"/>
<file name="kotlin_lib.js"/>
<file name="maps.js"/>
<file name="long.js"/>
</sources>
</closure-compiler>
@@ -472,8 +475,12 @@
public protected *;
}
# for kdoc
# for kdoc & dokka
-keep class com.intellij.openapi.util.TextRange { *; }
-keep class com.intellij.lang.impl.PsiBuilderImpl* {
public protected *;
}
-keep class com.intellij.openapi.util.text.StringHash { *; }
-keepclassmembers enum * {
public static **[] values();

View File

@@ -18,6 +18,7 @@ package org.jetbrains.jet.compiler.android;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.UsefulTestCase;
import org.jetbrains.annotations.NotNull;
@@ -31,6 +32,7 @@ import org.jetbrains.jet.codegen.GenerationUtils;
import org.jetbrains.jet.compiler.PathManager;
import org.jetbrains.jet.generators.tests.generator.TestGeneratorUtil;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.utils.Printer;
import org.junit.Assert;
@@ -197,6 +199,9 @@ public class CodegenTestsOnAndroidGenerator extends UsefulTestCase {
processFiles(printer, listFiles, holderFull, holderMock);
}
}
else if (!FileUtilRt.getExtension(file.getName()).equals(JetFileType.INSTANCE.getDefaultExtension())) {
// skip non kotlin files
}
else {
String text = FileUtil.loadFile(file, true);

View File

@@ -53,6 +53,7 @@ public class SpecialFiles {
filesCompiledWithoutStdLib.add("kt4265.kt"); // OVERLOAD_RESOLUTION_AMBIGUITY
filesCompiledWithoutStdLib.add("realStringRepeat.kt"); // OVERLOAD_RESOLUTION_AMBIGUITY
filesCompiledWithoutStdLib.add("kt2395.kt"); // With MOCK_JDK
filesCompiledWithoutStdLib.add("useAnonymousObjectAsIterator.kt"); // OVERLOAD_RESOLUTION_AMBIGUITY
}
private static void fillExcludedFiles() {

View File

@@ -40,10 +40,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
@@ -243,7 +240,6 @@ public class AsmUtil {
return NO_FLAG_PACKAGE_PRIVATE;
}
public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) {
if (isDeclarationInsideInlineFunction(descriptor)) {
return ACC_PUBLIC;
@@ -251,7 +247,7 @@ public class AsmUtil {
return NO_FLAG_PACKAGE_PRIVATE;
}
public static boolean isDeclarationInsideInlineFunction(@NotNull ClassDescriptor descriptor) {
private static boolean isDeclarationInsideInlineFunction(@NotNull ClassDescriptor descriptor) {
//NB: constructor context couldn't be inline
DeclarationDescriptor parentDeclaration = descriptor.getContainingDeclaration();
if (parentDeclaration instanceof SimpleFunctionDescriptor &&
@@ -261,6 +257,31 @@ public class AsmUtil {
return false;
}
public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) {
return getVisibilityAccessFlag(innerClass) |
innerAccessFlagsForModalityAndKind(innerClass) |
(innerClass.isInner() ? 0 : ACC_STATIC);
}
private static int innerAccessFlagsForModalityAndKind(@NotNull ClassDescriptor innerClass) {
switch (innerClass.getKind()) {
case TRAIT:
return ACC_ABSTRACT | ACC_INTERFACE;
case ENUM_CLASS:
return ACC_FINAL | ACC_ENUM;
case ANNOTATION_CLASS:
return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE;
default:
if (innerClass.getModality() == Modality.FINAL) {
return ACC_FINAL;
}
else if (innerClass.getModality() == Modality.ABSTRACT) {
return ACC_ABSTRACT;
}
}
return 0;
}
public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) {
if (descriptor instanceof PropertyAccessorDescriptor) {
return KotlinBuiltIns.getInstance().isDeprecated(descriptor)
@@ -705,12 +726,12 @@ public class AsmUtil {
return expectedType;
}
public static void pop(@NotNull InstructionAdapter v, @NotNull Type type) {
public static void pop(@NotNull MethodVisitor v, @NotNull Type type) {
if (type.getSize() == 2) {
v.pop2();
v.visitInsn(Opcodes.POP2);
}
else {
v.pop();
v.visitInsn(Opcodes.POP);
}
}
@@ -806,11 +827,6 @@ public class AsmUtil {
}
}
@NotNull
public static Type getArrayOf(@NotNull String internalClassName) {
return Type.getType("[L" + internalClassName + ";");
}
public static int getReceiverIndex(@NotNull CodegenContext context, @NotNull CallableMemberDescriptor descriptor) {
OwnerKind kind = context.getContextKind();
//Trait always should have this descriptor

View File

@@ -45,4 +45,9 @@ public class CodegenStatementVisitor extends JetVisitor<StackValue, StackValue>
public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue data) {
return codegen.generateWhenExpression(expression, true);
}
@Override
public StackValue visitBlockExpression(@NotNull JetBlockExpression expression, StackValue data) {
return codegen.generateBlock(expression, true);
}
}

View File

@@ -31,6 +31,7 @@ import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.binding.MutableClosure;
import org.jetbrains.jet.codegen.context.*;
import org.jetbrains.jet.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.jet.codegen.inline.InlineCodegen;
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
import org.jetbrains.jet.codegen.inline.NameGenerator;
@@ -261,7 +262,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
public void gen(JetElement expr, Type type) {
StackValue value = gen(expr);
StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr);
value.put(type, v);
}
@@ -408,10 +409,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
StackValue conditionValue = gen(expression.getCondition());
conditionValue.condJump(end, true, v);
JetExpression body = expression.getBody();
if (body != null) {
gen(body, Type.VOID_TYPE);
}
generateLoopBody(expression.getBody());
v.goTo(condition);
@@ -446,7 +444,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
statements.addAll(doWhileStatements);
statements.add(condition);
conditionValue = generateBlock(statements, true, continueLabel);
conditionValue = generateBlock(statements, false, continueLabel);
}
else {
if (body != null) {
@@ -633,10 +631,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
protected abstract void increment(@NotNull Label loopExit);
public void body() {
JetExpression body = forExpression.getBody();
if (body != null) {
gen(body, Type.VOID_TYPE);
}
generateLoopBody(forExpression.getBody());
}
private void scheduleLeaveVariable(Runnable runnable) {
@@ -676,6 +671,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
private void generateLoopBody(@Nullable JetExpression body) {
if (body != null) {
gen(body, Type.VOID_TYPE);
}
}
private class IteratorForLoopGenerator extends AbstractForLoopGenerator {
private int iteratorVarIndex;
@@ -1277,10 +1278,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitBlockExpression(@NotNull JetBlockExpression expression, StackValue receiver) {
List<JetElement> statements = expression.getStatements();
JetType unitType = KotlinBuiltIns.getInstance().getUnitType();
boolean lastStatementIsExpression = !unitType.equals(bindingContext.get(EXPRESSION_TYPE, expression));
return generateBlock(statements, lastStatementIsExpression);
return generateBlock(expression, false);
}
@Override
@@ -1413,11 +1411,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) {
return generateBlock(statements, lastStatementIsExpression, null);
/* package */ StackValue generateBlock(@NotNull JetBlockExpression expression, boolean isStatement) {
return generateBlock(expression.getStatements(), isStatement, null);
}
private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression, Label labelBeforeLastExpression) {
private StackValue generateBlock(List<JetElement> statements, boolean isStatement, Label labelBeforeLastExpression) {
Label blockEnd = new Label();
List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList();
@@ -1449,7 +1447,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks);
}
boolean isExpression = !iterator.hasNext() && lastStatementIsExpression;
boolean isExpression = !iterator.hasNext() && !isStatement;
if (isExpression && labelBeforeLastExpression != null) {
v.mark(labelBeforeLastExpression);
}
@@ -1671,10 +1669,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
public void returnExpression(JetExpression expr) {
StackValue lastValue = gen(expr);
boolean isBlockedNamedFunction = expr instanceof JetBlockExpression && expr.getParent() instanceof JetNamedFunction;
// If generating body for named block-bodied function, generate it as sequence of statements
gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType);
// If it does not end with return we should return something
// because if we don't there can be VerifyError (specific cases with Nothing-typed expressions)
if (!endsWithReturn(expr)) {
lastValue.put(returnType, v);
if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) {
StackValue.none().put(returnType, v);
}
v.areturn(returnType);
}
}
@@ -1725,6 +1731,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.OBJECT$.getInstances(state.getProject())) {
StackValue result = extension.apply(receiver, resolvedCall, new ExpressionCodegenExtension.Context(typeMapper, v));
if (result != null) return result;
}
boolean directToField =
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
JetExpression r = getReceiverForSelector(expression);
@@ -1754,8 +1766,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.field(type, type, descriptor.getName().asString(), true);
}
ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor();
assert classObjectDescriptor != null : "Class object is not found for " + descriptor;
return StackValue.singleton(classObjectDescriptor, typeMapper);
if (classObjectDescriptor != null) {
return StackValue.singleton(classObjectDescriptor, typeMapper);
}
return StackValue.none();
}
if (descriptor instanceof TypeParameterDescriptor) {

View File

@@ -148,7 +148,9 @@ public class FunctionCodegen extends ParentCodegenAware {
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature);
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature);
}
generateBridges(functionDescriptor);

View File

@@ -285,48 +285,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
// TODO: proper access
int innerClassAccess = getVisibilityAccessFlag(innerClass);
if (innerClass.getModality() == Modality.FINAL) {
innerClassAccess |= ACC_FINAL;
}
else if (innerClass.getModality() == Modality.ABSTRACT) {
innerClassAccess |= ACC_ABSTRACT;
}
if (innerClass.getKind() == ClassKind.TRAIT) {
innerClassAccess |= ACC_INTERFACE;
}
else if (innerClass.getKind() == ClassKind.ENUM_CLASS) {
innerClassAccess |= ACC_ENUM;
}
if (!innerClass.isInner()) {
innerClassAccess |= ACC_STATIC;
}
// TODO: cache internal names
DeclarationDescriptor containing = innerClass.getContainingDeclaration();
String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null;
String outerClassInternalName =
containing instanceof ClassDescriptor ? typeMapper.mapClass((ClassDescriptor) containing).getInternalName() : null;
String innerClassInternalName;
String innerName;
String innerName = isClassObject(innerClass)
? JvmAbi.CLASS_OBJECT_CLASS_NAME
: innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
if (isClassObject(innerClass)) {
innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME;
innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
}
else {
innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
innerClassInternalName = getInternalNameForImpl(innerClass);
}
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess);
}
@NotNull
private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) {
return typeMapper.mapClass(descriptor).getInternalName();
String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
}
@NotNull

View File

@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.Stack;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
@@ -67,10 +66,6 @@ public class JvmCodegenUtil {
return closure.getCaptureThis() == null && closure.getCaptureReceiverType() == null && closure.getCaptureVariables().isEmpty();
}
public static <T> T peekFromStack(Stack<T> stack) {
return stack.empty() ? null : stack.peek();
}
private static boolean isCallInsideSameClassAsDeclared(@NotNull CallableMemberDescriptor descriptor, @NotNull CodegenContext context) {
boolean isFakeOverride = descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
boolean isDelegate = descriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION;

View File

@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -247,8 +248,16 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
type = boxType(type);
}
codegen.gen(initializer, type);
propValue.store(type, codegen.v);
ResolvedCall<FunctionDescriptor> pdResolvedCall =
bindingContext.get(BindingContext.DELEGATED_PROPERTY_PD_RESOLVED_CALL, propertyDescriptor);
if (pdResolvedCall != null) {
int index = PropertyCodegen.indexOfDelegatedProperty(property);
StackValue lastValue = PropertyCodegen.invokeDelegatedPropertyConventionMethod(propertyDescriptor, codegen,
state.getTypeMapper(), pdResolvedCall, index, 0);
lastValue.put(Type.VOID_TYPE, codegen.v);
}
}
private boolean shouldInitializeProperty(@NotNull JetProperty property) {

View File

@@ -344,7 +344,7 @@ public class PropertyCodegen {
functionCodegen.generateMethod(OtherOrigin(accessor != null ? accessor : p, accessorDescriptor), signature, accessorDescriptor, strategy);
}
private static int indexOfDelegatedProperty(@NotNull JetProperty property) {
public static int indexOfDelegatedProperty(@NotNull JetProperty property) {
PsiElement parent = property.getParent();
JetDeclarationContainer container;
if (parent instanceof JetClassBody) {
@@ -409,6 +409,46 @@ public class PropertyCodegen {
}
}
public static StackValue invokeDelegatedPropertyConventionMethod(
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull ExpressionCodegen codegen,
@NotNull JetTypeMapper typeMapper,
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
final int indexInPropertyMetadataArray,
int propertyMetadataArgumentIndex
) {
if (codegen.getContext().getContextKind() != OwnerKind.PACKAGE) {
codegen.v.load(0, OBJECT_TYPE);
}
CodegenContext<? extends ClassOrPackageFragmentDescriptor> ownerContext = codegen.getContext().getClassOrPackageParentContext();
final Type owner;
if (ownerContext instanceof ClassContext) {
owner = typeMapper.mapClass(((ClassContext) ownerContext).getContextDescriptor());
}
else if (ownerContext instanceof PackageContext) {
owner = ((PackageContext) ownerContext).getPackagePartType();
}
else {
throw new UnsupportedOperationException("Unknown context: " + ownerContext);
}
codegen.tempVariables.put(
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),
new StackValue(PROPERTY_METADATA_TYPE) {
@Override
public void put(Type type, InstructionAdapter v) {
v.getstatic(owner.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
v.iconst(indexInPropertyMetadataArray);
StackValue.arrayElement(PROPERTY_METADATA_TYPE).put(type, v);
}
}
);
StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
return codegen.invokeFunction(resolvedCall, delegatedProperty);
}
private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
private final int index;
@@ -426,37 +466,8 @@ public class PropertyCodegen {
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, callableDescriptor);
assert resolvedCall != null : "Resolve call should be recorded for delegate call " + signature.toString();
if (codegen.getContext().getContextKind() != OwnerKind.PACKAGE) {
v.load(0, OBJECT_TYPE);
}
CodegenContext<? extends ClassOrPackageFragmentDescriptor> ownerContext = codegen.getContext().getClassOrPackageParentContext();
final Type owner;
if (ownerContext instanceof ClassContext) {
owner = state.getTypeMapper().mapClass(((ClassContext) ownerContext).getContextDescriptor());
}
else if (ownerContext instanceof PackageContext) {
owner = ((PackageContext) ownerContext).getPackagePartType();
}
else {
throw new UnsupportedOperationException("Unknown context: " + ownerContext);
}
codegen.tempVariables.put(
resolvedCall.getCall().getValueArguments().get(1).asElement(),
new StackValue(PROPERTY_METADATA_TYPE) {
@Override
public void put(Type type, InstructionAdapter v) {
v.getstatic(owner.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
v.iconst(index);
StackValue.arrayElement(PROPERTY_METADATA_TYPE).put(type, v);
}
}
);
StackValue delegatedProperty = codegen.intermediateValueForProperty(callableDescriptor.getCorrespondingProperty(), true, null);
StackValue lastValue = codegen.invokeFunction(resolvedCall, delegatedProperty);
StackValue lastValue = invokeDelegatedPropertyConventionMethod(callableDescriptor.getCorrespondingProperty(),
codegen, state.getTypeMapper(), resolvedCall, index, 1);
Type asmType = signature.getReturnType();
lastValue.put(asmType, v);
v.areturn(asmType);

View File

@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.util.ArrayUtil;
import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.context.CodegenContext;
@@ -38,7 +39,8 @@ import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.method;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForScriptDescriptor;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
@@ -52,17 +54,17 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
@NotNull GenerationState state,
@NotNull CodegenContext parentContext
) {
ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, declaration);
BindingContext bindingContext = state.getBindingContext();
ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration);
assert scriptDescriptor != null;
ClassDescriptor classDescriptorForScript = state.getBindingContext().get(CLASS_FOR_SCRIPT, scriptDescriptor);
ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
assert classDescriptorForScript != null;
Type className = state.getBindingContext().get(ASM_TYPE, classDescriptorForScript);
assert className != null;
Type classType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
ClassBuilder builder = state.getFactory().newVisitor(OtherOrigin(declaration, classDescriptorForScript),
className, declaration.getContainingFile());
classType, declaration.getContainingFile());
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
ScriptContext scriptContext = parentContext.intoScript(
scriptDescriptor,
@@ -90,8 +92,7 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
@Override
protected void generateDeclaration() {
Type classType = bindingContext.get(ASM_TYPE, context.getContextDescriptor());
assert classType != null;
Type classType = typeMapper.mapClass(context.getContextDescriptor());
v.defineClass(scriptDeclaration,
V1_6,
@@ -99,7 +100,7 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
classType.getInternalName(),
null,
"java/lang/Object",
new String[0]);
ArrayUtil.EMPTY_STRING_ARRAY);
generateReflectionObjectField(state, classType, v, method("kClassFromKotlin", K_CLASS_IMPL_TYPE, getType(Class.class)),
JvmAbi.KOTLIN_CLASS_FIELD_NAME, createOrGetClInitCodegen().v);
@@ -124,6 +125,7 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
@NotNull ClassBuilder classBuilder,
@NotNull final MethodContext methodContext
) {
//noinspection ConstantConditions
Type blockType = typeMapper.mapType(scriptDescriptor.getScriptCodeDescriptor().getReturnType());
PropertyDescriptor scriptResultProperty = scriptDescriptor.getScriptResultProperty();
@@ -142,8 +144,7 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
final InstructionAdapter iv = new InstructionAdapter(mv);
Type classType = bindingContext.get(ASM_TYPE, classDescriptorForScript);
assert classType != null;
Type classType = typeMapper.mapType(classDescriptorForScript);
iv.load(0, classType);
iv.invokespecial("java/lang/Object", "<init>", "()V", false);

View File

@@ -933,7 +933,8 @@ public abstract class StackValue {
}
}
public static Type sharedTypeForType(Type type) {
@NotNull
public static Type sharedTypeForType(@NotNull Type type) {
switch (type.getSort()) {
case Type.OBJECT:
case Type.ARRAY:

View File

@@ -23,7 +23,10 @@ import com.intellij.util.containers.Stack;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.jet.codegen.JvmRuntimeTypes;
import org.jetbrains.jet.codegen.SamCodegenUtil;
import org.jetbrains.jet.codegen.SamType;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.when.SwitchCodegenUtil;
import org.jetbrains.jet.codegen.when.WhenByEnumsMapping;
@@ -33,6 +36,7 @@ import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
@@ -42,17 +46,15 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.EnumValue;
import org.jetbrains.jet.lang.resolve.constants.NullValue;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.source.SourcePackage;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.*;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.peekFromStack;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.name.SpecialNames.safeIdentifier;
@@ -105,6 +107,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
@NotNull
private ClassDescriptor recordClassForFunction(
@NotNull JetElement element,
@NotNull FunctionDescriptor funDescriptor,
@NotNull Collection<JetType> supertypes,
@NotNull String name
@@ -112,7 +115,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String simpleName = name.substring(name.lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
funDescriptor.getContainingDeclaration(), Name.special("<closure-" + simpleName + ">"), Modality.FINAL, supertypes,
SourceElement.NO_SOURCE
SourcePackage.toSourceElement(element)
);
classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
@@ -191,7 +194,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
JetPsiUtil.getElementTextWithContext(classObject));
String name = peekFromStack(nameStack) + JvmAbi.CLASS_OBJECT_SUFFIX;
recordClosure(classObject, classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -213,7 +216,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
if (classDescriptor == null) return;
String name = getName(classDescriptor);
recordClosure(declaration, classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -232,7 +235,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
if (classDescriptor == null) return;
String name = getName(classDescriptor);
recordClosure(klass, classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -258,11 +261,10 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
}
String name = inventAnonymousClassName(expression.getObjectDeclaration());
recordClosure(expression.getObjectDeclaration(), classDescriptor, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
//noinspection ConstantConditions
nameStack.push(bindingContext.get(ASM_TYPE, classDescriptor).getInternalName());
nameStack.push(CodegenBinding.getAsmType(bindingContext, classDescriptor).getInternalName());
super.visitObjectLiteralExpression(expression);
nameStack.pop();
popClassDescriptor();
@@ -278,8 +280,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String name = inventAnonymousClassName(expression);
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name);
recordClosure(functionLiteral, classDescriptor, name);
ClassDescriptor classDescriptor = recordClassForFunction(functionLiteral, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -329,8 +331,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) referencedFunction.getResultingDescriptor());
String name = inventAnonymousClassName(expression);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name);
recordClosure(expression, classDescriptor, name);
ClassDescriptor classDescriptor = recordClassForFunction(expression, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -340,12 +342,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
}
private void recordClosure(
@NotNull JetElement element,
@NotNull ClassDescriptor classDescriptor,
@NotNull String name
) {
CodegenBinding.recordClosure(bindingTrace, element, classDescriptor, getOuterClassDescriptor(), Type.getObjectType(name));
private void recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) {
CodegenBinding.recordClosure(bindingTrace, classDescriptor, getOuterClassDescriptor(), Type.getObjectType(name));
}
@Override
@@ -380,8 +378,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
else {
String name = inventAnonymousClassName(function);
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, supertypes, name);
recordClosure(function, classDescriptor, name);
ClassDescriptor classDescriptor = recordClassForFunction(function, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
pushClassDescriptor(classDescriptor);
nameStack.push(name);
@@ -401,14 +399,12 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
return peek + '$' + name;
}
else if (containingDeclaration instanceof PackageFragmentDescriptor) {
FqName qualifiedName = ((PackageFragmentDescriptor) containingDeclaration).getFqName();
String packageClassShortName = PackageClassUtils.getPackageClassName(qualifiedName);
String packageClassName = peek.isEmpty() ? packageClassShortName : peek + "/" + packageClassShortName;
return packageClassName + '$' + name;
}
else {
return null;
JetFile containingFile = DescriptorToSourceUtils.getContainingFile(descriptor);
assert containingFile != null : "File not found for " + descriptor;
return PackagePartClassUtils.getPackagePartInternalName(containingFile) + '$' + name;
}
return null;
}
@Override
@@ -498,66 +494,56 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
@Override
public void visitWhenExpression(@NotNull JetWhenExpression expression) {
super.visitWhenExpression(expression);
if (isWhenWithEnums(expression)) {
String currentClassName = getCurrentTopLevelClassOrPackagePartInternalName(expression.getContainingJetFile());
if (!isWhenWithEnums(expression)) return;
if (bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName) == null) {
bindingTrace.record(
MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE,
currentClassName,
new ArrayList<WhenByEnumsMapping>()
);
}
String currentClassName = getCurrentTopLevelClassOrPackagePartInternalName(expression.getContainingJetFile());
List<WhenByEnumsMapping> mappings = bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName);
assert mappings != null : "guaranteed by contract";
int fieldNumber = mappings.size();
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression());
assert type != null : "should not be null in a valid when by enums";
ClassDescriptor classDescriptor = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor();
assert classDescriptor != null : "because it's enum";
WhenByEnumsMapping mapping = new WhenByEnumsMapping(
CodegenBinding.getAsmType(bindingContext, classDescriptor).getInternalName(),
currentClassName,
fieldNumber
);
for (CompileTimeConstant constant : SwitchCodegenUtil.getAllConstants(expression, bindingContext)) {
if (constant instanceof NullValue) continue;
assert constant instanceof EnumValue : "expression in when should be EnumValue";
mapping.putFirstTime((EnumValue) constant, mapping.size() + 1);
}
mappings.add(mapping);
bindingTrace.record(MAPPING_FOR_WHEN_BY_ENUM, expression, mapping);
if (bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName) == null) {
bindingTrace.record(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName, new ArrayList<WhenByEnumsMapping>(1));
}
List<WhenByEnumsMapping> mappings = bindingContext.get(MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE, currentClassName);
assert mappings != null : "guaranteed by contract";
int fieldNumber = mappings.size();
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getSubjectExpression());
assert type != null : "should not be null in a valid when by enums";
ClassDescriptor classDescriptor = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor();
assert classDescriptor != null : "because it's enum";
WhenByEnumsMapping mapping = new WhenByEnumsMapping(classDescriptor, currentClassName, fieldNumber);
for (CompileTimeConstant constant : SwitchCodegenUtil.getAllConstants(expression, bindingContext)) {
if (constant instanceof NullValue) continue;
assert constant instanceof EnumValue : "expression in when should be EnumValue";
mapping.putFirstTime((EnumValue) constant, mapping.size() + 1);
}
mappings.add(mapping);
bindingTrace.record(MAPPING_FOR_WHEN_BY_ENUM, expression, mapping);
}
private boolean isWhenWithEnums(@NotNull JetWhenExpression expression) {
return WhenChecker.isWhenByEnum(expression, bindingContext) &&
SwitchCodegenUtil.checkAllItemsAreConstantsSatisfying(
expression,
bindingContext,
new Function1<CompileTimeConstant, Boolean>() {
@Override
public Boolean invoke(
@NotNull CompileTimeConstant constant
) {
return constant instanceof EnumValue || constant instanceof NullValue;
}
}
);
SwitchCodegenUtil.checkAllItemsAreConstantsSatisfying(
expression,
bindingContext,
new Function1<CompileTimeConstant, Boolean>() {
@Override
public Boolean invoke(@NotNull CompileTimeConstant constant) {
return constant instanceof EnumValue || constant instanceof NullValue;
}
}
);
}
@NotNull
private String getCurrentTopLevelClassOrPackagePartInternalName(@NotNull JetFile file) {
ListIterator<ClassDescriptorWithState> iterator = classStack.listIterator(classStack.size());
while(iterator.hasPrevious()) {
while (iterator.hasPrevious()) {
ClassDescriptor previous = iterator.previous().getDescriptor();
if (DescriptorUtils.isTopLevelOrInnerClass(previous)) {
return CodegenBinding.getAsmType(bindingContext, previous).getInternalName();
@@ -566,4 +552,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
return PackagePartClassUtils.getPackagePartInternalName(file);
}
private static <T> T peekFromStack(@NotNull Stack<T> stack) {
return stack.empty() ? null : stack.peek();
}
}

View File

@@ -28,12 +28,9 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
import org.jetbrains.jet.util.slicedmap.Slices;
@@ -44,7 +41,9 @@ import java.util.*;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.isInterface;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage.getResolvedCall;
import static org.jetbrains.jet.lang.resolve.source.SourcePackage.toSourceElement;
public class CodegenBinding {
public static final WritableSlice<ClassDescriptor, MutableClosure> CLOSURE = Slices.createSimpleSlice();
@@ -53,7 +52,7 @@ public class CodegenBinding {
public static final WritableSlice<ScriptDescriptor, ClassDescriptor> CLASS_FOR_SCRIPT = Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Type> ASM_TYPE = Slices.createCollectiveSlice();
public static final WritableSlice<ClassDescriptor, Type> ASM_TYPE = Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Boolean> ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice();
@@ -138,22 +137,6 @@ public class CodegenBinding {
return getAsmType(bindingContext, anonymousClassForFunction(bindingContext, descriptor));
}
// SCRIPT: register asmType for script descriptor, move to ScriptingUtil
public static void registerClassNameForScript(
BindingTrace bindingTrace,
@NotNull ScriptDescriptor scriptDescriptor,
@NotNull Type asmType
) {
ClassDescriptorImpl classDescriptor =
new ClassDescriptorImpl(scriptDescriptor, Name.special("<script-" + asmType.getInternalName() + ">"), Modality.FINAL,
Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()), SourceElement.NO_SOURCE);
classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
recordClosure(bindingTrace, null, classDescriptor, null, asmType);
bindingTrace.record(CLASS_FOR_SCRIPT, scriptDescriptor, classDescriptor);
}
public static boolean canHaveOuter(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) {
if (classDescriptor.getKind() != ClassKind.CLASS) {
return false;
@@ -168,40 +151,28 @@ public class CodegenBinding {
}
static void recordClosure(
@NotNull BindingTrace bindingTrace,
@Nullable JetElement element,
@NotNull BindingTrace trace,
@NotNull ClassDescriptor classDescriptor,
@Nullable ClassDescriptor enclosing,
@NotNull Type asmType
) {
ResolvedCall<ConstructorDescriptor> superCall = findSuperCall(bindingTrace.getBindingContext(), element);
JetElement element = (JetElement) descriptorToDeclaration(classDescriptor);
assert element != null : "No source element for " + classDescriptor;
CallableDescriptor enclosingReceiver = null;
if (classDescriptor.getContainingDeclaration() instanceof CallableDescriptor) {
enclosingReceiver = (CallableDescriptor) classDescriptor.getContainingDeclaration();
enclosingReceiver = enclosingReceiver instanceof PropertyAccessorDescriptor
? ((PropertyAccessorDescriptor) enclosingReceiver).getCorrespondingProperty()
: enclosingReceiver;
if (enclosingReceiver.getReceiverParameter() == null) {
enclosingReceiver = null;
}
}
MutableClosure closure = new MutableClosure(superCall, enclosing, enclosingReceiver);
assert PsiCodegenPredictor.checkPredictedNameFromPsi(classDescriptor, asmType);
bindingTrace.record(ASM_TYPE, classDescriptor, asmType);
bindingTrace.record(CLOSURE, classDescriptor, closure);
MutableClosure closure = new MutableClosure(classDescriptor, findSuperCall(trace.getBindingContext(), element), enclosing);
if (classDescriptor.isInner()) {
closure.setCaptureThis();
}
assert PsiCodegenPredictor.checkPredictedNameFromPsi(classDescriptor, asmType);
trace.record(ASM_TYPE, classDescriptor, asmType);
trace.record(CLOSURE, classDescriptor, closure);
//TEMPORARY EAT INNER CLASS INFO FOR FUNCTION LITERALS
//TODO: we should understand that lambda/closure would be inlined and don't generate inner class record
if (enclosing != null && !(element instanceof JetFunctionLiteral)) {
recordInnerClass(bindingTrace, enclosing, classDescriptor);
recordInnerClass(trace, enclosing, classDescriptor);
}
}
@@ -219,16 +190,21 @@ public class CodegenBinding {
}
// SCRIPT: register asmType for script, move to ScriptingUtil
public static void registerClassNameForScript(
BindingTrace bindingTrace,
@NotNull JetScript jetScript,
@NotNull Type asmType
) {
ScriptDescriptor descriptor = bindingTrace.getBindingContext().get(SCRIPT, jetScript);
public static void registerClassNameForScript(@NotNull BindingTrace trace, @NotNull JetScript script, @NotNull Type asmType) {
ScriptDescriptor descriptor = trace.getBindingContext().get(SCRIPT, script);
if (descriptor == null) {
throw new IllegalStateException("Descriptor is not found for PSI " + jetScript);
throw new IllegalStateException("Script descriptor is not found for PSI: " + JetPsiUtil.getElementTextWithContext(script));
}
registerClassNameForScript(bindingTrace, descriptor, asmType);
String simpleName = asmType.getInternalName().substring(asmType.getInternalName().lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor =
new ClassDescriptorImpl(descriptor, Name.special("<script-" + simpleName + ">"), Modality.FINAL,
Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()), toSourceElement(script));
classDescriptor.initialize(JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
recordClosure(trace, classDescriptor, null, asmType);
trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor);
}
@NotNull
@@ -287,73 +263,30 @@ public class CodegenBinding {
@NotNull
public static Type getAsmType(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor klass) {
klass = (ClassDescriptor) klass.getOriginal();
Type alreadyComputedType = bindingContext.get(ASM_TYPE, klass);
if (alreadyComputedType != null) {
return alreadyComputedType;
}
Type asmType = Type.getObjectType(getAsmTypeImpl(bindingContext, klass));
assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType);
return asmType;
}
@NotNull
private static String getAsmTypeImpl(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor klass) {
DeclarationDescriptor container = klass.getContainingDeclaration();
Name name = SpecialNames.safeIdentifier(klass.getName());
if (container instanceof PackageFragmentDescriptor) {
String shortName = name.getIdentifier();
FqName fqName = ((PackageFragmentDescriptor) container).getFqName();
return fqName.isRoot() ? shortName : fqName.asString().replace('.', '/') + '/' + shortName;
}
if (container instanceof ScriptDescriptor) {
Type scriptType = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
return scriptType.getInternalName() + "$" + name.getIdentifier();
}
assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
String containerInternalName = getAsmType(bindingContext, (ClassDescriptor) container).getInternalName();
switch (klass.getKind()) {
case ENUM_ENTRY:
return containerInternalName;
case CLASS_OBJECT:
return containerInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
default:
return containerInternalName + "$" + name.getIdentifier();
}
Type type = bindingContext.get(ASM_TYPE, klass);
assert type != null : "Type is not yet recorded for " + klass;
return type;
}
@Nullable
private static ResolvedCall<ConstructorDescriptor> findSuperCall(
@NotNull BindingContext bindingContext,
@Nullable JetElement classOrObject
@NotNull JetElement classOrObject
) {
if (!(classOrObject instanceof JetClassOrObject)) {
return null;
}
if (!(classOrObject instanceof JetClassOrObject)) return null;
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) {
return null;
}
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) return null;
for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) {
if (specifier instanceof JetDelegatorToSuperCall) {
JetType supertype = bindingContext.get(TYPE, specifier.getTypeReference());
assert supertype != null : String.format(
"No type in binding context for \n---\n%s\n---\n", JetPsiUtil.getElementTextWithContext(specifier));
if (!(specifier instanceof JetDelegatorToSuperCall)) continue;
ClassifierDescriptor superClass = supertype.getConstructor().getDeclarationDescriptor();
if (superClass != null && !isInterface(superClass)) {
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (resolvedCall != null && resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor) {
//noinspection unchecked
return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
}
}
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (resolvedCall == null) continue;
CallableDescriptor constructor = resolvedCall.getResultingDescriptor();
if (constructor instanceof ConstructorDescriptor && !isInterface(constructor.getContainingDeclaration())) {
//noinspection unchecked
return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
}
}
@@ -384,9 +317,4 @@ public class CodegenBinding {
return allInnerClasses;
}
@NotNull
public static String getJvmInternalName(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) {
return getAsmType(bindingContext, classDescriptor).getClassName();
}
}

View File

@@ -27,6 +27,8 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.util.*;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.getDirectMember;
public final class MutableClosure implements CalculatedClosure {
private final ResolvedCall<ConstructorDescriptor> superCall;
@@ -40,13 +42,25 @@ public final class MutableClosure implements CalculatedClosure {
private List<Pair<String, Type>> recordedFields;
MutableClosure(
@NotNull ClassDescriptor classDescriptor,
@Nullable ResolvedCall<ConstructorDescriptor> superCall,
@Nullable ClassDescriptor enclosingClass,
@Nullable CallableDescriptor enclosingReceiverDescriptor
@Nullable ClassDescriptor enclosingClass
) {
this.superCall = superCall;
this.enclosingClass = enclosingClass;
this.enclosingReceiverDescriptor = enclosingReceiverDescriptor;
this.superCall = superCall;
this.enclosingReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor);
}
@Nullable
private static CallableDescriptor enclosingExtensionMemberForClass(@NotNull ClassDescriptor classDescriptor) {
DeclarationDescriptor classContainer = classDescriptor.getContainingDeclaration();
if (classContainer instanceof CallableMemberDescriptor) {
CallableMemberDescriptor member = getDirectMember((CallableMemberDescriptor) classContainer);
if (member.getReceiverParameter() != null) {
return member;
}
}
return null;
}
@Nullable

View File

@@ -16,32 +16,18 @@
package org.jetbrains.jet.codegen.binding;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.jet.codegen.ClassBuilderFactories;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.Collection;
import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
public final class PsiCodegenPredictor {
@@ -82,14 +68,14 @@ public final class PsiCodegenPredictor {
}
}
else {
FqName packageFqName = declaration.getContainingJetFile().getPackageFqName();
JetFile containingFile = declaration.getContainingJetFile();
if (declaration instanceof JetNamedFunction) {
Name name = ((JetNamedFunction) declaration).getNameAsName();
return name == null ? null : PackageClassUtils.getPackageClassInternalName(packageFqName) + "$" + name.asString();
return name == null ? null : PackagePartClassUtils.getPackagePartInternalName(containingFile) + "$" + name.asString();
}
parentInternalName = AsmUtil.internalNameByFqNameWithoutInnerClasses(packageFqName);
parentInternalName = AsmUtil.internalNameByFqNameWithoutInnerClasses(containingFile.getPackageFqName());
}
if (declaration instanceof JetClassObject) {
@@ -128,39 +114,4 @@ public final class PsiCodegenPredictor {
return parentInternalName + (parentDeclaration == null ? "/" : "$") + name.asString();
}
@Nullable
public static JetFile getFileForPackagePartName(@NotNull Collection<JetFile> allPackageFiles, @NotNull JvmClassName className) {
for (JetFile file : allPackageFiles) {
String internalName = PackagePartClassUtils.getPackagePartInternalName(file);
JvmClassName jvmClassName = JvmClassName.byInternalName(internalName);
if (jvmClassName.equals(className)) {
return file;
}
}
return null;
}
@Nullable
public static JetFile getFileForCodegenNamedClass(
@NotNull ModuleDescriptor module,
@NotNull BindingContext context,
@NotNull Collection<JetFile> allPackageFiles,
@NotNull String classInternalName
) {
Project project = allPackageFiles.iterator().next().getProject();
GenerationState state = new GenerationState(project, ClassBuilderFactories.THROW_EXCEPTION, module, context,
new ArrayList<JetFile>(allPackageFiles));
state.beforeCompile();
BindingTrace trace = state.getBindingTrace();
for (ClassDescriptor classDescriptor : trace.getKeys(CodegenBinding.ASM_TYPE)) {
Type type = trace.get(CodegenBinding.ASM_TYPE, classDescriptor);
if (type != null && classInternalName.equals(type.getInternalName())) {
return DescriptorToSourceUtils.getContainingFile(classDescriptor);
}
}
return null;
}
}

View File

@@ -20,7 +20,6 @@ import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.binding.MutableClosure;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
@@ -39,7 +38,8 @@ import java.util.Map;
import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_THIS_FIELD;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.anonymousClassForFunction;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.canHaveOuter;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
@@ -266,13 +266,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
lazyOuterExpression = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue(new Function0<StackValue>() {
@Override
public StackValue invoke() {
BindingContext bindingContext = typeMapper.getBindingContext();
ClassDescriptor enclosingClass = getEnclosingClass();
return enclosingClass != null && canHaveOuter(bindingContext, classDescriptor)
? StackValue.field(typeMapper.mapType(enclosingClass),
CodegenBinding.getAsmType(bindingContext, classDescriptor),
CAPTURED_THIS_FIELD,
false)
if (enclosingClass == null) return null;
return canHaveOuter(typeMapper.getBindingContext(), classDescriptor)
? StackValue.field(typeMapper.mapType(enclosingClass), typeMapper.mapType(classDescriptor),
CAPTURED_THIS_FIELD, false)
: null;
}
});
@@ -289,7 +288,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) {
if (aCase.isCase(d)) {
Type classType = state.getBindingContext().get(ASM_TYPE, getThisDescriptor());
Type classType = state.getTypeMapper().mapType(getThisDescriptor());
StackValue innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType);
if (innerValue == null) {
break;

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.extensions
import org.jetbrains.jet.extensions.ProjectExtensionDescriptor
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.codegen.StackValue
import org.jetbrains.jet.codegen.state.JetTypeMapper
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
public trait ExpressionCodegenExtension {
class object : ProjectExtensionDescriptor<ExpressionCodegenExtension>("org.jetbrains.kotlin.expressionCodegenExtension", javaClass<ExpressionCodegenExtension>())
public class Context(
public val typeMapper: JetTypeMapper,
public val v: InstructionAdapter
)
// return null if not applicable
public fun apply(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue?
}

View File

@@ -79,7 +79,7 @@ public class AnonymousObjectTransformer {
if (file == null) {
throw new RuntimeException("Couldn't find virtual file for " + objectInternalName);
}
reader = new ClassReader(file.getInputStream());
reader = new ClassReader(file.contentsToByteArray());
}
}
catch (IOException e) {

View File

@@ -47,18 +47,15 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.Method;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
import org.jetbrains.org.objectweb.asm.util.Textifier;
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.addInlineMarker;
public class InlineCodegen implements CallGenerator {
private final GenerationState state;
@@ -130,7 +127,7 @@ public class InlineCodegen implements CallGenerator {
throw new CompilationException("Couldn't inline method call '" +
functionDescriptor.getName() +
"' into \n" + (element != null ? element.getText() : "null psi element " + this.codegen.getContext().getContextDescriptor()) +
(generateNodeText ? ("\ncause: " + getNodeText(node)) : ""),
(generateNodeText ? ("\ncause: " + InlineCodegenUtil.getNodeText(node)) : ""),
e, callElement);
}
@@ -158,7 +155,7 @@ public class InlineCodegen implements CallGenerator {
MethodNode node;
if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable((DeserializedSimpleFunctionDescriptor) functionDescriptor, state);
node = InlineCodegenUtil.getMethodNode(file.getInputStream(), asmMethod.getName(), asmMethod.getDescriptor());
node = InlineCodegenUtil.getMethodNode(file.contentsToByteArray(), asmMethod.getName(), asmMethod.getDescriptor());
if (node == null) {
throw new RuntimeException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
@@ -208,6 +205,8 @@ public class InlineCodegen implements CallGenerator {
//through generation captured parameters will be added to invocationParamBuilder
putClosureParametersOnStack();
addInlineMarker(codegen.v, true);
Parameters parameters = invocationParamBuilder.buildParameters();
InliningContext info = new RootInliningContext(expressionMap,
@@ -242,10 +241,13 @@ public class InlineCodegen implements CallGenerator {
}
}
};
List<MethodInliner.FinallyBlockInfo> infos = MethodInliner.processReturns(adapter, labelOwner, true, null);
List<MethodInliner.ExternalFinallyBlockInfo> infos = MethodInliner.processReturns(adapter, labelOwner, true, null);
generateAndInsertFinallyBlocks(adapter, infos);
adapter.accept(new InliningInstructionAdapter(codegen.v));
addInlineMarker(codegen.v, false);
return result;
}
@@ -443,19 +445,6 @@ public class InlineCodegen implements CallGenerator {
return (getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) != 0;
}
@NotNull
public static String getNodeText(@Nullable MethodNode node) {
if (node == null) {
return "Not generated";
}
Textifier p = new Textifier();
node.accept(new TraceMethodVisitor(p));
StringWriter sw = new StringWriter();
p.print(new PrintWriter(sw));
sw.flush();
return node.name + " " + node.desc + ": \n " + sw.getBuffer().toString();
}
private static String descriptorName(DeclarationDescriptor descriptor) {
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
}
@@ -494,10 +483,10 @@ public class InlineCodegen implements CallGenerator {
}
public void generateAndInsertFinallyBlocks(MethodNode intoNode, List<MethodInliner.FinallyBlockInfo> insertPoints) {
public void generateAndInsertFinallyBlocks(MethodNode intoNode, List<MethodInliner.ExternalFinallyBlockInfo> insertPoints) {
if (!codegen.hasFinallyBlocks()) return;
for (MethodInliner.FinallyBlockInfo insertPoint : insertPoints) {
for (MethodInliner.ExternalFinallyBlockInfo insertPoint : insertPoints) {
MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode();
ExpressionCodegen finallyCodegen =
new ExpressionCodegen(finallyNode, codegen.getFrameMap(), codegen.getReturnType(),

View File

@@ -16,13 +16,13 @@
package org.jetbrains.jet.codegen.inline;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.PackageContext;
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils;
@@ -44,12 +45,14 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.InsnList;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
import org.jetbrains.org.objectweb.asm.tree.*;
import org.jetbrains.org.objectweb.asm.util.Textifier;
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.ListIterator;
@@ -69,10 +72,13 @@ public class InlineCodegenUtil {
public static final String NON_LOCAL_RETURN = "$$$$$NON_LOCAL_RETURN$$$$$";
public static final String ROOT_LABEL = "$$$$$ROOT$$$$$";
public static final String INLINE_MARKER_CLASS_NAME = "kotlin/jvm/internal/InlineMarker";
public static final String INLINE_MARKER_BEFORE_METHOD_NAME = "beforeInlineCall";
public static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall";
@Nullable
public static MethodNode getMethodNode(
InputStream classData,
byte[] classData,
final String methodName,
final String methodDescriptor
) throws ClassNotFoundException, IOException {
@@ -254,8 +260,8 @@ public class InlineCodegenUtil {
}
@NotNull
public static MaxCalcNode wrapWithMaxLocalCalc(@NotNull MethodNode methodNode) {
return new MaxCalcNode(methodNode);
public static MethodVisitor wrapWithMaxLocalCalc(@NotNull MethodNode methodNode) {
return new MaxStackFrameSizeAndLocalsCalculator(API, methodNode.access, methodNode.desc, methodNode);
}
private static boolean isInteger(@NotNull String string) {
@@ -283,6 +289,13 @@ public class InlineCodegenUtil {
return opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN;
}
//marked return could be either non-local or local in case of labeled lambda self-returns
public static boolean isMarkedReturn(@NotNull AbstractInsnNode returnIns) {
assert isReturnOpcode(returnIns.getOpcode()) : "Should be called on return instruction, but " + returnIns;
AbstractInsnNode globalFlag = returnIns.getPrevious();
return globalFlag instanceof MethodInsnNode && NON_LOCAL_RETURN.equals(((MethodInsnNode)globalFlag).owner);
}
public static void generateGlobalReturnFlag(@NotNull InstructionAdapter iv, @NotNull String labelName) {
iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false);
}
@@ -294,16 +307,16 @@ public class InlineCodegenUtil {
case Opcodes.DRETURN: return Type.DOUBLE_TYPE;
case Opcodes.FRETURN: return Type.FLOAT_TYPE;
case Opcodes.LRETURN: return Type.LONG_TYPE;
default: return Type.getObjectType("object");
default: return AsmTypeConstants.OBJECT_TYPE;
}
}
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode afterNode) {
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) {
InsnList instructions = to.instructions;
ListIterator<AbstractInsnNode> iterator = from.instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode next = iterator.next();
instructions.insertBefore(afterNode, next);
instructions.insertBefore(beforeNode, next);
}
}
@@ -311,4 +324,69 @@ public class InlineCodegenUtil {
public static MethodNode createEmptyMethodNode() {
return new MethodNode(API, 0, "fake", "()V", null, null);
}
private static boolean isLastGoto(@NotNull AbstractInsnNode insnNode, @NotNull AbstractInsnNode stopAt) {
if (insnNode.getOpcode() == Opcodes.GOTO) {
insnNode = insnNode.getNext();
while (insnNode != stopAt && isLineNumberOrLabel(insnNode)) {
insnNode = insnNode.getNext();
}
return stopAt == insnNode;
}
return false;
}
static boolean isLineNumberOrLabel(@Nullable AbstractInsnNode node) {
return node instanceof LineNumberNode || node instanceof LabelNode;
}
@NotNull
public static LabelNode firstLabelInChain(@NotNull LabelNode node) {
LabelNode curNode = node;
while (curNode.getPrevious() instanceof LabelNode) {
curNode = (LabelNode) curNode.getPrevious();
}
return curNode;
}
@NotNull
public static String getNodeText(@Nullable MethodNode node) {
return getNodeText(node, new Textifier());
}
@NotNull
public static String getNodeText(@Nullable MethodNode node, @NotNull Textifier textifier) {
if (node == null) {
return "Not generated";
}
node.accept(new TraceMethodVisitor(textifier));
StringWriter sw = new StringWriter();
textifier.print(new PrintWriter(sw));
sw.flush();
return node.name + " " + node.desc + ": \n " + sw.getBuffer().toString();
}
public static class LabelTextifier extends Textifier {
public LabelTextifier() {
super(API);
}
@Nullable
@TestOnly
@SuppressWarnings("UnusedDeclaration")
public String getLabelNameIfExists(@NotNull Label l) {
return labelNames == null ? null : labelNames.get(l);
}
}
public static void addInlineMarker(
@NotNull InstructionAdapter v,
boolean isStartNotEnd
) {
v.visitMethodInsn(Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,
(isStartNotEnd ? INLINE_MARKER_BEFORE_METHOD_NAME : INLINE_MARKER_AFTER_METHOD_NAME),
"()V", false);
}
}

View File

@@ -0,0 +1,547 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.inline;
import com.google.common.base.Objects;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.tree.*;
import java.util.*;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.*;
public class InternalFinallyBlockInliner {
private static class FinallyBlockInfo {
final AbstractInsnNode startIns;
final AbstractInsnNode endInsExclusive;
private FinallyBlockInfo(@NotNull AbstractInsnNode inclusiveStart, @NotNull AbstractInsnNode exclusiveEnd) {
startIns = inclusiveStart;
endInsExclusive = exclusiveEnd;
}
}
public static void processInlineFunFinallyBlocks(@NotNull MethodNode inlineFun, int lambdaTryCatchBlockNodes) {
int index = 0;
List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo = new ArrayList<TryCatchBlockNodeInfo>();
for (TryCatchBlockNode block : inlineFun.tryCatchBlocks) {
inlineFunTryBlockInfo.add(new TryCatchBlockNodeInfo(block, index++ < lambdaTryCatchBlockNodes));
}
if (hasFinallyBlocks(inlineFunTryBlockInfo)) {
new InternalFinallyBlockInliner(inlineFun, inlineFunTryBlockInfo).processInlineFunFinallyBlocks();
}
}
@NotNull
private final MethodNode inlineFun;
private final List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo;
private final ListMultimap<LabelNode, TryCatchBlockNodeInfo> tryBlockStarts = LinkedListMultimap.create();
private final ListMultimap<LabelNode, TryCatchBlockNodeInfo> tryBlockEnds = LinkedListMultimap.create();
//lambdaTryCatchBlockNodes is number of TryCatchBlockNodes that was inlined with lambdas into function
//due to code generation specific they placed before function TryCatchBlockNodes
private InternalFinallyBlockInliner(@NotNull MethodNode inlineFun, List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo) {
this.inlineFun = inlineFun;
this.inlineFunTryBlockInfo = inlineFunTryBlockInfo;
}
private int initAndGetVarIndexForNonLocalReturnValue() {
//sortTryCatchBlocks();/*TODO maybe remove*/
mapLabelsToTryCatchBlocks();
MaxLocalsCalculator tempCalcNode = new MaxLocalsCalculator(
InlineCodegenUtil.API,
inlineFun.access, inlineFun.desc, null
);
inlineFun.accept(tempCalcNode);
return tempCalcNode.getMaxLocals();
}
private void processInlineFunFinallyBlocks() {
int nextTempNonLocalVarIndex = initAndGetVarIndexForNonLocalReturnValue();
Stack<TryCatchBlockNodeInfo> coveringTryCatchBlocks = new Stack<TryCatchBlockNodeInfo>();
InsnList instructions = inlineFun.instructions;
//As we do finally block code search after non-local return instruction
// we should be sure that all others non-local returns already processed in this finally block.
// So we do instruction processing in reverse order!
AbstractInsnNode curIns = instructions.getLast();
while (curIns != null) {
updateCoveringTryBlocks(coveringTryCatchBlocks, curIns);
//At this point only global return is possible, local one already substituted with: goto endLabel
if (!InlineCodegenUtil.isReturnOpcode(curIns.getOpcode()) || !InlineCodegenUtil.isMarkedReturn(curIns)) {
curIns = curIns.getPrevious();
continue;
}
AbstractInsnNode instrInsertFinallyBefore = curIns.getPrevious();
AbstractInsnNode nextPrev = instrInsertFinallyBefore.getPrevious();
Type nonLocalReturnType = InlineCodegenUtil.getReturnType(curIns.getOpcode());
//Generally there could be several tryCatch blocks (group) on one code interval (same start and end labels, but maybe different handlers) -
// all of them refer to one try/*catches*/finally or try/catches.
// Each group that corresponds to try/*catches*/finally contains tryCatch block with default handler.
// For each such group we should insert corresponding finally before non-local return.
// So we split all try blocks on current instructions to groups and process them independently
List<TryBlockCluster<TryCatchBlockNodeInfo>> clusters = InlinePackage.doClustering(coveringTryCatchBlocks);
ListIterator<TryBlockCluster<TryCatchBlockNodeInfo>> tryCatchBlockIterator = clusters.listIterator(clusters.size());
//Reverse visiting cause innermost tryCatchBlocks in the end
while (tryCatchBlockIterator.hasPrevious()) {
TryBlockCluster originalFinallyCluster = tryCatchBlockIterator.previous();
List<TryCatchBlockNodeInfo> clusterBlocks = originalFinallyCluster.getBlocks();
TryCatchBlockNodeInfo originalFinallyBlock = clusterBlocks.get(0);
FinallyBlockInfo finallyInfo = findFinallyBlockBody(originalFinallyBlock, inlineFunTryBlockInfo);
if (finallyInfo == null) continue;
instructions.resetLabels();
List<TryCatchBlockNodePosition> tryCatchBlockInlinedInFinally = findTryCatchBlocksInlinedInFinally(finallyInfo);
//Keep some information about label nodes, we need it to understand whether it's jump inside finally block or outside
// in first case we do call VISIT on instruction otherwise recreating jump instruction (see below)
Set<LabelNode> labelsInsideFinally = rememberOriginalLabelNodes(finallyInfo);
//Creating temp node for finally block copy with some additional instruction
MethodNode finallyBlockCopy = createEmptyMethodNode();
Label newFinallyStart = new Label();
Label newFinallyEnd = new Label();
Label insertedBlockEnd = new Label();
if (nonLocalReturnType != Type.VOID_TYPE) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ISTORE), nextTempNonLocalVarIndex);
}
finallyBlockCopy.visitLabel(newFinallyStart);
//Writing finally block body to temporary node
AbstractInsnNode currentIns = finallyInfo.startIns;
while (currentIns != finallyInfo.endInsExclusive) {
//This condition allows another model for non-local returns processing
if (false && InlineCodegenUtil.isReturnOpcode(currentIns.getOpcode()) && !InlineCodegenUtil.isMarkedReturn(currentIns)) {
//substitute all local returns in finally finallyInfo with non-local one lambdaFinallyBlocks try finallyInfo
//TODO same for jumps
Type localReturnType = InlineCodegenUtil.getReturnType(currentIns.getOpcode());
substituteReturnValueInFinally(nextTempNonLocalVarIndex, nonLocalReturnType, finallyBlockCopy,
localReturnType, true);
instrInsertFinallyBefore.accept(finallyBlockCopy);
curIns.accept(finallyBlockCopy);
}
else {
boolean isInsOrJumpInsideFinally =
!(currentIns instanceof JumpInsnNode) ||
labelsInsideFinally.contains(((JumpInsnNode) currentIns).label);
if (isInsOrJumpInsideFinally) {
currentIns.accept(finallyBlockCopy); //VISIT
}
else {
//keep original jump: add currentIns clone
finallyBlockCopy.instructions.add(new JumpInsnNode(currentIns.getOpcode(), ((JumpInsnNode) currentIns).label));
}
}
currentIns = currentIns.getNext();
}
finallyBlockCopy.visitLabel(newFinallyEnd);
if (nonLocalReturnType != Type.VOID_TYPE) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ILOAD), nextTempNonLocalVarIndex);
nextTempNonLocalVarIndex += nonLocalReturnType.getSize(); //TODO: do more wise indexing
}
finallyBlockCopy.visitLabel(insertedBlockEnd);
//Copying finally body before non-local return instruction
InlineCodegenUtil.insertNodeBefore(finallyBlockCopy, inlineFun, instrInsertFinallyBefore);
nextPrev = updateExceptionTable(coveringTryCatchBlocks, nextPrev, clusterBlocks, newFinallyStart, newFinallyEnd,
tryCatchBlockInlinedInFinally, labelsInsideFinally, (LabelNode) insertedBlockEnd.info);
}
curIns = nextPrev;
}
inlineFun.tryCatchBlocks.clear();
for (TryCatchBlockNodeInfo info : inlineFunTryBlockInfo) {
inlineFun.tryCatchBlocks.add(info.getNode());
}
}
@NotNull
private static Set<LabelNode> rememberOriginalLabelNodes(@NotNull FinallyBlockInfo finallyInfo) {
Set<LabelNode> labelsInsideFinally = new HashSet<LabelNode>();
for (AbstractInsnNode currentIns = finallyInfo.startIns; currentIns != finallyInfo.endInsExclusive; currentIns = currentIns.getNext()) {
if (currentIns instanceof LabelNode) {
labelsInsideFinally.add((LabelNode) currentIns);
}
}
return labelsInsideFinally;
}
@Nullable
private AbstractInsnNode updateExceptionTable(
@NotNull Stack<TryCatchBlockNodeInfo> coveringTryBlocks,
@Nullable AbstractInsnNode nextPrev,
@NotNull List<TryCatchBlockNodeInfo> updatingClusterBlocks,
@NotNull Label newFinallyStart,
@NotNull Label newFinallyEnd,
@NotNull List<TryCatchBlockNodePosition> tryCatchBlockPresentInFinally,
@NotNull Set<LabelNode> labelsInsideFinally,
@NotNull LabelNode insertedBlockEnd
) {
//copy tryCatchFinallies that totally in finally block
List<TryBlockCluster<TryCatchBlockNodePosition>> clusters = InlinePackage.doClustering(tryCatchBlockPresentInFinally);
Map<LabelNode, TryBlockCluster<TryCatchBlockNodePosition>> handler2Cluster = new HashMap<LabelNode, TryBlockCluster<TryCatchBlockNodePosition>>();
for (TryBlockCluster<TryCatchBlockNodePosition> cluster : clusters) {
List<TryCatchBlockNodePosition> clusterBlocks = cluster.getBlocks();
TryCatchBlockNodePosition block0 = clusterBlocks.get(0);
TryCatchPosition clusterPosition = block0.getPosition();
if (clusterPosition == TryCatchPosition.INNER) {
for (TryCatchBlockNodePosition position : clusterBlocks) {
assert clusterPosition == position.getPosition() : "Wrong inner tryCatchBlock structure";
TryCatchBlockNode tryCatchBlockNode = position.getNodeInfo().getNode();
assert inlineFun.instructions.indexOf(tryCatchBlockNode.start) <= inlineFun.instructions.indexOf(tryCatchBlockNode.end);
TryCatchBlockNode additionalTryCatchBlock =
new TryCatchBlockNode((LabelNode) tryCatchBlockNode.start.getLabel().info,
(LabelNode) tryCatchBlockNode.end.getLabel().info,
getNewOrOldLabel(tryCatchBlockNode.handler, labelsInsideFinally),
tryCatchBlockNode.type);
assert inlineFun.instructions.indexOf(additionalTryCatchBlock.start) <= inlineFun.instructions.indexOf(additionalTryCatchBlock.end);
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, true);
tryBlockStarts.put(newInfo.getStartLabel(), newInfo);
tryBlockEnds.put(newInfo.getEndLabel(), newInfo);
inlineFunTryBlockInfo.add(newInfo);
}
}
else if (clusterPosition == TryCatchPosition.END) {
TryCatchBlockNodePosition defaultHandler = cluster.getDefaultHandler();
assert defaultHandler != null : "Default handler should be present";
handler2Cluster.put(defaultHandler.getHandler(), cluster);
}
else {
assert clusterPosition == TryCatchPosition.START;
TryCatchBlockNodePosition defaultHandler = cluster.getDefaultHandler();
assert defaultHandler != null : "Default handler should be present";
TryBlockCluster<TryCatchBlockNodePosition> endCluster = handler2Cluster.remove(defaultHandler.getHandler());
assert endCluster != null : "Could find start cluster for " + clusterPosition;
//at this point only external finallies could occurs
//they don't collision with updatingClusterBlocks, but may with external ones on next updateExceptionTable invocation
Iterator<TryCatchBlockNodePosition> startBlockPositions = clusterBlocks.iterator();
for (TryCatchBlockNodePosition endBlockPosition : endCluster.getBlocks()) {
TryCatchBlockNodeInfo startNode = startBlockPositions.next().getNodeInfo();
TryCatchBlockNodeInfo endNode = endBlockPosition.getNodeInfo();
assert Objects.equal(startNode.getType(), endNode.getType()) : "Different handler types : " + startNode.getType() + " " + endNode.getType();
patchTryBlocks((LabelNode) startNode.getStartLabel().getLabel().info, endNode, false);
}
}
}
if (handler2Cluster.size() == 1) {
TryBlockCluster<TryCatchBlockNodePosition> singleCluster = handler2Cluster.values().iterator().next();
if (singleCluster.getBlocks().get(0).getPosition() == TryCatchPosition.END) {
//Pair that starts on default handler don't added to tryCatchBlockPresentInFinally cause it's out of finally block
//TODO rewrite to clusters
for (TryCatchBlockNodePosition endBlockPosition : singleCluster.getBlocks()) {
TryCatchBlockNodeInfo endNode = endBlockPosition.getNodeInfo();
patchTryBlocks((LabelNode) insertedBlockEnd.getLabel().info, endNode, true);
//nextPrev = (AbstractInsnNode) insertedBlockEnd.getLabel().info;
}
handler2Cluster.clear();
}
}
assert handler2Cluster.isEmpty() : "Unmatched clusters " + handler2Cluster.size();
// Inserted finally shouldn't be handled by corresponding catches,
// so we should split original interval by inserted finally one
for (TryCatchBlockNodeInfo block : updatingClusterBlocks) {
//update exception mapping
LabelNode oldStartNode = block.getNode().start;
tryBlockStarts.remove(oldStartNode, block);
block.getNode().start = (LabelNode) newFinallyEnd.info;
//tryBlockStarts.put(block.getStartLabel(), block);
TryCatchBlockNode additionalTryCatchBlock =
new TryCatchBlockNode(oldStartNode, (LabelNode) newFinallyStart.info, block.getNode().handler, block.getNode().type);
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, false);
tryBlockStarts.put(additionalTryCatchBlock.start, newInfo);
tryBlockEnds.put(additionalTryCatchBlock.end, newInfo);
inlineFunTryBlockInfo.add(newInfo);
//TODO add assert
nextPrev = additionalTryCatchBlock.end;
coveringTryBlocks.pop();
}
sortTryCatchBlocks(inlineFunTryBlockInfo);
return nextPrev;
}
private void patchTryBlocks(@NotNull LabelNode newStartLabelNode, @NotNull TryCatchBlockNodeInfo endNode, boolean sort) {
LabelNode oldStart = endNode.getStartLabel();
endNode.getNode().start = newStartLabelNode;
tryBlockStarts.remove(oldStart, endNode);
tryBlockStarts.put(endNode.getNode().start, endNode);
TryCatchBlockNode endTryBlock = endNode.getNode();
TryCatchBlockNode additionalTryCatchBlock =
new TryCatchBlockNode(oldStart,
(LabelNode) endTryBlock.end.getLabel().info,
endTryBlock.handler,
endTryBlock.type);
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, endNode.getOnlyCopyNotProcess());
tryBlockStarts.put(newInfo.getStartLabel(), newInfo);
tryBlockEnds.put(newInfo.getEndLabel(), newInfo);
inlineFunTryBlockInfo.add(newInfo);
}
private static LabelNode getNewOrOldLabel(LabelNode oldHandler, @NotNull Set<LabelNode> labelsInsideFinally) {
if (labelsInsideFinally.contains(oldHandler)) {
return (LabelNode) oldHandler.getLabel().info;
}
return oldHandler;
}
//Keep information about try blocks that cover current instruction -
// pushing and popping it to stack entering and exiting tryCatchBlock start and end labels
private void updateCoveringTryBlocks(Stack<TryCatchBlockNodeInfo> coveringTryBlocks, AbstractInsnNode curIns) {
if (!(curIns instanceof LabelNode)) return;
List<TryCatchBlockNodeInfo> infos = tryBlockStarts.get((LabelNode) curIns);
for (TryCatchBlockNodeInfo startNode : infos) {
if (!startNode.getOnlyCopyNotProcess()) {
TryCatchBlockNodeInfo pop = coveringTryBlocks.pop();
//Temporary disabled cause during patched structure of exceptions changed
//assert startNode == pop : "Wrong try-catch structure " + startNode + " " + pop + " " + infos.size();
}
}
//Reversing list order cause we should pop external block before internal one
// (originally internal blocks goes before external one, such invariant preserved via sortTryCatchBlocks method)
for (TryCatchBlockNodeInfo info : Lists.reverse(tryBlockEnds.get((LabelNode) curIns))) {
if (!info.getOnlyCopyNotProcess()) {
coveringTryBlocks.add(info);
}
}
}
private static boolean hasFinallyBlocks(List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo) {
for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) {
if (!block.getOnlyCopyNotProcess() && block.getNode().type == null) {
return true;
}
}
return false;
}
private void mapLabelsToTryCatchBlocks() {
for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) {
tryBlockStarts.put(block.getNode().start, block);
tryBlockEnds.put(block.getNode().end, block);
}
}
//As described above all tryCatch group that have finally block also should contains tryCatchBlockNode with default handler.
//So we assume that instructions between end of tryCatchBlock and start of next tryCatchBlock with same default handler is required finally body.
//There is at least two tryCatchBlockNodes in list cause there is always tryCatchBlockNode on first instruction of default handler:
// "ASTORE defaultHandlerExceptionIndex" (handles itself, as does java).
@Nullable
private FinallyBlockInfo findFinallyBlockBody(
@NotNull TryCatchBlockNodeInfo tryCatchBlock,
@NotNull List<TryCatchBlockNodeInfo> tryCatchBlocks
) {
List<TryCatchBlockNodeInfo> sameDefaultHandler = new ArrayList<TryCatchBlockNodeInfo>();
LabelNode defaultHandler = null;
boolean afterStartBlock = false;
for (TryCatchBlockNodeInfo block : tryCatchBlocks) {
if (tryCatchBlock == block) {
afterStartBlock = true;
}
if (afterStartBlock) {
if (block.getNode().type == null && (firstLabelInChain(tryCatchBlock.getNode().start) == firstLabelInChain(block.getNode().start) &&
firstLabelInChain(tryCatchBlock.getNode().end) == firstLabelInChain(block.getNode().end)
|| defaultHandler == firstLabelInChain(block.getNode().handler))) {
sameDefaultHandler.add(block); //first is tryCatchBlock if no catch clauses
if (defaultHandler == null) {
defaultHandler = firstLabelInChain(block.getNode().handler);
}
}
}
}
if (sameDefaultHandler.isEmpty()) {
//there is no finally block
//it always should be present in default handler
return null;
}
TryCatchBlockNodeInfo nextIntervalWithSameDefaultHandler = sameDefaultHandler.get(1);
AbstractInsnNode startFinallyChain = tryCatchBlock.getNode().end;
AbstractInsnNode endFinallyChainExclusive = skipLastGotoIfNeeded(nextIntervalWithSameDefaultHandler.getNode().handler,
nextIntervalWithSameDefaultHandler.getNode().start);
return new FinallyBlockInfo(startFinallyChain.getNext(), endFinallyChainExclusive);
}
@NotNull
private AbstractInsnNode skipLastGotoIfNeeded(
@NotNull LabelNode defaultHandlerStartLabel,
@NotNull AbstractInsnNode lastFinallyInsExclusive
) {
AbstractInsnNode prevLast = getPrevNoLineNumberOrLabel(lastFinallyInsExclusive, true);
assert prevLast != null : "Empty finally block: " + lastFinallyInsExclusive;
if (prevLast.getOpcode() == Opcodes.GOTO) {
//There we should understand whether goto is jump over catches or last break/continue command inside finally.
//If it's a jump over catches so next is true:
// 1. jump label should go after default catch handler start label
// AND
// 2. it shouldn't be present in default catch block, otherwise it break/continue
LabelNode targetJump = ((JumpInsnNode) prevLast).label;
InsnList instructions = inlineFun.instructions;
if (instructions.indexOf(defaultHandlerStartLabel) < instructions.indexOf(targetJump)) { //1 condition
AbstractInsnNode cur = defaultHandlerStartLabel;
while (cur != targetJump) {
if (cur.getOpcode() == Opcodes.GOTO) {
//noinspection ConstantConditions
if (((JumpInsnNode) cur).label == targetJump) { //fail of 2 condition
return lastFinallyInsExclusive;
}
}
cur = cur.getNext();
}
return prevLast;
}
}
return lastFinallyInsExclusive;
}
@NotNull
private List<TryCatchBlockNodePosition> findTryCatchBlocksInlinedInFinally(@NotNull FinallyBlockInfo finallyInfo) {
List<TryCatchBlockNodePosition> result = new ArrayList<TryCatchBlockNodePosition>();
Map<TryCatchBlockNodeInfo, TryCatchBlockNodePosition> processedBlocks = new HashMap<TryCatchBlockNodeInfo, TryCatchBlockNodePosition>();
for (AbstractInsnNode curInstr = finallyInfo.startIns; curInstr != finallyInfo.endInsExclusive; curInstr = curInstr.getNext()) {
if (!(curInstr instanceof LabelNode)) continue;
LabelNode curLabel = (LabelNode) curInstr;
List<TryCatchBlockNodeInfo> startedTryBlocks = tryBlockStarts.get(curLabel);
if (startedTryBlocks != null) {
for (TryCatchBlockNodeInfo block : startedTryBlocks) {
assert !processedBlocks.containsKey(block) : "Try catch block already processed before start label!!! " + block;
TryCatchBlockNodePosition info = new TryCatchBlockNodePosition(block, TryCatchPosition.START);
processedBlocks.put(block, info);
result.add(info);
}
}
List<TryCatchBlockNodeInfo> endedTryBlocks = tryBlockEnds.get(curLabel);
if (endedTryBlocks == null) continue;
for (TryCatchBlockNodeInfo block : endedTryBlocks) {
TryCatchBlockNodePosition info = processedBlocks.get(block);
if (info != null) {
assert info.getPosition() == TryCatchPosition.START;
info.setPosition(TryCatchPosition.INNER);
}
else {
info = new TryCatchBlockNodePosition(block, TryCatchPosition.END);
processedBlocks.put(block, info);
result.add(info);
}
}
}
return result;
}
private static void substituteReturnValueInFinally(
int nonLocalVarIndex,
@NotNull Type nonLocalReturnType,
@NotNull MethodNode finallyBlockCopy,
@NotNull Type localReturnType,
boolean doPop
) {
if (doPop && localReturnType != Type.VOID_TYPE) {
AsmUtil.pop(finallyBlockCopy, localReturnType);
}
if (nonLocalReturnType != Type.VOID_TYPE) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ILOAD), nonLocalVarIndex);
}
}
@Nullable
private static AbstractInsnNode getPrevNoLineNumberOrLabel(@NotNull AbstractInsnNode node, boolean strict) {
AbstractInsnNode result = strict ? node.getPrevious() : node;
while (isLineNumberOrLabel(result)) {
result = result.getPrevious();
}
return result;
}
private void sortTryCatchBlocks(@NotNull List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo) {
Comparator<TryCatchBlockNodeInfo> comp = new Comparator<TryCatchBlockNodeInfo>() {
@Override
public int compare(@NotNull TryCatchBlockNodeInfo t1, @NotNull TryCatchBlockNodeInfo t2) {
int result = inlineFun.instructions.indexOf(t1.getNode().handler) - inlineFun.instructions.indexOf(t2.getNode().handler);
if (result == 0) {
result = inlineFun.instructions.indexOf(t1.getNode().start) - inlineFun.instructions.indexOf(t2.getNode().start);
if (result == 0) {
assert false : "Error: support multicatch finallies!";
result = inlineFun.instructions.indexOf(t1.getNode().end) - inlineFun.instructions.indexOf(t2.getNode().end);
}
}
return result;
}
};
Collections.sort(inlineFunTryBlockInfo, comp);
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.inline;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
import java.util.ListIterator;
public class MaxCalcNode extends MethodVisitor {
private int maxLocal;
private final MethodNode node;
public MaxCalcNode(MethodNode node) {
super(InlineCodegenUtil.API, node);
this.node = node;
int paramsSize = (node.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
Type[] types = Type.getArgumentTypes(node.desc);
for (Type type : types) {
paramsSize += type.getSize();
}
maxLocal = paramsSize;
}
@Override
public void visitVarInsn(int opcode, int var) {
super.visitVarInsn(opcode, var);
int size = opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE ? 2 : 1;
updateMaxLocal(var, size);
}
@Override
public void visitIincInsn(int var, int increment) {
super.visitIincInsn(var, increment);
updateMaxLocal(var, 1);
}
private void updateMaxLocal(int index, int size) {
maxLocal = Math.max(maxLocal, index + size);
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
//NB: it's hack for fast maxStack calculation cause it performed only in MethodWriter
//temporary solution: maxStack = instruction size (without labels and line numbers) * 2 (cause 1 instruction could put value of size 2)
int size = 0;
ListIterator<AbstractInsnNode> iterator = node.instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode next = iterator.next();
int type = next.getType();
if (type != AbstractInsnNode.LINE && type != AbstractInsnNode.LABEL) {
size++;
}
}
super.visitMaxs(Math.max(size * 2, maxStack), Math.max(maxLocals, this.maxLocal));
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.inline;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
public class MaxLocalsCalculator extends MethodVisitor {
private int maxLocals;
public MaxLocalsCalculator(int api, int access, String descriptor, MethodVisitor mv) {
super(api, mv);
// updates maxLocals
int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
if ((access & Opcodes.ACC_STATIC) != 0) {
--size;
}
maxLocals = size;
}
@Override
public void visitVarInsn(int opcode, int var) {
int n;
if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD ||
opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
n = var + 2;
}
else {
n = var + 1;
}
updateMaxLocals(n);
super.visitVarInsn(opcode, var);
}
@Override
public void visitIincInsn(int var, int increment) {
updateMaxLocals(var + 1);
super.visitIincInsn(var, increment);
}
@Override
public void visitLocalVariable(
@NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index
) {
// updates max locals
char c = desc.charAt(0);
int n = index + (c == 'J' || c == 'D' ? 2 : 1);
updateMaxLocals(n);
super.visitLocalVariable(name, desc, signature, start, end, index);
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
super.visitMaxs(maxStack, this.maxLocals);
}
public int getMaxLocals() {
return maxLocals;
}
private void updateMaxLocals(int nextFreeSlotNumber) {
if (nextFreeSlotNumber > maxLocals) {
maxLocals = nextFreeSlotNumber;
}
}
}

View File

@@ -0,0 +1,430 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.inline;
import com.intellij.openapi.util.Factory;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.org.objectweb.asm.*;
import java.util.*;
public class MaxStackFrameSizeAndLocalsCalculator extends MaxLocalsCalculator {
private static final int[] FRAME_SIZE_CHANGE_BY_OPCODE;
static {
// copy-pasted from org.jetbrains.org.objectweb.asm.Frame
int i;
int[] b = new int[202];
String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
+ "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
+ "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
+ "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
for (i = 0; i < b.length; ++i) {
b[i] = s.charAt(i) - 'E';
}
FRAME_SIZE_CHANGE_BY_OPCODE = b;
}
private final LabelWrapper firstLabel;
private LabelWrapper currentBlock;
private LabelWrapper previousBlock;
/**
* The (relative) stack size after the last visited instruction. This size
* is relative to the beginning of the current basic block, i.e., the true
* stack size after the last visited instruction is equal to the
* {@link MaxStackFrameSizeAndLocalsCalculator.LabelWrapper#inputStackSize} of the current basic block
* plus <tt>stackSize</tt>.
*/
private int stackSize;
/**
* The (relative) maximum stack size after the last visited instruction.
* This size is relative to the beginning of the current basic block, i.e.,
* the true maximum stack size after the last visited instruction is equal
* to the {@link MaxStackFrameSizeAndLocalsCalculator.LabelWrapper#inputStackSize} of the current basic
* block plus <tt>stackSize</tt>.
*/
private int maxStackSize;
/**
* Maximum stack size of this method.
*/
private int maxStack;
private final Collection<ExceptionHandler> exceptionHandlers = new LinkedList<ExceptionHandler>();
private final Map<Label, LabelWrapper> labelWrappersMap = new HashMap<Label, LabelWrapper>();
public MaxStackFrameSizeAndLocalsCalculator(int api, int access, String descriptor, MethodVisitor mv) {
super(api, access, descriptor, mv);
firstLabel = getLabelWrapper(new Label());
processLabel(firstLabel.label);
}
@Override
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
throw new AssertionError("We don't support visitFrame because currently nobody needs");
}
@Override
public void visitInsn(int opcode) {
increaseStackSize(FRAME_SIZE_CHANGE_BY_OPCODE[opcode]);
// if opcode == ATHROW or xRETURN, ends current block (no successor)
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
noSuccessor();
}
super.visitInsn(opcode);
}
@Override
public void visitIntInsn(int opcode, int operand) {
if (opcode != Opcodes.NEWARRAY) {
// updates current and max stack sizes only if it's not NEWARRAY
// (stack size variation is 0 for NEWARRAY and +1 BIPUSH or SIPUSH)
increaseStackSize(1);
}
super.visitIntInsn(opcode, operand);
}
@Override
public void visitVarInsn(int opcode, int var) {
increaseStackSize(FRAME_SIZE_CHANGE_BY_OPCODE[opcode]);
super.visitVarInsn(opcode, var);
}
@Override
public void visitTypeInsn(int opcode, @NotNull String type) {
if (opcode == Opcodes.NEW) {
// updates current and max stack sizes only if opcode == NEW
// (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
increaseStackSize(1);
}
super.visitTypeInsn(opcode, type);
}
@Override
public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) {
int stackSizeVariation;
// computes the stack size variation
char c = desc.charAt(0);
switch (opcode) {
case Opcodes.GETSTATIC:
stackSizeVariation = c == 'D' || c == 'J' ? 2 : 1;
break;
case Opcodes.PUTSTATIC:
stackSizeVariation = c == 'D' || c == 'J' ? -2 : -1;
break;
case Opcodes.GETFIELD:
stackSizeVariation = c == 'D' || c == 'J' ? 1 : 0;
break;
// case Constants.PUTFIELD:
default:
stackSizeVariation = c == 'D' || c == 'J' ? -3 : -2;
break;
}
increaseStackSize(stackSizeVariation);
super.visitFieldInsn(opcode, owner, name, desc);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
int argSize = Type.getArgumentsAndReturnSizes(desc);
int sizeVariation;
if (opcode == Opcodes.INVOKESTATIC) {
sizeVariation = (argSize & 0x03) - (argSize >> 2) + 1;
}
else {
sizeVariation = (argSize & 0x03) - (argSize >> 2);
}
increaseStackSize(sizeVariation);
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
@Override
public void visitInvokeDynamicInsn(@NotNull String name, @NotNull String desc, @NotNull Handle bsm, @NotNull Object... bsmArgs) {
int argSize = Type.getArgumentsAndReturnSizes(desc);
increaseStackSize((argSize & 0x03) - (argSize >> 2) + 1);
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
@Override
public void visitJumpInsn(int opcode, @NotNull Label label) {
if (currentBlock != null) {
// updates current stack size (max stack size unchanged
// because stack size variation always negative in this
// case)
stackSize += FRAME_SIZE_CHANGE_BY_OPCODE[opcode];
addSuccessor(getLabelWrapper(label), stackSize);
if (opcode == Opcodes.GOTO) {
noSuccessor();
}
}
super.visitJumpInsn(opcode, label);
}
@Override
public void visitLabel(@NotNull Label label) {
processLabel(label);
super.visitLabel(label);
}
private void processLabel(Label label) {
LabelWrapper wrapper = getLabelWrapper(label);
if (currentBlock != null) {
// ends current block (with one new successor)
currentBlock.outputStackMax = maxStackSize;
addSuccessor(wrapper, stackSize);
}
// begins a new current block
currentBlock = wrapper;
// resets the relative current and max stack sizes
stackSize = 0;
maxStackSize = 0;
if (previousBlock != null) {
previousBlock.nextLabel = wrapper;
}
previousBlock = wrapper;
}
@Override
public void visitLdcInsn(@NotNull Object cst) {
// computes the stack size variation
if (cst instanceof Long || cst instanceof Double) {
increaseStackSize(2);
}
else {
increaseStackSize(1);
}
super.visitLdcInsn(cst);
}
@Override
public void visitTableSwitchInsn(int min, int max, @NotNull Label dflt, @NotNull Label... labels) {
visitSwitchInsn(dflt, labels);
super.visitTableSwitchInsn(min, max, dflt, labels);
}
@Override
public void visitLookupSwitchInsn(@NotNull Label dflt, @NotNull int[] keys, @NotNull Label[] labels) {
visitSwitchInsn(dflt, labels);
super.visitLookupSwitchInsn(dflt, keys, labels);
}
private void visitSwitchInsn(Label dflt, Label[] labels) {
if (currentBlock != null) {
// updates current stack size (max stack size unchanged)
--stackSize;
// adds current block successors
addSuccessor(getLabelWrapper(dflt), stackSize);
for (Label label : labels) {
addSuccessor(getLabelWrapper(label), stackSize);
}
// ends current block
noSuccessor();
}
}
@Override
public void visitMultiANewArrayInsn(@NotNull String desc, int dims) {
if (currentBlock != null) {
increaseStackSize(dims - 1);
}
super.visitMultiANewArrayInsn(desc, dims);
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
// completes the control flow graph with exception handler blocks
for (ExceptionHandler handler : exceptionHandlers) {
LabelWrapper l = handler.start;
LabelWrapper e = handler.end;
while (l != e) {
l.addSuccessor(handler.handlerLabel, 0, true);
l = l.nextLabel;
}
}
/*
* control flow analysis algorithm: while the block stack is not
* empty, pop a block from this stack, update the max stack size,
* compute the true (non relative) begin stack size of the
* successors of this block, and push these successors onto the
* stack (unless they have already been pushed onto the stack).
* Note: by hypothesis, the {@link LabelWrapper#inputStackSize} of the
* blocks in the block stack are the true (non relative) beginning
* stack sizes of these blocks.
*/
int max = 0;
Stack<LabelWrapper> stack = new Stack<LabelWrapper>();
Set<LabelWrapper> pushed = new HashSet<LabelWrapper>();
stack.push(firstLabel);
pushed.add(firstLabel);
while (!stack.empty()) {
LabelWrapper current = stack.pop();
int start = current.inputStackSize;
int blockMax = start + current.outputStackMax;
// updates the global max stack size
if (blockMax > max) {
max = blockMax;
}
// analyzes the successors of the block
for (ControlFlowEdge edge : current.successors) {
LabelWrapper successor = edge.successor;
if (!pushed.contains(successor)) {
// computes its true beginning stack size...
successor.inputStackSize = edge.isExceptional ? 1 : start + edge.outputStackSize;
// ...and pushes it onto the stack
pushed.add(successor);
stack.push(successor);
}
}
}
this.maxStack = Math.max(this.maxStack, Math.max(maxStack, max));
super.visitMaxs(this.maxStack, maxLocals);
}
@Override
public void visitTryCatchBlock(
@NotNull Label start, @NotNull Label end,
@NotNull Label handler, String type
) {
ExceptionHandler exceptionHandler = new ExceptionHandler(
getLabelWrapper(start), getLabelWrapper(end), getLabelWrapper(handler)
);
exceptionHandlers.add(exceptionHandler);
super.visitTryCatchBlock(start, end, handler, type);
}
private static class ExceptionHandler {
private final LabelWrapper start;
private final LabelWrapper end;
private final LabelWrapper handlerLabel;
public ExceptionHandler(
LabelWrapper start,
LabelWrapper end,
LabelWrapper handlerLabel
) {
this.start = start;
this.end = end;
this.handlerLabel = handlerLabel;
}
}
private static class ControlFlowEdge {
private final LabelWrapper successor;
private final int outputStackSize;
private final boolean isExceptional;
public ControlFlowEdge(LabelWrapper successor, int outputStackSize, boolean isExceptional) {
this.successor = successor;
this.outputStackSize = outputStackSize;
this.isExceptional = isExceptional;
}
}
private static class LabelWrapper {
private final Label label;
private LabelWrapper nextLabel = null;
private final Collection<ControlFlowEdge> successors = new LinkedList<ControlFlowEdge>();
private int outputStackMax = 0;
private int inputStackSize = 0;
public LabelWrapper(Label label) {
this.label = label;
}
private void addSuccessor(LabelWrapper successor, int outputStackSize, boolean isExceptional) {
successors.add(new ControlFlowEdge(successor, outputStackSize, isExceptional));
}
}
// ------------------------------------------------------------------------
// Utility methods
// ------------------------------------------------------------------------
private LabelWrapper getLabelWrapper(final Label label) {
return ContainerUtil.getOrCreate(labelWrappersMap, label, new Factory<LabelWrapper>() {
@Override
public LabelWrapper create() {
return new LabelWrapper(label);
}
});
}
private void increaseStackSize(int variation) {
updateStackSize(stackSize + variation);
}
private void updateStackSize(int size) {
if (size > maxStackSize) {
maxStackSize = size;
}
stackSize = size;
}
private void addSuccessor(LabelWrapper successor, int outputStackSize) {
currentBlock.addSuccessor(successor, outputStackSize, false);
}
/**
* Ends the current basic block. This method must be used in the case where
* the current basic block does not have any successor.
*/
private void noSuccessor() {
if (currentBlock != null) {
currentBlock.outputStackMax = maxStackSize;
currentBlock = null;
}
}
}

View File

@@ -17,11 +17,17 @@
package org.jetbrains.jet.codegen.inline;
import com.google.common.collect.Lists;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.ClosureCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -34,9 +40,7 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.*;
import java.util.*;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.getReturnType;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.isAnonymousConstructorCall;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.isInvokeOnLambda;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.*;
public class MethodInliner {
@@ -63,6 +67,8 @@ public class MethodInliner {
private final InlineResult result;
private int lambdasFinallyBlocks;
/*
*
* @param node
@@ -115,8 +121,12 @@ public class MethodInliner {
}
resultNode.visitLabel(end);
processReturns(resultNode, labelOwner, remapReturn, end);
if (inliningContext.isRoot()) {
InternalFinallyBlockInliner.processInlineFunFinallyBlocks(resultNode, lambdasFinallyBlocks);
}
processReturns(resultNode, labelOwner, remapReturn, end);
//flush transformed node to output
resultNode.accept(new InliningInstructionAdapter(adapter));
@@ -127,7 +137,7 @@ public class MethodInliner {
final Deque<InvokeCall> currentInvokes = new LinkedList<InvokeCall>(invokeCalls);
MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
final Iterator<ConstructorInvocation> iterator = constructorInvocations.iterator();
@@ -186,6 +196,7 @@ public class MethodInliner {
int valueParamShift = getNextLocalIndex();//NB: don't inline cause it changes
putStackValuesIntoLocals(info.getInvokeParamsWithoutCaptured(), valueParamShift, this, desc);
addInlineMarker(this, true);
Parameters lambdaParameters = info.addAllParameters(nodeRemapper);
InlinedLambdaRemapper newCapturedRemapper =
@@ -207,6 +218,7 @@ public class MethodInliner {
Method delegate = typeMapper.mapSignature(info.getFunctionDescriptor()).getAsmMethod();
StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this);
setLambdaInlining(false);
addInlineMarker(this, false);
}
else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
assert invocation != null : "<init> call not corresponds to new call" + owner + " " + name;
@@ -227,6 +239,12 @@ public class MethodInliner {
}
}
@Override
public void visitMaxs(int stack, int locals) {
lambdasFinallyBlocks = resultNode.tryCatchBlocks.size();
super.visitMaxs(stack, locals);
}
};
node.accept(lambdaInliner);
@@ -338,7 +356,7 @@ public class MethodInliner {
AbstractInsnNode cur = node.instructions.getFirst();
int index = 0;
Set<LabelNode> deadLabels = new HashSet<LabelNode>();
Set<LabelNode> possibleDeadLabels = new HashSet<LabelNode>();
while (cur != null) {
Frame<SourceValue> frame = sources[index];
@@ -398,10 +416,15 @@ public class MethodInliner {
if (frame == null) {
//clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems
if (prevNode.getType() == AbstractInsnNode.LABEL) {
deadLabels.add((LabelNode) prevNode);
possibleDeadLabels.add((LabelNode) prevNode);
} else {
node.instructions.remove(prevNode);
}
} else {
//Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression)
//it may occurs that interval for default handler starts before catch start label, so this label seems as dead,
//but as result all this labels will be merged into one (see KT-5863)
possibleDeadLabels.remove(prevNode.getPrevious());
}
}
@@ -409,7 +432,7 @@ public class MethodInliner {
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
for (Iterator<TryCatchBlockNode> iterator = blocks.iterator(); iterator.hasNext(); ) {
TryCatchBlockNode block = iterator.next();
if (deadLabels.contains(block.start) && deadLabels.contains(block.end)) {
if (possibleDeadLabels.contains(block.start) && possibleDeadLabels.contains(block.end)) {
iterator.remove();
}
}
@@ -523,7 +546,6 @@ public class MethodInliner {
}
}
//TODO: check annotation on class - it's package part
//TODO: check it's external module
//TODO?: assert method exists in facade?
public String changeOwnerForExternalPackage(String type, int opcode) {
@@ -531,10 +553,18 @@ public class MethodInliner {
return type;
}
int i = type.indexOf('-');
if (i >= 0) {
return type.substring(0, i);
JvmClassName name = JvmClassName.byInternalName(type);
String packageClassInternalName = PackageClassUtils.getPackageClassInternalName(name.getPackageFqName());
if (type.startsWith(packageClassInternalName + '$')) {
VirtualFile virtualFile = InlineCodegenUtil.findVirtualFile(inliningContext.state.getProject(), type);
if (virtualFile != null) {
KotlinJvmBinaryClass klass = KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile);
if (klass != null && klass.getClassHeader().getSyntheticClassKind() == KotlinSyntheticClass.Kind.PACKAGE_PART) {
return packageClassInternalName;
}
}
}
return type;
}
@@ -542,18 +572,20 @@ public class MethodInliner {
public RuntimeException wrapException(@NotNull Exception originalException, @NotNull MethodNode node, @NotNull String errorSuffix) {
if (originalException instanceof InlineException) {
return new InlineException(errorPrefix + ": " + errorSuffix, originalException);
} else {
}
else {
return new InlineException(errorPrefix + ": " + errorSuffix + "\ncause: " +
InlineCodegen.getNodeText(node), originalException);
getNodeText(node), originalException);
}
}
@NotNull
public static List<FinallyBlockInfo> processReturns(@NotNull MethodNode node, @NotNull LabelOwner labelOwner, boolean remapReturn, Label endLabel) {
//process local and global returns (local substituted with goto end-label global kept unchanged)
public static List<ExternalFinallyBlockInfo> processReturns(@NotNull MethodNode node, @NotNull LabelOwner labelOwner, boolean remapReturn, Label endLabel) {
if (!remapReturn) {
return Collections.emptyList();
}
List<FinallyBlockInfo> result = new ArrayList<FinallyBlockInfo>();
List<ExternalFinallyBlockInfo> result = new ArrayList<ExternalFinallyBlockInfo>();
InsnList instructions = node.instructions;
AbstractInsnNode insnNode = instructions.getFirst();
while (insnNode != null) {
@@ -584,23 +616,25 @@ public class MethodInliner {
}
//genetate finally block before nonLocalReturn flag/return/goto
result.add(new FinallyBlockInfo(isLocalReturn ? insnNode : insnNode.getPrevious(), getReturnType(insnNode.getOpcode())));
result.add(new ExternalFinallyBlockInfo(isLocalReturn ? insnNode : insnNode.getPrevious(), getReturnType(insnNode.getOpcode())
));
}
insnNode = insnNode.getNext();
}
return result;
}
public static class FinallyBlockInfo {
public static class ExternalFinallyBlockInfo {
final AbstractInsnNode beforeIns;
final Type returnType;
public FinallyBlockInfo(AbstractInsnNode beforeIns, Type returnType) {
public ExternalFinallyBlockInfo(AbstractInsnNode beforeIns, Type returnType) {
this.beforeIns = beforeIns;
this.returnType = returnType;
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.inline
import java.util.ArrayList
import org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil.*
import kotlin.properties.Delegates
enum class TryCatchPosition {
START
END
INNER
}
trait IntervalWithHandler {
val startLabel: LabelNode
val endLabel: LabelNode
val handler: LabelNode
val `type`: String?
}
class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: Boolean) : IntervalWithHandler {
override val startLabel: LabelNode
get() = node.start
override val endLabel: LabelNode
get() = node.end
override val handler: LabelNode
get() = node.handler!!
override val `type`: String?
get() = node.`type`
}
class TryCatchBlockNodePosition(val nodeInfo: TryCatchBlockNodeInfo, var position: TryCatchPosition): IntervalWithHandler by nodeInfo
class TryBlockCluster<T : IntervalWithHandler>(val blocks: MutableList<T>) {
val defaultHandler: T?
get() = blocks.firstOrNull() { it.`type` == null }
}
fun <T: IntervalWithHandler> doClustering(blocks: List<T>) : List<TryBlockCluster<T>> {
[data] class TryBlockInterval(val startLabel: LabelNode, val endLabel: LabelNode)
val clusters = linkedMapOf<TryBlockInterval, TryBlockCluster<T>>()
blocks.forEach { block ->
val interval = TryBlockInterval(firstLabelInChain(block.startLabel), firstLabelInChain(block.endLabel))
val cluster = clusters.getOrPut(interval, {TryBlockCluster(arrayListOf())})
cluster.blocks.add(block)
}
return clusters.values().toList();
}

View File

@@ -33,10 +33,11 @@ import java.util.ArrayList;
import java.util.List;
public class OptimizationMethodVisitor extends MethodVisitor {
private static final int MAX_INSTRUCTIONS_SIZE_TO_OPTIMIZE = 5000;
private static final MethodTransformer MAIN_METHOD_TRANSFORMER = new RedundantNullCheckMethodTransformer(
new RedundantBoxingMethodTransformer(null)
);
private static final int MEMORY_LIMIT_BY_METHOD_MB = 50;
private static final MethodTransformer[] TRANSFORMERS = new MethodTransformer[]{
new RedundantNullCheckMethodTransformer(), new RedundantBoxingMethodTransformer(),
new RedundantGotoMethodTransformer(), new StoreStackBeforeInlineMethodTransformer()
};
private final MethodNode methodNode;
private final MethodVisitor delegate;
@@ -65,9 +66,10 @@ public class OptimizationMethodVisitor extends MethodVisitor {
super.visitEnd();
if (methodNode.instructions.size() > 0 &&
methodNode.instructions.size() <= MAX_INSTRUCTIONS_SIZE_TO_OPTIMIZE) {
MAIN_METHOD_TRANSFORMER.transform("fake", methodNode);
if (canBeAnalyzed(methodNode)) {
for (MethodTransformer transformer : TRANSFORMERS) {
transformer.transform("fake", methodNode);
}
}
methodNode.accept(new EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate));
@@ -113,4 +115,12 @@ public class OptimizationMethodVisitor extends MethodVisitor {
return traceMethodVisitor;
}
private static boolean canBeAnalyzed(@NotNull MethodNode node) {
int totalFramesSizeMb = node.instructions.size() *
(node.maxLocals + node.maxStack) / (1024 * 1024);
return node.instructions.size() > 0 &&
totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.optimization
import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
public class RedundantGotoMethodTransformer : MethodTransformer() {
/**
* Removes redundant GOTO's, i.e. to subsequent labels
*/
override fun transform(internalClassName: String, methodNode: MethodNode) {
val insns = methodNode.instructions.toArray()
val insnsToRemove = arrayListOf<AbstractInsnNode>()
val currentLabels = hashSetOf<LabelNode>()
for (insn in insns.reverse()) {
if (insn.isMeaningful) {
if (insn.getOpcode() == Opcodes.GOTO && (insn as JumpInsnNode).label in currentLabels) {
insnsToRemove.add(insn)
}
else {
currentLabels.clear()
}
continue
}
if (insn is LabelNode) {
currentLabels.add(insn)
}
}
for (insnToRemove in insnsToRemove) {
methodNode.instructions.remove(insnToRemove)
}
}
}
private val AbstractInsnNode.isMeaningful : Boolean get() =
when (this.getType()) {
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME -> false
else -> true
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.optimization
import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.jet.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.Type
import com.intellij.util.containers.Stack
class StoreStackBeforeInlineMethodTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
val frames = MethodTransformer.analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
if (needToProcess(methodNode, frames)) {
process(methodNode, frames)
}
else {
removeInlineMarkers(methodNode)
}
}
}
private fun needToProcess(node: MethodNode, frames: Array<Frame<BasicValue>?>): Boolean {
val insns = node.instructions.toArray()
var balance = 0
var isThereAnyInlineMarker = false
for ((insn, frame) in insns.zip(frames)) {
if (isInlineMarker(insn)) {
isThereAnyInlineMarker = true
// inline marker is not available
if (frame == null) return false
}
if (isBeforeInlineMarker(insn)) {
balance++
}
else if(isAfterInlineMarker(insn)) {
balance--
}
if (balance < 0) return false
}
return balance == 0 && isThereAnyInlineMarker
}
private fun isBeforeInlineMarker(insn: AbstractInsnNode) = isInlineMarker(insn, InlineCodegenUtil.INLINE_MARKER_BEFORE_METHOD_NAME)
private fun isAfterInlineMarker(insn: AbstractInsnNode) = isInlineMarker(insn, InlineCodegenUtil.INLINE_MARKER_AFTER_METHOD_NAME)
private fun isInlineMarker(insn: AbstractInsnNode, markerName: String? = null): Boolean {
return insn.getOpcode() == Opcodes.INVOKESTATIC &&
insn is MethodInsnNode &&
insn.owner == InlineCodegenUtil.INLINE_MARKER_CLASS_NAME &&
if (markerName != null) markerName == insn.name else true
}
private fun process(methodNode: MethodNode, frames: Array<Frame<BasicValue>?>) {
val insns = methodNode.instructions.toArray()
val storedValuesDescriptorsStack = Stack<StoredStackValuesDescriptor>()
var firstAvailableVarIndex = methodNode.maxLocals
var currentStoredValuesCount = 0
for ((insn, frame) in insns.zip(frames)) {
if (isBeforeInlineMarker(insn)) {
frame ?: throw AssertionError("process method shouldn't be called if frame is null before inline marker")
val desc = storeStackValues(methodNode, frame, insn, firstAvailableVarIndex, currentStoredValuesCount)
firstAvailableVarIndex += desc.storedStackSize
currentStoredValuesCount += desc.storedValuesCount
storedValuesDescriptorsStack.push(desc)
}
else if (isAfterInlineMarker(insn)) {
frame ?: throw AssertionError("process method shouldn't be called if frame is null before inline marker")
val desc = storedValuesDescriptorsStack.pop() ?:
throw AssertionError("should be non null becase markers are balanced")
loadStackValues(methodNode, frame, insn, desc)
firstAvailableVarIndex -= desc.storedStackSize
currentStoredValuesCount -= desc.storedValuesCount
}
if (isInlineMarker(insn)) {
methodNode.instructions.remove(insn)
}
}
}
private class StoredStackValuesDescriptor(
val values: List<BasicValue>,
val firstVariableIndex: Int,
val storedStackSize: Int,
alreadyStoredValuesCount: Int
) {
val nextFreeVarIndex : Int get() = firstVariableIndex + storedStackSize
val storedValuesCount: Int get() = values.size
val isStored: Boolean get() = storedValuesCount > 0
val totalValuesCountOnStackBeforeInline = alreadyStoredValuesCount + storedValuesCount
}
private fun removeInlineMarkers(node: MethodNode) {
for (insn in node.instructions.toArray()) {
if (isInlineMarker(insn)) {
node.instructions.remove(insn)
}
}
}
private fun storeStackValues(
node: MethodNode,
frame: Frame<BasicValue>,
beforeInlineMarker: AbstractInsnNode,
firstAvailableVarIndex: Int,
alreadyStoredValuesCount: Int
) : StoredStackValuesDescriptor {
var stackSize = 0
val values = frame.getStackValuesStartingFrom(alreadyStoredValuesCount)
for (value in values.reverse()) {
node.instructions.insertBefore(
beforeInlineMarker,
VarInsnNode(
value.getType()!!.getOpcode(Opcodes.ISTORE),
firstAvailableVarIndex + stackSize
)
)
stackSize += value.getSize()
}
node.updateMaxLocals(firstAvailableVarIndex + stackSize)
return StoredStackValuesDescriptor(values, firstAvailableVarIndex, stackSize, alreadyStoredValuesCount)
}
private fun loadStackValues(
node: MethodNode,
frame: Frame<BasicValue>,
afterInlineMarker: AbstractInsnNode,
desc: StoredStackValuesDescriptor
) {
if (!desc.isStored) return
val insns = node.instructions
var returnValueVarIndex = -1
var returnType : Type? = null
if (frame.getStackSize() != desc.totalValuesCountOnStackBeforeInline) {
// only returned value
assert(
(frame.getStackSize() - desc.totalValuesCountOnStackBeforeInline) == 1,
"Stack sizes should not differ by more than 1 (returned value)"
)
returnValueVarIndex = desc.nextFreeVarIndex
returnType = frame.getStack(frame.getStackSize() - 1)!!.getType()
node.updateMaxLocals(returnValueVarIndex + returnType!!.getSize())
insns.insertBefore(
afterInlineMarker,
VarInsnNode(returnType!!.getOpcode(Opcodes.ISTORE), returnValueVarIndex)
)
}
var currentVarIndex = desc.firstVariableIndex + desc.storedStackSize
for (value in desc.values) {
currentVarIndex -= value.getSize()
insns.insertBefore(
afterInlineMarker,
VarInsnNode(
value.getType()!!.getOpcode(Opcodes.ILOAD),
currentVarIndex
)
)
}
if (returnValueVarIndex != -1) {
insns.insertBefore(
afterInlineMarker,
VarInsnNode(returnType!!.getOpcode(Opcodes.ILOAD), returnValueVarIndex)
)
}
}
private fun <V : BasicValue> Frame<V>.getStackValuesStartingFrom(from: Int): List<V> =
IntRange(from, getStackSize() - 1).map { getStack(it) }.requireNoNulls()
private fun MethodNode.updateMaxLocals(newMaxLocals: Int) {
maxLocals = Math.max(maxLocals, newMaxLocals)
}

View File

@@ -211,22 +211,12 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
return v;
}
if (v instanceof BoxedBasicValue && w == BasicValue.UNINITIALIZED_VALUE) {
return v;
}
if (w instanceof BoxedBasicValue && v == BasicValue.UNINITIALIZED_VALUE) {
return w;
}
if (v instanceof BoxedBasicValue) {
onMergeFail((BoxedBasicValue) v);
return MIXED_VALUE;
}
if (w instanceof BoxedBasicValue) {
onMergeFail((BoxedBasicValue) w);
return MIXED_VALUE;
}
return super.merge(v, w);

View File

@@ -31,9 +31,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Frame;
import java.util.*;
public class RedundantBoxingMethodTransformer extends MethodTransformer {
public RedundantBoxingMethodTransformer(MethodTransformer methodTransformer) {
super(methodTransformer);
}
@Override
public void transform(@NotNull String internalClassName, @NotNull MethodNode node) {
@@ -55,8 +52,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
adaptInstructionsForBoxedValues(node, valuesToOptimize);
}
super.transform(internalClassName, node);
}
private static void interpretPopInstructionsForBoxedValues(

View File

@@ -28,18 +28,12 @@ import java.util.ArrayList;
import java.util.List;
public class RedundantNullCheckMethodTransformer extends MethodTransformer {
public RedundantNullCheckMethodTransformer(MethodTransformer methodTransformer) {
super(methodTransformer);
}
@Override
public void transform(@NotNull String internalClassName, @NotNull MethodNode methodNode) {
while (removeRedundantNullCheckPass(internalClassName, methodNode)) {
//do nothing
}
super.transform(internalClassName, methodNode);
}
private static boolean removeRedundantNullCheckPass(@NotNull String internalClassName, @NotNull MethodNode methodNode) {

View File

@@ -27,7 +27,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter;
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
public class OptimizationBasicInterpreter extends BasicInterpreter {
public static final BasicValue MIXED_VALUE = new BasicValue(Type.getObjectType("#"));
private static final BasicValue BOOLEAN_VALUE = new BasicValue(Type.BOOLEAN_TYPE);
private static final BasicValue CHAR_VALUE = new BasicValue(Type.CHAR_TYPE);
private static final BasicValue BYTE_VALUE = new BasicValue(Type.BYTE_TYPE);
@@ -93,7 +92,25 @@ public class OptimizationBasicInterpreter extends BasicInterpreter {
@NotNull BasicValue v, @NotNull BasicValue w
) {
if (!v.equals(w)) {
return MIXED_VALUE;
if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) {
return BasicValue.UNINITIALIZED_VALUE;
}
// if merge of two references then `lub` is java/lang/Object
// arrays also are BasicValues with reference type's
if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) {
return BasicValue.REFERENCE_VALUE;
}
assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays";
// if merge of something can be stored in int var (int, char, boolean, byte, character)
if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE &&
w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) {
return BasicValue.INT_VALUE;
}
return BasicValue.UNINITIALIZED_VALUE;
}
return v;
}

View File

@@ -16,17 +16,15 @@
package org.jetbrains.jet.codegen.optimization.transformer;
import kotlin.jvm.KotlinSignature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
import org.jetbrains.org.objectweb.asm.tree.analysis.*;
public abstract class MethodTransformer {
private final MethodTransformer delegate;
protected MethodTransformer(MethodTransformer delegate) {
this.delegate = delegate;
}
@KotlinSignature("fun <V : Value?> runAnalyzer(analyzer: Analyzer<V>, internalClassName: String, node: MethodNode): Array<Frame<V>?>")
@NotNull
protected static <V extends Value> Frame<V>[] runAnalyzer(
@NotNull Analyzer<V> analyzer,
@NotNull String internalClassName,
@@ -39,6 +37,9 @@ public abstract class MethodTransformer {
throw new RuntimeException(e);
}
}
@KotlinSignature("fun <V : Value?> analyze(internalClassName: String, node: MethodNode, interpreter: Interpreter<V>): Array<Frame<V>?>")
@NotNull
protected static <V extends Value> Frame<V>[] analyze(
@NotNull String internalClassName,
@NotNull MethodNode node,
@@ -47,9 +48,5 @@ public abstract class MethodTransformer {
return runAnalyzer(new Analyzer<V>(interpreter), internalClassName, node);
}
public void transform(@NotNull String internalClassName, @NotNull MethodNode methodNode) {
if (delegate != null) {
delegate.transform(internalClassName, methodNode);
}
}
abstract public void transform(@NotNull String internalClassName, @NotNull MethodNode methodNode);
}

View File

@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor;
@@ -48,6 +49,7 @@ import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.org.objectweb.asm.Type;
@@ -277,7 +279,7 @@ public class JetTypeMapper {
}
if (descriptor instanceof ClassDescriptor) {
Type asmType = getAsmType(bindingContext, (ClassDescriptor) descriptor);
Type asmType = computeAsmType((ClassDescriptor) descriptor.getOriginal());
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
return asmType;
}
@@ -294,9 +296,48 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("Unknown type " + jetType);
}
@NotNull
private Type computeAsmType(@NotNull ClassDescriptor klass) {
Type alreadyComputedType = bindingContext.get(ASM_TYPE, klass);
if (alreadyComputedType != null) {
return alreadyComputedType;
}
Type asmType = Type.getObjectType(computeAsmTypeImpl(klass));
assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType);
return asmType;
}
@NotNull
private String computeAsmTypeImpl(@NotNull ClassDescriptor klass) {
DeclarationDescriptor container = klass.getContainingDeclaration();
String name = SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
if (container instanceof PackageFragmentDescriptor) {
FqName fqName = ((PackageFragmentDescriptor) container).getFqName();
return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name;
}
if (container instanceof ScriptDescriptor) {
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name;
}
assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
switch (klass.getKind()) {
case ENUM_ENTRY:
return containerInternalName;
case CLASS_OBJECT:
return containerInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
default:
return containerInternalName + "$" + name;
}
}
@NotNull
public Type mapTraitImpl(@NotNull ClassDescriptor descriptor) {
return Type.getObjectType(getAsmType(bindingContext, descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
return Type.getObjectType(mapType(descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
}
@NotNull

View File

@@ -52,20 +52,13 @@ public class EnumSwitchCodegen extends SwitchCodegen {
v.swap();
v.invokevirtual(
mapping.getEnumClassInternalName(),
"ordinal",
Type.getMethodDescriptor(Type.INT_TYPE),
false
);
Type enumType = codegen.getState().getTypeMapper().mapClass(mapping.getEnumClassDescriptor());
v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false);
v.aload(Type.INT_TYPE);
}
@Override
protected void processConstant(
@NotNull CompileTimeConstant constant,
@NotNull Label entryLabel
) {
protected void processConstant(@NotNull CompileTimeConstant constant, @NotNull Label entryLabel) {
assert constant instanceof EnumValue : "guaranteed by usage contract";
putTransitionOnce(mapping.getIndexByEntry((EnumValue) constant), entryLabel);
}

View File

@@ -18,11 +18,9 @@ package org.jetbrains.jet.codegen.when;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.jet.codegen.ClassBuilder;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.EnumValue;
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -43,16 +41,8 @@ public class MappingClassesForWhenByEnumCodegen {
this.state = state;
}
public void generate(
@NotNull List<WhenByEnumsMapping> mappings,
@NotNull Type mappingsClass,
@NotNull JetFile srcFile
) {
ClassBuilder cb = state.getFactory().newVisitor(
JvmDeclarationOrigin.NO_ORIGIN,
mappingsClass,
srcFile
);
public void generate(@NotNull List<WhenByEnumsMapping> mappings, @NotNull Type mappingsClass, @NotNull JetFile srcFile) {
ClassBuilder cb = state.getFactory().newVisitor(JvmDeclarationOrigin.NO_ORIGIN, mappingsClass, srcFile);
cb.defineClass(
srcFile,
V1_6,
@@ -69,10 +59,7 @@ public class MappingClassesForWhenByEnumCodegen {
cb.done();
}
private static void generateFields(
@NotNull ClassBuilder cb,
@NotNull List<WhenByEnumsMapping> mappings
) {
private static void generateFields(@NotNull ClassBuilder cb, @NotNull List<WhenByEnumsMapping> mappings) {
for (WhenByEnumsMapping mapping : mappings) {
cb.newField(
JvmDeclarationOrigin.NO_ORIGIN,
@@ -84,10 +71,7 @@ public class MappingClassesForWhenByEnumCodegen {
}
}
private static void generateInitialization(
@NotNull ClassBuilder cb,
@NotNull List<WhenByEnumsMapping> mappings
) {
private void generateInitialization(@NotNull ClassBuilder cb, @NotNull List<WhenByEnumsMapping> mappings) {
MethodVisitor mv = cb.newMethod(
JvmDeclarationOrigin.NO_ORIGIN,
ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY
@@ -107,40 +91,26 @@ public class MappingClassesForWhenByEnumCodegen {
mv.visitEnd();
}
private static void generateInitializationForMapping(
private void generateInitializationForMapping(
@NotNull ClassBuilder cb,
@NotNull InstructionAdapter v,
@NotNull WhenByEnumsMapping mapping
) {
v.invokestatic(
mapping.getEnumClassInternalName(), "values",
Type.getMethodDescriptor(
AsmUtil.getArrayOf(mapping.getEnumClassInternalName())
),
false
);
Type enumType = state.getTypeMapper().mapClass(mapping.getEnumClassDescriptor());
v.invokestatic(enumType.getInternalName(), "values", Type.getMethodDescriptor(Type.getType("[" + enumType.getDescriptor())), false);
v.arraylength();
v.newarray(Type.INT_TYPE);
v.putstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR);
String enumClassDesc = Type.getObjectType(mapping.getEnumClassInternalName()).getDescriptor();
for (Map.Entry<EnumValue, Integer> item : mapping.enumValuesToIntMapping()) {
EnumValue enumEntry = item.getKey();
int mappedValue = item.getValue();
v.getstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR);
v.getstatic(
mapping.getEnumClassInternalName(),
enumEntry.getValue().getName().asString(),
enumClassDesc
);
v.invokevirtual(
mapping.getEnumClassInternalName(), "ordinal",
Type.getMethodDescriptor(Type.INT_TYPE),
false
);
v.getstatic(enumType.getInternalName(), enumEntry.getValue().getName().asString(), enumType.getDescriptor());
v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false);
v.iconst(mappedValue);
v.astore(Type.INT_TYPE);
}

View File

@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen.when;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.resolve.constants.EnumValue;
import java.util.HashMap;
@@ -27,13 +28,17 @@ public class WhenByEnumsMapping {
private static final String MAPPINGS_CLASS_NAME_POSTFIX = "$WhenMappings";
private final Map<EnumValue, Integer> map = new HashMap<EnumValue, Integer>();
private final String enumClassInternalName;
private final ClassDescriptor enumClassDescriptor;
private final String outerClassInternalNameForExpression;
private final String mappingsClassInternalName;
private final int fieldNumber;
public WhenByEnumsMapping(String enumClassInternalName, String outerClassInternalNameForExpression, int fieldNumber) {
this.enumClassInternalName = enumClassInternalName;
public WhenByEnumsMapping(
@NotNull ClassDescriptor enumClassDescriptor,
@NotNull String outerClassInternalNameForExpression,
int fieldNumber
) {
this.enumClassDescriptor = enumClassDescriptor;
this.outerClassInternalNameForExpression = outerClassInternalNameForExpression;
this.mappingsClassInternalName = outerClassInternalNameForExpression + MAPPINGS_CLASS_NAME_POSTFIX;
this.fieldNumber = fieldNumber;
@@ -45,7 +50,7 @@ public class WhenByEnumsMapping {
return result;
}
public void putFirstTime(EnumValue value, int index) {
public void putFirstTime(@NotNull EnumValue value, int index) {
if (!map.containsKey(value)) {
map.put(value, index);
}
@@ -55,22 +60,27 @@ public class WhenByEnumsMapping {
return map.size();
}
@NotNull
public String getFieldName() {
return MAPPING_ARRAY_FIELD_PREFIX + fieldNumber;
}
public String getEnumClassInternalName() {
return enumClassInternalName;
@NotNull
public ClassDescriptor getEnumClassDescriptor() {
return enumClassDescriptor;
}
@NotNull
public String getOuterClassInternalNameForExpression() {
return outerClassInternalNameForExpression;
}
@NotNull
public String getMappingsClassInternalName() {
return mappingsClassInternalName;
}
@NotNull
public Iterable<Map.Entry<EnumValue, Integer>> enumValuesToIntMapping() {
return map.entrySet();
}

View File

@@ -164,6 +164,6 @@ public class BuiltInsSerializer(val out: PrintStream?) {
}
fun getFileName(classDescriptor: ClassDescriptor): String {
return BuiltInsSerializationUtil.getClassMetadataPath(DeserializedResolverUtils.getClassId(classDescriptor))
return BuiltInsSerializationUtil.getClassMetadataPath(DeserializedResolverUtils.getClassId(classDescriptor))!!
}
}

View File

@@ -23,6 +23,8 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
public abstract class CommonCompilerArguments {
public static final String PLUGIN_OPTION_FORMAT = "<pluginId>:<optionName>=<value>";
@Argument(value = "nowarn", description = "Generate no warnings")
public boolean suppressWarnings;
@@ -38,6 +40,14 @@ public abstract class CommonCompilerArguments {
@Argument(value = "X", description = "Print a synopsis of advanced options")
public boolean extraHelp;
@Argument(value = "Xplugin", description = "Load a plugin from the given classpath")
@ValueDescription("<path>")
public String[] pluginClasspaths;
@Argument(value = "P", description = "Pass an option to a plugin")
@ValueDescription(PLUGIN_OPTION_FORMAT)
public String[] pluginOptions;
public List<String> freeArgs = new SmartList<String>();
@NotNull

View File

@@ -40,6 +40,7 @@ import org.jetbrains.jet.lang.resolve.kotlin.incremental.cache.IncrementalCacheP
import org.jetbrains.jet.utils.KotlinPaths;
import org.jetbrains.jet.utils.KotlinPathsFromHomeDir;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException;
import java.io.File;
import java.util.Collections;
@@ -87,6 +88,15 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
return INTERNAL_ERROR;
}
try {
PluginCliParser.processPluginOptions(arguments, configuration);
}
catch (CliOptionProcessingException e) {
// TODO Print usage?
messageCollector.report(CompilerMessageSeverity.ERROR, e.getMessage(), CompilerMessageLocation.NO_LOCATION);
return INTERNAL_ERROR;
}
if (!arguments.script &&
arguments.module == null &&
arguments.freeArgs.isEmpty() &&

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.cli.jvm
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments
import kotlin.platform.*
import java.util.jar.JarFile
import java.util.jar.Attributes
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
import java.util.regex.Pattern
import org.jetbrains.jet.utils.valuesToMap
import org.jetbrains.jet.config.CompilerConfiguration
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.compiler.plugin.CliOption
public object PluginCliParser {
public val PLUGIN_ARGUMENT_PREFIX: String = "plugin:"
private fun getCommandLineProcessors(arguments: CommonCompilerArguments): Collection<CommandLineProcessor> {
return arguments.pluginClasspaths!!.map {
loadCommandLineProcessor(JarFile(it).getManifest()?.getAttributes("org.jetbrains.kotlin.compiler.plugin"))
}.filterNotNull()
}
private fun loadCommandLineProcessor(attributes: Attributes?): CommandLineProcessor? {
if (attributes == null) return null
val processorClassName = attributes.getValue("CommandLineProcessor")
if (processorClassName == null) return null
try {
val processorClass = Class.forName(processorClassName)
return processorClass.newInstance() as CommandLineProcessor
}
catch (e: Throwable) {
throw CliOptionProcessingException("Loading plugin component failed: $processorClassName", e)
}
}
[platformStatic]
fun processPluginOptions(arguments: CommonCompilerArguments, configuration: CompilerConfiguration) {
val optionValuesByPlugin = arguments.pluginOptions!!.map { parsePluginOption(it) }.groupBy {
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
it.optionName
}
val processors = getCommandLineProcessors(arguments)
for (processor in processors) {
val declaredOptions = processor.pluginOptions.valuesToMap { it.name }
val optionsToValues = MultiMap<CliOption, PluginOptionValue>()
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
val option = declaredOptions[optionValue!!.optionName]
if (option == null) {
throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
}
optionsToValues.putValue(option, optionValue)
}
for (option in processor.pluginOptions) {
val values = optionsToValues[option]
if (option.required && values.isEmpty()) {
throw CliOptionProcessingException("Required plugin option not present: ${processor.pluginId}:${option.name}")
}
if (!option.allowMultipleOccurrences && values.size() > 1) {
throw CliOptionProcessingException("Multiple values not allowed for plugin option ${processor.pluginId}:${option.name}")
}
for (value in values) {
processor.processOption(option, value.value, configuration)
}
}
}
}
private class PluginOptionValue(
val pluginId: String,
val optionName: String,
val value: String
) {
override fun toString() = "$pluginId:$optionName=$value"
}
private fun parsePluginOption(argumentValue: String): PluginOptionValue? {
val pattern = Pattern.compile("""^([^:]*):([^=]*)=(.*)$""")
val matcher = pattern.matcher(argumentValue)
if (matcher.matches()) {
return PluginOptionValue(matcher.group(1)!!, matcher.group(2)!!, matcher.group(3)!!)
}
return null
}
}

View File

@@ -97,6 +97,12 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport
return module;
}
@TestOnly
@Nullable
public ModuleDescriptorImpl getLightClassModule() {
return module;
}
@TestOnly
public void setModule(@NotNull ModuleDescriptorImpl module) {
assert this.module == null : "module already configured: " + module;

View File

@@ -48,8 +48,10 @@ import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys;
import org.jetbrains.jet.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.jet.config.CommonConfigurationKeys;
import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.extensions.ExternalDeclarationsProvider;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -59,6 +61,7 @@ import org.jetbrains.jet.lang.resolve.lazy.declarations.CliDeclarationProviderFa
import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactoryService;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar;
import java.io.File;
import java.util.ArrayList;
@@ -208,6 +211,13 @@ public class JetCoreEnvironment {
configuration.getList(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY));
project.registerService(VirtualFileFinderFactory.class, new CliVirtualFileFinderFactory(classPath));
for (ComponentRegistrar registrar : configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) {
registrar.registerProjectComponents(project, configuration);
}
ExternalDeclarationsProvider.OBJECT$.registerExtensionPoint(project);
ExpressionCodegenExtension.OBJECT$.registerExtensionPoint(project);
}
// made public for Upsource

View File

@@ -23,6 +23,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.impl.PsiFileFactoryImpl;
@@ -49,8 +50,8 @@ import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetScript;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
@@ -77,6 +78,7 @@ import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.registerClassNameForScript;
import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
public class ReplInterpreter {
private int lineNumber = 0;
@@ -366,8 +368,11 @@ public class ReplInterpreter {
ScriptDescriptor earlierDescriptor = pair.first;
Type earlierClassType = pair.second;
registerClassNameForScript(state.getBindingTrace(), earlierDescriptor, earlierClassType);
earlierScriptDescriptors.add(earlierDescriptor);
PsiElement jetScript = descriptorToDeclaration(earlierDescriptor);
if (jetScript != null) {
registerClassNameForScript(state.getBindingTrace(), (JetScript) jetScript, earlierClassType);
earlierScriptDescriptors.add(earlierDescriptor);
}
}
state.setEarlierScriptsForReplInterpreter(earlierScriptDescriptors);
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
<orderEntry type="library" name="intellij-core" level="project" />
<orderEntry type="module" module-name="frontend" />
</component>
</module>

View File

@@ -33,6 +33,10 @@ import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.jet.analyzer.ModuleInfo
import org.jetbrains.jet.analyzer.ModuleContent
import org.jetbrains.jet.di.InjectorForLazyResolveWithJava
import org.jetbrains.jet.lang.psi.JetFile
import java.util.ArrayList
import org.jetbrains.jet.extensions.ExternalDeclarationsProvider
import kotlin.platform.platformStatic
public class JvmResolverForModule(
override val lazyResolveSession: ResolveSession,
@@ -54,8 +58,9 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
resolverForProject: ResolverForProject<M, JvmResolverForModule>
): JvmResolverForModule {
val (syntheticFiles, moduleContentScope) = moduleContent
val filesToAnalyze = getAllFilesToAnalyze(project, syntheticFiles)
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
project, globalContext.storageManager, syntheticFiles, moduleContentScope
project, globalContext.storageManager, filesToAnalyze, moduleContentScope
)
val moduleClassResolver = ModuleClassResolverImpl { javaClass ->
@@ -76,4 +81,12 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
override val defaultImports = TopDownAnalyzerFacadeForJVM.DEFAULT_IMPORTS
override val platformToKotlinClassMap = JavaToKotlinClassMap.getInstance()
public platformStatic fun getAllFilesToAnalyze(project: Project, baseFiles: Collection<JetFile>): List<JetFile> {
val allFiles = ArrayList(baseFiles)
for (externalDeclarationsProvider in ExternalDeclarationsProvider.getInstances(project)) {
allFiles.addAll(externalDeclarationsProvider.getExternalDeclarations())
}
return allFiles
}
}

View File

@@ -75,6 +75,8 @@ public enum TopDownAnalyzerFacadeForJVM {
false
);
List<JetFile> allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, files);
InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(project, topDownAnalysisParameters, trace, module);
try {
List<PackageFragmentProvider> additionalProviders = new ArrayList<PackageFragmentProvider>();
@@ -85,7 +87,7 @@ public enum TopDownAnalyzerFacadeForJVM {
additionalProviders.add(
new IncrementalPackageFragmentProvider(
files, module, globalContext.getStorageManager(), injector.getDeserializationGlobalContextForJava(),
allFiles, module, globalContext.getStorageManager(), injector.getDeserializationGlobalContextForJava(),
incrementalCache, moduleId, injector.getJavaDescriptorResolver()
)
);
@@ -93,7 +95,7 @@ public enum TopDownAnalyzerFacadeForJVM {
}
additionalProviders.add(injector.getJavaDescriptorResolver().getPackageFragmentProvider());
injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, files, additionalProviders);
injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, allFiles, additionalProviders);
return AnalyzeExhaust.success(trace.getBindingContext(), module);
}
finally {

View File

@@ -81,8 +81,9 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
@NotNull
protected abstract byte[] getFileContents();
// TODO public to be accessible in class object of subclass, workaround for KT-3974
@Nullable
protected static <T extends FileBasedKotlinClass> T create(
public static <T extends FileBasedKotlinClass> T create(
@NotNull byte[] fileContents,
@NotNull Function3<ClassId, KotlinClassHeader, InnerClassesInfo, T> factory
) {

View File

@@ -56,8 +56,12 @@ public class PackagePartClassUtils {
String fileName = FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.getName()));
// path hashCode to prevent same name / different path collision
String srcName = facadeFqName.shortName().asString() + "-" + replaceSpecialSymbols(fileName) + "-" + Integer.toHexString(
getPathHashCode(file));
String srcName = String.format(
"%s$%s$%08x",
facadeFqName.shortName().asString(),
replaceSpecialSymbols(fileName),
getPathHashCode(file)
);
return facadeFqName.parent().child(Name.identifier(srcName));
}

View File

@@ -23,17 +23,17 @@ import org.jetbrains.jet.lang.resolve.java.JvmClassName
import java.util.HashMap
import java.io.File
public fun IncrementalCache.getPackagesWithRemovedFiles(compiledSourceFiles: Collection<JetFile>): Collection<FqName> {
return getRemovedPackageParts(compiledSourceFiles).map { it.getFqNameForClassNameWithoutDollars().parent() }
public fun IncrementalCache.getPackagesWithRemovedFiles(sourceFilesToCompile: Collection<JetFile>): Collection<FqName> {
return getRemovedPackageParts(sourceFilesToCompile).map { it.getPackageFqName() }
}
public fun IncrementalCache.getRemovedPackageParts(compiledSourceFiles: Collection<JetFile>): Collection<JvmClassName> {
val compiledSourceFilesToFqName = HashMap<File, String>()
for (sourceFile in compiledSourceFiles) {
compiledSourceFilesToFqName[File(sourceFile.getVirtualFile()!!.getPath())] = sourceFile.getPackageFqName().asString()
public fun IncrementalCache.getRemovedPackageParts(sourceFilesToCompile: Collection<JetFile>): Collection<JvmClassName> {
val sourceFilesToFqName = HashMap<File, String>()
for (sourceFile in sourceFilesToCompile) {
sourceFilesToFqName[File(sourceFile.getVirtualFile()!!.getPath())] = sourceFile.getPackageFqName().asString()
}
return getRemovedPackageParts(compiledSourceFilesToFqName).map { JvmClassName.byInternalName(it) }
return getRemovedPackageParts(sourceFilesToFqName).map { JvmClassName.byInternalName(it) }
}
public fun IncrementalCache.getPackageData(fqName: FqName): ByteArray? {

View File

@@ -56,6 +56,7 @@ public class IncrementalPackageFragmentProvider(
).toSet()
val fqNameToSubFqNames = MultiMap<FqName, FqName>()
val fqNameToPackageFragment = HashMap<FqName, PackageFragmentDescriptor>()
val fqNamesToLoad: Set<FqName>
;{
fun createPackageFragment(fqName: FqName) {
@@ -72,13 +73,12 @@ public class IncrementalPackageFragmentProvider(
fqNameToPackageFragment[fqName] = IncrementalPackageFragment(fqName)
}
for (source in PackagePartClassUtils.getPackageFilesWithCallables(sourceFiles)) {
createPackageFragment(source.getPackageFqName())
}
fqNamesToLoad = (
PackagePartClassUtils.getPackageFilesWithCallables(sourceFiles).map { it.getPackageFqName() }
+ incrementalCache.getPackagesWithRemovedFiles(sourceFiles)
).toSet()
for (fqName in incrementalCache.getPackagesWithRemovedFiles(sourceFiles)) {
createPackageFragment(fqName)
}
fqNamesToLoad.forEach { createPackageFragment(it) }
}
override fun getSubPackagesOf(fqName: FqName): Collection<FqName> {
@@ -95,12 +95,17 @@ public class IncrementalPackageFragmentProvider(
get() = this@IncrementalPackageFragmentProvider.moduleId
val _memberScope: NotNullLazyValue<JetScope> = storageManager.createLazyValue {
val packageDataBytes = incrementalCache.getPackageData(fqName)
if (packageDataBytes == null) {
if (fqName !in fqNamesToLoad) {
JetScope.EMPTY
}
else {
IncrementalPackageScope(JavaProtoBufUtil.readPackageDataFrom(packageDataBytes))
val packageDataBytes = incrementalCache.getPackageData(fqName)
if (packageDataBytes == null) {
JetScope.EMPTY
}
else {
IncrementalPackageScope(JavaProtoBufUtil.readPackageDataFrom(packageDataBytes))
}
}
}

View File

@@ -23,7 +23,7 @@ import java.util.HashMap
import java.io.File
public trait IncrementalCache {
public fun getRemovedPackageParts(compiledSourceFilesToFqName: Map<File, String>): Collection<String>
public fun getRemovedPackageParts(sourceFilesToCompileAndFqNames: Map<File, String>): Collection<String>
public fun getPackageData(fqName: String): ByteArray?

View File

@@ -13,6 +13,7 @@
<orderEntry type="module" module-name="util" />
<orderEntry type="module" module-name="serialization" />
<orderEntry type="module" module-name="descriptors" exported="" />
<orderEntry type="module" module-name="plugin-api" exported="" />
</component>
</module>

View File

@@ -38,15 +38,23 @@ public trait ResolverForModule {
public trait ResolverForProject<M : ModuleInfo, R : ResolverForModule> {
public fun resolverForModule(moduleInfo: M): R
public fun descriptorForModule(moduleInfo: M): ModuleDescriptor
val allModules: Collection<M>
}
public class EmptyResolverForProject<M : ModuleInfo, R : ResolverForModule> : ResolverForProject<M, R> {
override fun resolverForModule(moduleInfo: M): R = throw IllegalStateException("Should not be called for $moduleInfo")
override fun descriptorForModule(moduleInfo: M) = throw IllegalStateException("Should not be called for $moduleInfo")
override val allModules: Collection<M> = listOf()
}
public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>(
val descriptorByModule: Map<M, ModuleDescriptorImpl>
val descriptorByModule: Map<M, ModuleDescriptorImpl>,
val delegateResolver: ResolverForProject<M, R> = EmptyResolverForProject()
) : ResolverForProject<M, R> {
val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, R> = HashMap()
private val allModules: Collection<M> by Delegates.lazy {
descriptorByModule.keySet()
override val allModules: Collection<M> by Delegates.lazy {
(descriptorByModule.keySet() + delegateResolver.allModules).toSet()
}
private fun assertCorrectModuleInfo(moduleInfo: M) {
@@ -57,13 +65,13 @@ public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>(
override fun resolverForModule(moduleInfo: M): R {
assertCorrectModuleInfo(moduleInfo)
val descriptor = descriptorByModule[moduleInfo]!!
val descriptor = descriptorByModule[moduleInfo] ?: return delegateResolver.resolverForModule(moduleInfo)
return resolverByModuleDescriptor[descriptor]!!
}
override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
assertCorrectModuleInfo(moduleInfo)
return descriptorByModule[moduleInfo]!!
return descriptorByModule[moduleInfo] ?: return delegateResolver.descriptorForModule(moduleInfo) as ModuleDescriptorImpl
}
}
@@ -111,7 +119,8 @@ public trait AnalyzerFacade<out A : ResolverForModule, in P : PlatformAnalysisPa
project: Project,
modules: Collection<M>,
modulesContent: (M) -> ModuleContent,
platformParameters: P
platformParameters: P,
delegateResolver: ResolverForProject<M, A> = EmptyResolverForProject()
): ResolverForProject<M, A> {
fun createResolverForProject(): ResolverForProjectImpl<M, A> {
@@ -120,7 +129,7 @@ public trait AnalyzerFacade<out A : ResolverForModule, in P : PlatformAnalysisPa
module ->
descriptorByModule[module] = ModuleDescriptorImpl(module.name, defaultImports, platformToKotlinClassMap)
}
return ResolverForProjectImpl(descriptorByModule)
return ResolverForProjectImpl(descriptorByModule, delegateResolver)
}
val resolverForProject = createResolverForProject()

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.extensions
import org.jetbrains.jet.lang.psi.JetFile
public trait ExternalDeclarationsProvider {
class object : ProjectExtensionDescriptor<ExternalDeclarationsProvider>(
"org.jetbrains.kotlin.externalDeclarationsProvider",
javaClass<ExternalDeclarationsProvider>()
)
public fun getExternalDeclarations(): Collection<JetFile>
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.extensions
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionPoint
public open class ProjectExtensionDescriptor<T>(name: String, private val extensionClass: Class<T>) {
public val extensionPointName: ExtensionPointName<T> = ExtensionPointName.create(name)!!
public fun registerExtensionPoint(project: Project) {
Extensions.getArea(project).registerExtensionPoint(
extensionPointName.getName()!!,
extensionClass.getName(),
ExtensionPoint.Kind.INTERFACE
)
}
public fun registerExtension(project: Project, extension: T) {
Extensions.getArea(project).getExtensionPoint(extensionPointName).registerExtension(extension)
}
public fun getInstances(project: Project): Collection<T> {
val projectArea = Extensions.getArea(project)
if (!projectArea.hasExtensionPoint(extensionPointName.getName()!!)) return listOf()
return projectArea.getExtensionPoint(extensionPointName).getExtensions().toList()
}
}

View File

@@ -49,7 +49,5 @@ public class ReturnValueInstruction(
return ReturnValueInstruction((element as JetExpression), lexicalScope, newLabel, returnedValue)
}
public val resultExpression: JetExpression =
element.let{ if (it is JetReturnExpression) it.getReturnedExpression()!! else element as JetExpression }
public val returnExpressionIfAny: JetReturnExpression? = element as? JetReturnExpression
}

View File

@@ -446,6 +446,7 @@ public interface Errors {
DiagnosticFactory2<JetExpression, String, Collection<? extends ResolvedCall<?>>> DELEGATE_SPECIAL_FUNCTION_AMBIGUITY = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<JetExpression, String, Collection<? extends ResolvedCall<?>>> DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE = DiagnosticFactory2.create(ERROR);
DiagnosticFactory3<JetExpression, String, JetType, JetType> DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR);
DiagnosticFactory2<JetExpression, String, Collection<? extends ResolvedCall<?>>> DELEGATE_PD_METHOD_NONE_APPLICABLE = DiagnosticFactory2.create(WARNING);
DiagnosticFactory1<JetSimpleNameExpression, JetType> COMPARE_TO_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);

View File

@@ -285,6 +285,7 @@ public class DefaultErrorMessages {
STRING, AMBIGUOUS_CALLS);
MAP.put(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH, "The ''{0}'' function of property delegate is expected to return ''{1}'', but returns ''{2}''",
STRING, RENDER_TYPE, RENDER_TYPE);
MAP.put(DELEGATE_PD_METHOD_NONE_APPLICABLE, "''{0}'' method may be missing. None of the following functions will be called: {1}", STRING, AMBIGUOUS_CALLS);
MAP.put(COMPARE_TO_TYPE_MISMATCH, "''compareTo()'' must return kotlin.Int, but returns {0}", RENDER_TYPE);

View File

@@ -216,9 +216,8 @@ public class JetPsiFactory(private val project: Project) {
return createClass("class A(){}").getBody()!!
}
public fun createParameter(name: String, `type`: String): JetParameter {
val function = createFunction("fun foo(" + name + " : " + `type` + ") {}")
return function.getValueParameters().first()
public fun createParameter(text : String): JetParameter {
return createClass("class A($text)").getPrimaryConstructorParameters().first()
}
public fun createParameterList(text: String): JetParameterList {

View File

@@ -335,3 +335,14 @@ public fun JetExpression.isFunctionLiteralOutsideParentheses(): Boolean {
else -> false
}
}
public fun PsiElement.siblings(forward: Boolean = true, withItself: Boolean = true): Stream<PsiElement> {
val stepFun = if (forward) { (e: PsiElement) -> e.getNextSibling() } else { (e: PsiElement) -> e.getPrevSibling() }
val stream = stream(this, stepFun)
return if (withItself) stream else stream.drop(1)
}
public fun PsiElement.parents(withItself: Boolean = true): Stream<PsiElement> {
val stream = stream(this) { if (it is PsiFile) null else it.getParent() }
return if (withItself) stream else stream.drop(1)
}

View File

@@ -113,6 +113,8 @@ public interface BindingContext {
WritableSlice<PropertyAccessorDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice();
WritableSlice<PropertyAccessorDescriptor, Call> DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice();
WritableSlice<PropertyDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice();
WritableSlice<JetMultiDeclarationEntry, ResolvedCall<FunctionDescriptor>> COMPONENT_RESOLVED_CALL = Slices.createSimpleSlice();
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_GET = Slices.createSimpleSlice();

View File

@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull;
@@ -26,17 +25,13 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lexer.JetModifierKeywordToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.Box;
import org.jetbrains.jet.util.ReenteringLazyValueComputationException;
@@ -553,6 +548,9 @@ public class BodyResolver {
delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
trace, accessorScope);
}
delegatedPropertyResolver.resolveDelegatedPropertyPDMethod(propertyDescriptor, delegateExpression, delegateType,
trace, accessorScope);
}
public void resolvePropertyInitializer(

View File

@@ -61,6 +61,8 @@ public class DelegatedPropertyResolver {
@NotNull
private CallResolver callResolver;
private static final String PD_METHOD_NAME = "propertyDelegated";
@Inject
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
this.expressionTypingServices = expressionTypingServices;
@@ -115,6 +117,55 @@ public class DelegatedPropertyResolver {
resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, scope, false);
}
@NotNull
private static JetExpression createExpressionForPropertyMetadata(
@NotNull JetPsiFactory psiFactory,
@NotNull PropertyDescriptor propertyDescriptor
) {
return psiFactory.createExpression(KotlinBuiltIns.getInstance().getPropertyMetadataImpl().getName().asString() +
"(\"" +
propertyDescriptor.getName().asString() +
"\")");
}
public void resolveDelegatedPropertyPDMethod(
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull JetExpression delegateExpression,
@NotNull JetType delegateType,
@NotNull BindingTrace trace,
@NotNull JetScope scope
) {
TemporaryBindingTrace traceToResolvePDMethod = TemporaryBindingTrace.create(trace, "Trace to resolve propertyDelegated method in delegated property");
ExpressionTypingContext context = ExpressionTypingContext.newContext(
expressionTypingServices, traceToResolvePDMethod, scope,
DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE);
List<JetExpression> arguments = Lists.newArrayList();
JetPsiFactory psiFactory = JetPsiFactory(delegateExpression);
arguments.add(createExpressionForPropertyMetadata(psiFactory, propertyDescriptor));
Name functionName = Name.identifier(PD_METHOD_NAME);
JetReferenceExpression fakeCalleeExpression = psiFactory.createSimpleName(functionName.asString());
ExpressionReceiver receiver = new ExpressionReceiver(delegateExpression, delegateType);
Call call = CallMaker.makeCallWithExpressions(fakeCalleeExpression, receiver, null, fakeCalleeExpression, arguments, Call.CallType.DEFAULT);
OverloadResolutionResults<FunctionDescriptor> functionResults =
callResolver.resolveCallWithGivenName(context, call, fakeCalleeExpression, functionName);
if (!functionResults.isSuccess()) {
String expectedFunction = renderCall(call, traceToResolvePDMethod.getBindingContext());
if (functionResults.isIncomplete() || functionResults.isSingleResult() ||
functionResults.getResultCode() == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) {
trace.report(DELEGATE_PD_METHOD_NONE_APPLICABLE.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
} else if (functionResults.isAmbiguity()) {
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY
.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
}
return;
}
trace.record(DELEGATED_PROPERTY_PD_RESOLVED_CALL, propertyDescriptor, functionResults.getResultingCall());
}
/* Resolve get() or set() methods from delegate */
private void resolveDelegatedPropertyConventionMethod(
@NotNull PropertyDescriptor propertyDescriptor,
@@ -179,10 +230,7 @@ public class DelegatedPropertyResolver {
JetPsiFactory psiFactory = JetPsiFactory(delegateExpression);
arguments.add(psiFactory.createExpression(hasThis ? "this" : "null"));
arguments.add(psiFactory.createExpression(KotlinBuiltIns.getInstance().getPropertyMetadataImpl().getName().asString() +
"(\"" +
propertyDescriptor.getName().asString() +
"\")"));
arguments.add(createExpressionForPropertyMetadata(psiFactory, propertyDescriptor));
if (!isGet) {
JetReferenceExpression fakeArgument = (JetReferenceExpression) createFakeExpressionOfType(expressionTypingServices.getProject(), trace,

View File

@@ -421,7 +421,7 @@ public class DescriptorResolver {
Annotations.EMPTY,
COPY_METHOD_NAME,
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
classDescriptor.getSource()
);
List<ValueParameterDescriptor> parameterDescriptors = Lists.newArrayList();

View File

@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.jet.renderer.DescriptorRendererBuilder;
@@ -69,66 +70,85 @@ public class MemberComparator implements Comparator<DeclarationDescriptor> {
return namesCompareTo;
}
if (!(o1 instanceof CallableDescriptor) || !(o2 instanceof CallableDescriptor)) {
assert false : "Descriptors must be callable:\n" + o1 + "\n" + o2;
}
if (o1 instanceof CallableDescriptor && o2 instanceof CallableDescriptor) {
CallableDescriptor c1 = (CallableDescriptor) o1;
CallableDescriptor c2 = (CallableDescriptor) o2;
CallableDescriptor c1 = (CallableDescriptor)o1;
CallableDescriptor c2 = (CallableDescriptor)o2;
ReceiverParameterDescriptor c1ReceiverParameter = c1.getReceiverParameter();
ReceiverParameterDescriptor c2ReceiverParameter = c2.getReceiverParameter();
assert (c1ReceiverParameter != null) == (c2ReceiverParameter != null);
if (c1ReceiverParameter != null) {
String r1 = RENDERER.renderType(c1ReceiverParameter.getType());
String r2 = RENDERER.renderType(c2ReceiverParameter.getType());
int receiversCompareTo = r1.compareTo(r2);
if (receiversCompareTo != 0) {
return receiversCompareTo;
}
}
ReceiverParameterDescriptor c1ReceiverParameter = c1.getReceiverParameter();
ReceiverParameterDescriptor c2ReceiverParameter = c2.getReceiverParameter();
assert (c1ReceiverParameter != null) == (c2ReceiverParameter != null);
if (c1ReceiverParameter != null) {
String r1 = RENDERER.renderType(c1ReceiverParameter.getType());
String r2 = RENDERER.renderType(c2ReceiverParameter.getType());
int receiversCompareTo = r1.compareTo(r2);
if (receiversCompareTo != 0) {
return receiversCompareTo;
List<ValueParameterDescriptor> c1ValueParameters = c1.getValueParameters();
List<ValueParameterDescriptor> c2ValueParameters = c2.getValueParameters();
for (int i = 0; i < Math.min(c1ValueParameters.size(), c2ValueParameters.size()); i++) {
String p1 = RENDERER.renderType(c1ValueParameters.get(i).getType());
String p2 = RENDERER.renderType(c2ValueParameters.get(i).getType());
int parametersCompareTo = p1.compareTo(p2);
if (parametersCompareTo != 0) {
return parametersCompareTo;
}
}
int valueParametersNumberCompareTo = c1ValueParameters.size() - c2ValueParameters.size();
if (valueParametersNumberCompareTo != 0) {
return valueParametersNumberCompareTo;
}
List<TypeParameterDescriptor> c1TypeParameters = c1.getTypeParameters();
List<TypeParameterDescriptor> c2TypeParameters = c2.getTypeParameters();
for (int i = 0; i < Math.min(c1TypeParameters.size(), c2TypeParameters.size()); i++) {
String p1 = RENDERER.renderType(c1TypeParameters.get(i).getUpperBoundsAsType());
String p2 = RENDERER.renderType(c2TypeParameters.get(i).getUpperBoundsAsType());
int parametersCompareTo = p1.compareTo(p2);
if (parametersCompareTo != 0) {
return parametersCompareTo;
}
}
int typeParametersCompareTo = c1TypeParameters.size() - c2TypeParameters.size();
if (typeParametersCompareTo != 0) {
return typeParametersCompareTo;
}
if (c1 instanceof CallableMemberDescriptor && c2 instanceof CallableMemberDescriptor) {
CallableMemberDescriptor.Kind c1Kind = ((CallableMemberDescriptor) c1).getKind();
CallableMemberDescriptor.Kind c2Kind = ((CallableMemberDescriptor) c2).getKind();
int kindsCompareTo = c1Kind.ordinal() - c2Kind.ordinal();
if (kindsCompareTo != 0) {
return kindsCompareTo;
}
}
}
else if (o1 instanceof ClassDescriptor && o2 instanceof ClassDescriptor) {
ClassDescriptor class1 = (ClassDescriptor) o1;
ClassDescriptor class2 = (ClassDescriptor) o2;
List<ValueParameterDescriptor> c1ValueParameters = c1.getValueParameters();
List<ValueParameterDescriptor> c2ValueParameters = c2.getValueParameters();
for (int i = 0; i < Math.min(c1ValueParameters.size(), c2ValueParameters.size()); i++) {
String p1 = RENDERER.renderType(c1ValueParameters.get(i).getType());
String p2 = RENDERER.renderType(c2ValueParameters.get(i).getType());
int parametersCompareTo = p1.compareTo(p2);
if (parametersCompareTo != 0) {
return parametersCompareTo;
if (class1.getKind().ordinal() != class2.getKind().ordinal()) {
return class1.getKind().ordinal() - class2.getKind().ordinal();
}
}
int valueParametersNumberCompareTo = c1ValueParameters.size() - c2ValueParameters.size();
if (valueParametersNumberCompareTo != 0) {
return valueParametersNumberCompareTo;
else {
throw new AssertionError(String.format(
"Unsupported pair of descriptors:\n'" +
"%s' Class: %s\n" +
"%s' Class: %s",
o1, o1.getClass(), o2, o2.getClass()));
}
List<TypeParameterDescriptor> c1TypeParameters = c1.getTypeParameters();
List<TypeParameterDescriptor> c2TypeParameters = c2.getTypeParameters();
for (int i = 0; i < Math.min(c1TypeParameters.size(), c2TypeParameters.size()); i++) {
String p1 = RENDERER.renderType(c1TypeParameters.get(i).getUpperBoundsAsType());
String p2 = RENDERER.renderType(c2TypeParameters.get(i).getUpperBoundsAsType());
int parametersCompareTo = p1.compareTo(p2);
if (parametersCompareTo != 0) {
return parametersCompareTo;
}
}
int renderDiff = RENDERER.render(o1).compareTo(RENDERER.render(o2));
if (renderDiff != 0) return renderDiff;
int typeParametersCompareTo = c1TypeParameters.size() - c2TypeParameters.size();
if (typeParametersCompareTo != 0) {
return typeParametersCompareTo;
}
Name firstModuleName = DescriptorUtils.getContainingModule(o1).getName();
Name secondModuleName = DescriptorUtils.getContainingModule(o2).getName();
if (c1 instanceof CallableMemberDescriptor && c2 instanceof CallableMemberDescriptor) {
CallableMemberDescriptor.Kind c1Kind = ((CallableMemberDescriptor) c1).getKind();
CallableMemberDescriptor.Kind c2Kind = ((CallableMemberDescriptor) c2).getKind();
int kindsCompareTo = c1Kind.ordinal() - c2Kind.ordinal();
if (kindsCompareTo != 0) {
return kindsCompareTo;
}
}
return RENDERER.render(o1).compareTo(RENDERER.render(o2));
return firstModuleName.compareTo(secondModuleName);
}
}

View File

@@ -44,6 +44,7 @@ public class AutoCastUtils {
private AutoCastUtils() {}
@NotNull
public static List<JetType> getAutoCastVariants(
@NotNull ReceiverValue receiverToCast,
@NotNull ResolutionContext context
@@ -51,6 +52,7 @@ public class AutoCastUtils {
return getAutoCastVariants(receiverToCast, context.trace.getBindingContext(), context.dataFlowInfo);
}
@NotNull
public static List<JetType> getAutoCastVariants(
@NotNull ReceiverValue receiverToCast,
@NotNull BindingContext bindingContext,

View File

@@ -36,6 +36,7 @@ import java.util.Set;
public final class JetScopeUtils {
private JetScopeUtils() {}
@NotNull
public static List<ReceiverValue> getImplicitReceiversHierarchyValues(@NotNull JetScope scope) {
Collection<ReceiverParameterDescriptor> hierarchy = scope.getImplicitReceiversHierarchy();
@@ -56,6 +57,7 @@ public final class JetScopeUtils {
* @param scope Scope for query extensions.
* @return extension descriptors.
*/
@NotNull
public static Collection<CallableDescriptor> getAllExtensions(@NotNull JetScope scope) {
Set<CallableDescriptor> result = Sets.newHashSet();

Some files were not shown because too many files have changed in this diff Show More