Compare commits

...

143 Commits

Author SHA1 Message Date
Nikolay Krasko
fe4400c768 Consider only pinned builds for bootstrapping 2016-03-04 20:52:36 +03:00
Nikolay Krasko
3cbd0b3496 Do not depend on MOVE_SEARCH_FOR_REFERENCES_FOR_FILE global setting
Always search for references if something is under source root and disable search otherwise.

 #KT-11277 Fixed
2016-03-04 19:51:12 +03:00
Nikolay Krasko
e3beb060f7 Don't intercept move when there're no kotlin files
#KT-11277 Fixed
2016-03-04 19:50:35 +03:00
nik
360e1ed0d6 until-build set to 146.9999 to make Kotlin plugin compatible with new IDEA builds
(cherry picked from commit c69d332)
2016-02-18 10:21:00 +03:00
Dmitry Jemerov
63771c6368 trim -release- from plugin version number when checking whether the runtime is outdated
(cherry picked from commit 2a8e1af)
2016-02-14 15:38:15 +01:00
Dmitry Jemerov
8549ec7645 K 2016-02-12 20:39:08 +01:00
Pavel V. Talanov
4b3970ec58 Fix stub/ast mismatch for old binaries (rc-1036) in newer versions of plugin 2016-02-12 19:11:23 +03:00
Ilya Gorbunov
bded4842ee Change default buffer size to be 8K (same default as in java BufferedReader).
Rename internal constants.
(cherry picked from commit 17a9538)
2016-02-12 15:13:11 +03:00
Ilya Gorbunov
1d00a58922 Use HALF_EVEN rounding mode by default for BigDecimal division operator.
#KT-10462 Fixed
(cherry picked from commit 6c7cefa)
2016-02-11 18:43:59 +03:00
Nikolay Krasko
d332f0f236 Fix forgotten test data for 10648f44ac (KT-10212) 2016-02-11 16:43:01 +03:00
Alexey Sedunov
b40afdbe19 Change Signature: Temporarily disable type resolution checks in Change Signature Dialog 2016-02-10 16:23:37 +03:00
Alexey Sedunov
90e158f54c Change Signature: Fix reference substitution when default value is a single simple name reference
#KT-10954 Fixed
(cherry picked from commit bb2a5b0)
2016-02-09 19:42:43 +03:00
Alexey Sedunov
05b880f9a3 Introduce Variable: Skip type in template if no resolvable/non-error types are available in the current context
#KT-10808 Fixed
(cherry picked from commit 792d9c1)
2016-02-09 19:42:35 +03:00
Alexey Sedunov
9d53f5f7d7 Go to Test Action: Make available in the entire class text range
#KT-10757 Fixed
(cherry picked from commit e386a6b)
2016-02-09 19:42:20 +03:00
Zalim Bashorov
966b1dbb7f FIx possible NPEs when try to use TestModuleProperties in IDEA 144.x
#EA-78931 Fixed

(cherry picked from commit eacd50c)
2016-02-09 15:57:30 +03:00
Ilya Gorbunov
59c24718c2 J2K, expected errors: for each argument of removed overloads
(cherry picked from commit 78b7fb1)
2016-02-09 15:20:38 +03:00
Ilya Gorbunov
a406a897d7 Drop previously deprecated API.
(cherry picked from commit b4ebaad)
2016-02-09 15:20:04 +03:00
Ilya Gorbunov
dde3b3a245 Make Throwable properties message and cause open.
#KT-5587 Fixed
(cherry picked from commit 5361f6e)
2016-02-09 15:19:24 +03:00
Michael Bogdanov
9915356c1f Removed absent test 2016-02-09 10:13:43 +03:00
Stanislav Erokhin
075ff1a92c Correcting rewrite type info after compete call.
#KT-10934 Fixed
#KT-10896 Fixed
(cherry picked from commit 434bd07)
2016-02-08 21:27:36 +03:00
Michael Bogdanov
2a26b1bc01 Rollback "Fix for KT-10659: Debugger: Evaluate Expression and Watches fail for inline function parameter passed by reference"
(cherry picked from commit 848549dd5d)

Conflicts:
	idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java
2016-02-08 16:47:09 +03:00
Zalim Bashorov
15e73d1260 Allow to use internal declarations from special modules in compiler (JPS)
(e.g. IDEA 16 gradle tests loaded in separate module)

 #KT-10595 Fixed
(cherry picked from commit 3c4cb54)
2016-02-08 16:06:54 +03:00
Zalim Bashorov
219afa4f9f J2K KotlinBuilderModuleScriptGenerator: cleanup
(cherry picked from commit e328c24)
2016-02-08 16:06:50 +03:00
Zalim Bashorov
b82f04053f J2K KotlinBuilderModuleScriptGenerator: convert
(cherry picked from commit 21e69a0)
2016-02-08 16:06:46 +03:00
Zalim Bashorov
8a6b2dbbfc J2K KotlinBuilderModuleScriptGenerator: .java -> .kt
(cherry picked from commit d503033)
2016-02-08 16:06:40 +03:00
Zalim Bashorov
21d2548073 Allow to use internal declarations from special modules in IDEA
(e.g. IDEA 16 gradle tests loaded in separate module)

 #KT-10595 Fixed
(cherry picked from commit 2c1d1e8)
2016-02-08 16:05:02 +03:00
Nikolay Krasko
bf23dd3aaa SOE on setEnabled(). setEnabled() changes were propagated back to action group with the request to update state (EA-71014) 2016-02-08 15:37:08 +03:00
Nikolay Krasko
5beb4bd340 Allow to process return statements without parent KtDeclaration (EA-70883) 2016-02-08 15:36:56 +03:00
Nikolay Krasko
0121860b64 Can't get file when event is invalid (EA-77748) 2016-02-08 15:36:47 +03:00
Dmitry Petrov
a42c8d811a KT-10939 CANNOT_COMPLETE_RESOLVE for inherited generic interface method
'original' for value parameters of fake override is not a value parameter of unsubstituted fake override.
Match value parameters by index.
(cherry picked from commit 5968ce9)
2016-02-08 10:17:23 +03:00
Alexander Udalov
b986297a90 Fix test data after removing old annotation classes 2016-02-07 10:08:33 +05:30
Alexander Udalov
a86e1d18c9 Delete old metadata annotation classes 2016-02-06 15:54:48 +05:30
Alexander Udalov
7cdf677368 Move constants from JvmAnnotationNames closer to usages 2016-02-06 15:54:44 +05:30
Alexander Udalov
8200c0ff21 Minor, add extra constant to JvmAnnotationNames, drop unneeded utility 2016-02-06 15:54:41 +05:30
Alexander Udalov
7ae324657d Do not write old metadata annotations to bytecode 2016-02-06 15:54:39 +05:30
Alexander Udalov
082f7709b5 Use kotlin.Metadata instead of old annotations in IDE, reflection and tests 2016-02-06 15:54:37 +05:30
Denis Zharkov
eae19c52b9 Generate multi-files facade even if it's empty
It still contains useful information about it's parts,
that may be used while building stubs for multi-file group
containing only InlineOnly functions
2016-02-05 17:29:24 +03:00
Denis Zharkov
29759e0712 Refine multi-file facades generation
Do not generate delegation from multi-file facade to inline-only functions
because they are effectively private in bytecode

 #KT-10858 Fixed
2016-02-05 17:29:24 +03:00
Valentin Kipyatkov
f168c401b3 Better diagnostic for EA-70945
(cherry picked from commit affbefd)
2016-02-05 16:32:22 +03:00
Valentin Kipyatkov
43232f4167 Added better diagnostic for EA-75805
(cherry picked from commit ce8e2d7)
2016-02-05 16:32:15 +03:00
Valentin Kipyatkov
e0533892a7 More correct convertation to string template when number literals involved
(cherry picked from commit 3fe6f9c)
2016-02-05 16:32:09 +03:00
Valentin Kipyatkov
eff6863d11 Fixed EA-75114
(cherry picked from commit 9c426e7)
2016-02-05 16:32:03 +03:00
Valentin Kipyatkov
b0292cc3a7 Fixed EA-75251
(cherry picked from commit c914ca0)
2016-02-05 16:31:56 +03:00
Valentin Kipyatkov
de72511c04 Fixed EA-75979
(cherry picked from commit eca581e)
2016-02-05 16:31:47 +03:00
Valentin Kipyatkov
28a84b7370 Fixed EA-76497
(cherry picked from commit 8b6338c)
2016-02-05 16:31:39 +03:00
Yan Zhulanow
e89819047b Pack actual Kotlin Android compiler plugin sources into kotlin-android-extensions-ver-sources.jar 2016-02-04 17:26:21 +03:00
Andrey Breslav
5995f73662 Adding sources jar to kotlin-android-extensions 2016-02-04 14:26:44 +03:00
Dmitry Jemerov
9ff208d840 ensure Kotlin's move handlers run before Java's
#KT-10703 Fixed
(cherry picked from commit 0a46033)
2016-02-03 17:47:34 +01:00
Pavel V. Talanov
21392e6b21 Prevent recursion when computing parameter list of KtLightMethod (part 2)
Use ClsWrapperStubPsiFactory when building light classes for decompiled kotlin classes
2016-02-03 19:44:57 +03:00
Ilya Gorbunov
3ebf25fe5c Inline-only Lazy.getValue extension 2016-02-03 18:29:38 +03:00
Michael Bogdanov
67f4f8fde2 More wise lambda search during inlining
(cherry picked from commit 6c45cf8)
2016-02-03 18:30:12 +03:00
Dmitry Jemerov
4d349c8623 don't veto rename of constructors
#KT-9693 Fixed
(cherry picked from commit 187694d)
2016-02-03 16:01:00 +01:00
Ilya Gorbunov
eabe9b5ae8 J2K: Remove special conversion for String.format.
(cherry picked from commit 805410bb19)
2016-02-03 17:22:17 +03:00
Ilya Gorbunov
0d3a2e7c54 In addition to extension String.format introduce String.Companion.format(format, args) to be used like in java.
(cherry picked from commit c243a2bdd5)
2016-02-03 17:22:16 +03:00
Ilya Gorbunov
8ae57107c4 Documentation stubs for new packages.
(cherry picked from commit 7105c7c182)
2016-02-03 17:22:15 +03:00
Mikhail Glukhikh
b7c4c23da1 Type comparison: first check for star projections, then obtain constructor parameters #KT-10893 Fixed
Also #EA-78405 Fixed
(cherry picked from commit 0c32fab)
2016-02-03 17:03:18 +03:00
Pavel V. Talanov
6c51df9fec Prevent recursion when computing parameter list of KtLightMethod
#KT-10890 Fixed
 #KT-10851 Fixed
2016-02-03 16:11:30 +03:00
Dmitry Jemerov
981523ce03 better place for J2K options
#KT-10513 Fixed
(cherry picked from commit db51910)
2016-02-03 13:23:26 +01:00
Dmitry Jemerov
981bb30707 don't show two "Rename variables" checkboxes for a Kotlin class
#KT-8509 Fixed
(cherry picked from commit 45a3876)
2016-02-03 13:23:17 +01:00
Dmitry Jemerov
9914f0ee65 use new API for excluding Kotlin plugin from update checks
(cherry picked from commit c881cd1)
2016-02-03 13:23:07 +01:00
Dmitry Jemerov
6fb246a352 use more deterministic check to determine that "Configure Kotlin in project" notification should be displayed
#KT-10898 Fixed
(cherry picked from commit e227f6f)
2016-02-03 13:22:52 +01:00
Michael Bogdanov
32a1e7dc82 Updated test data
(cherry picked from commit 3ec96f1)
2016-02-03 10:31:13 +03:00
Ilya Gorbunov
ad2d1ea15b SAM-constructors for Iterable and Sequence interfaces.
(cherry picked from commit f19ef6e3d5)
2016-02-03 03:06:11 +03:00
Ilya Gorbunov
ce0f22d299 Minor: reorder primitive specializations in generated code (according to the order they defined in java).
(cherry picked from commit 947fd84f1e)

# Conflicts:
#	libraries/stdlib/src/generated/_Arrays.kt
2016-02-03 03:06:08 +03:00
Ilya Gorbunov
0fb369f6ae Minor: reorder families in generated code.
(cherry picked from commit 7a50562a4e)
2016-02-03 03:05:20 +03:00
Ilya Gorbunov
7ad2732d3e Rearrange stdlib, part 2: rename files to better represent their content.
(cherry picked from commit 477b57cdfd)
2016-02-03 03:05:18 +03:00
Ilya Gorbunov
ba67067629 Rearrange stdlib between files and folders, rename files to better represent their content.
Fix package part name in testData

(cherry picked from commit 57cfa54957)
2016-02-03 03:05:16 +03:00
Ilya Gorbunov
601b18a4d8 IDEA version for bootstrapping (use IDEA built with kotlin rc branch) 2016-02-02 19:21:52 +03:00
Michael Bogdanov
25351185d4 Fix for crashed build
(cherry picked from commit 062f037)
2016-02-02 17:29:20 +03:00
Mikhail Glukhikh
5e4b94a3ca Delegated properties now cannot be used before initialization #KT-10869 Fixed
(cherry picked from commit 45298e0)
2016-02-02 17:10:43 +03:00
Michael Bogdanov
e3a16098e4 INVISIBLE_MEMBER_FROM_INLINE renamed to NON_PUBLIC_CALL_FROM_PUBLIC_INLINE
(cherry picked from commit 956c3b9)
2016-02-02 16:40:30 +03:00
Michael Bogdanov
056def876e Error diagnostic for private classes in inline functions; Fix for KT-7545: IllegalAccessError when accessing private nested class through inlined function from different package
#KT-7545 Fixed

(cherry picked from commit f0392643e632cbe1cf6a5a0b575ff41f7ee2d834)

Conflicts:
	compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
2016-02-02 16:40:24 +03:00
Michael Bogdanov
05437aed3d Generate package private visibility in bytecode for private classes
(cherry picked from commit c49ef8a)
2016-02-02 16:35:33 +03:00
Dmitry Jemerov
18461f067b don't try to parse empty text as XML
(cherry picked from commit 4a1d282)
2016-02-02 13:41:00 +01:00
Nikolay Krasko
c04f3bfbf1 Failed build is good enough for version increment 2016-02-02 15:36:10 +03:00
Denis Zharkov
ab3268957c Refine 'isMoreSpecific' calculation
Choose member with better visibility, it's needed for proper calculation
of types intersection member scope

 #KT-10481 Fixed
2016-02-02 15:28:45 +03:00
Ilya Gorbunov
bf2449876a Add UTF_32 charsets to Charsets object as lazy initialized properties.
#KT-10379 Fixed

(cherry picked from commit 148b53fc62)
2016-02-02 15:27:27 +03:00
Dmitry Petrov
07b2cff0aa Fix for KT-10881 Declaring constant in a mutlifile class causes an IllegalAccessError on its usage.
Generate fields for 'const' properties in facade class.

NB reading annotations for 'const' vals in multifile class doesn't work, KT-10892.
2016-02-02 15:13:40 +03:00
Yan Zhulanow
aec9bd7d52 Check annotations on default property getter/setter 2016-02-02 13:16:29 +03:00
Ilya Gorbunov
1523c95379 Make DEFAULT_BUFFER_SIZE a constant.
(cherry picked from commit 0519254)
2016-02-01 22:28:06 +03:00
Ilya Gorbunov
7c9efb1f4f Fix testData
(cherry picked from commit 801a26a)
2016-02-01 22:28:00 +03:00
Ilya Gorbunov
1360d75849 Do not inline Regex.replace
(cherry picked from commit a192915)
2016-02-01 22:27:54 +03:00
Ilya Gorbunov
5028859097 Introduce annotation InlineExposed to indicate internal members effectively public due to usage in inlined functions.
Currently, doesn't affect anything.

Make collectionSizeOrDefault and collectionSizeOrNull internal, but expose them via inlining together with mapCapacity.

Make Regex(Pattern) constructor exposed by inlined Pattern.toRegex
(cherry picked from commit dccae6c)
2016-02-01 22:27:47 +03:00
Ilya Gorbunov
1b03ba305a Make all assert inline. Field _Assertions.ENABLED instead of property ASSERTIONS_ENABLED
(cherry picked from commit dacf25f)
2016-02-01 22:27:35 +03:00
Ilya Gorbunov
def8d30322 IDEA version for bootstrapping
Build markdown every time (again).
(cherry picked from commit c763b59)
2016-02-01 22:27:21 +03:00
Ilya Gorbunov
500cc0c33c Throw assertion when inline-only is applied without inline
(cherry picked from commit 1cef327)
2016-02-01 22:27:11 +03:00
Ilya Gorbunov
ed09405d2e Do not use inline-only in java
(cherry picked from commit a12fe2c)
2016-02-01 22:27:05 +03:00
Ilya Gorbunov
8c6a32cd0b Include internal annotatations in mock runtime
(cherry picked from commit 8a00db5)
2016-02-01 22:26:59 +03:00
Ilya Gorbunov
fefa08bfc9 Deprecate currentThread property
(cherry picked from commit fc3f98d)
2016-02-01 22:26:49 +03:00
Ilya Gorbunov
53564770f2 Drop CharSequence.get extension
(cherry picked from commit 42bd8df)
2016-02-01 22:26:42 +03:00
Ilya Gorbunov
d89a3024ac Swap parameters in File.forEachBlock
(cherry picked from commit 1eee1fa)
2016-02-01 22:26:33 +03:00
Ilya Gorbunov
23105b1c7e Inline-only in kotlin.comparisons
(cherry picked from commit abe9270)
2016-02-01 22:26:30 +03:00
Ilya Gorbunov
80034fce1b Inline-only in kotlin.io
(cherry picked from commit 54977ee)
2016-02-01 22:26:05 +03:00
Ilya Gorbunov
933b4b2645 Inline-only in kotlin.text
(cherry picked from commit 47d580c)
2016-02-01 22:25:47 +03:00
Ilya Gorbunov
ebe9b23dcc Inline-only in kotlin and kotlin.system packages, split Float/Double extension implementations for JVM and JS to make them inline-only in JVM.
(cherry picked from commit 56c5758)
2016-02-01 22:25:36 +03:00
Ilya Gorbunov
dd81988a58 Inline-only in kotlin.concurrent, make all timer utilities inline.
(cherry picked from commit 40fae04)
2016-02-01 22:25:22 +03:00
Ilya Gorbunov
1800869ed5 Inline-only in kotlin.collections
(cherry picked from commit ce5fd3e)
2016-02-01 22:25:15 +03:00
Ilya Gorbunov
c8c36d7d56 Inline-only in generated code
(cherry picked from commit c7bd707)
2016-02-01 22:25:08 +03:00
Ilya Gorbunov
25cdcd6dd9 StdLib Generators: support three flavors of inline
(cherry picked from commit 8c0008a)
2016-02-01 22:25:01 +03:00
Dmitry Jemerov
d9a81aa8fc don't apply StandardScriptDefinition in REPL
(cherry picked from commit 38b58db)
2016-02-01 19:23:28 +01:00
Dmitry Jemerov
a93ce4aa80 correctly separate stdout and stderr when parsing REPL output
(cherry picked from commit 84f9cb9)
2016-02-01 19:23:20 +01:00
Ilya Gorbunov
7e31c16983 Wrap exceptions thrown by class builders and add details about class file being generated.
(cherry picked from commit 3ae4c03)
2016-02-01 21:02:31 +03:00
Ilya Gorbunov
92e1fd6cfb Verify index expectations for reduceIndexed/reduceRightIndexed
(cherry picked from commit 4f1418b)
2016-02-01 21:02:25 +03:00
Ilya Gorbunov
ee29f8294e Minor: verify exception type of failed fold/reduce
(cherry picked from commit 1357c77)
2016-02-01 21:02:20 +03:00
Gabriel Borges
d76f55396a Add foldIndexed and reduceIndexed groups of functions
- foldIndexed, foldRightIndexed, reduceIndexed and reduceRightIndexed have been added, in line with filterIndexed etc.;
- Test cases added appropriately for the new functions.
(cherry picked from commit d58efff)
2016-02-01 21:02:13 +03:00
Ilya Gorbunov
a1bed57179 InlineOnly annotation suppresses NOTHING_TO_INLINE diagnostics.
(cherry picked from commit 911940d)
2016-02-01 21:01:52 +03:00
Dmitry Jemerov
fa7eac71f1 remove old API usage inspection
(cherry picked from commit 95683bb)
2016-02-01 18:46:36 +01:00
Mikhail Glukhikh
ef5b692f9b Annotations on object literals are now correctly resolved #KT-9320 Fixed
(cherry picked from commit 84100ab)
2016-02-01 20:05:07 +03:00
Michael Bogdanov
b9a4890a14 Fix for KT-10729: Accessing private const field in companion object from a function in the same companion generates run-time error
(cherry picked from commit 5f38c1d)
2016-02-01 18:43:13 +03:00
Michael Bogdanov
d3c612a035 Idea dependency updated to 143.2072
(cherry picked from commit 9790afb)
2016-02-01 18:38:05 +03:00
Michael Bogdanov
9ba7338a9c Removed old default generation
(cherry picked from commit 328b9bf)
2016-02-01 18:38:02 +03:00
Michael Bogdanov
30a1a95a3a Added assertion for super call with default arguments in function default impl body
(cherry picked from commit c9cc9c5)
2016-02-01 18:37:49 +03:00
Michael Bogdanov
525bce6cc5 KT-10670: Debugger: Evaluate Expression/Watches fail for inline function parameter initialized with default value
#KT-10670 Fixed
(cherry picked from commit dc2cb40)
2016-02-01 18:37:47 +03:00
Michael Bogdanov
2e0412679c Fix for KT-10659: Debugger: Evaluate Expression and Watches fail for inline function parameter passed by reference
#KT-10659 Fixed
(cherry picked from commit d4df7aa)
2016-02-01 18:37:44 +03:00
Pavel V. Talanov
85d4cf8fc5 Fix NPE on trying to compile script files
(There is still no design)
2016-02-01 17:42:31 +03:00
Mikhail Glukhikh
de853b8961 Correct report of NO_VALUE_FOR_PARAMETER when function call contains no brackets and lambda at the end #KT-7813 Fixed
(cherry picked from commit d194af5)
2016-02-01 17:14:02 +03:00
Yan Zhulanow
19685e9974 Kapt: compile kotlinAfterJava without Jdk as well in Android projects (KT-10854) 2016-02-01 14:34:13 +03:00
Denis Zharkov
4e46b0ca90 Temporary disable warning about unchecked reified argument
#KT-10847 Fixed
 #KT-6484 Reopened
2016-02-01 13:40:30 +03:00
Mikhail Glukhikh
47b2adbb78 Take into account data flow info changes for special call (if/when/elvis/!!) arguments #KT-10824 Fixed
Smart casts on complex expressions look as no more possible
(cherry picked from commit ed8ccdc)
2016-01-29 17:45:18 +03:00
Mikhail Glukhikh
d19e59576c Fix for unprocessed lambda under not-null assertion #KT-10843 Fixed
Also #EA-76890 Fixed
(cherry picked from commit 4691351)
2016-01-29 17:32:14 +03:00
Mikhail Glukhikh
4095c54028 Additional catch for ReenteringLazyValueComputationException #KT-8448 Fixed
Also #EA-76264 Fixed
(cherry picked from commit 7fd1f50)
2016-01-29 17:30:48 +03:00
Mikhail Glukhikh
ec3ef1bb03 One non-processed branch is now allowed for if statement #KT-10805 Fixed
Also #EA-64033 Fixed
(cherry picked from commit 7e26fa6)
2016-01-29 17:29:47 +03:00
Evgeny Gerashchenko
a497b1fbf7 Minor. Syntax error cosmetics.
(cherry picked from commit c242ad9)
2016-01-29 15:09:49 +03:00
Evgeny Gerashchenko
27a013de2a KT-8275 Unterminated multi-line comment should be compilation error
#KT-8275 fixed
(cherry picked from commit 0d79c65)
2016-01-29 15:09:43 +03:00
Dmitry Jemerov
f36a68dcd4 remove logic to filter perf output from compiler output
(cherry picked from commit 6d7e1c6)
2016-01-28 16:13:46 +01:00
Dmitry Jemerov
8a68bc4061 report perf only if enabled in command line
(cherry picked from commit 6f7aed2)
2016-01-28 16:13:38 +01:00
Mikhail Glukhikh
d6a7780971 Regression: correct smart cast from Type? to Type!
(cherry picked from commit 5062ce2)
2016-01-28 17:51:38 +03:00
Ilya Gorbunov
1ac8602bc8 Move IndexedValue to kotlin.collections. 2016-01-28 12:38:09 +03:00
Nikolay Krasko
503053dfb2 Parametrize maven deploy to allow pushing to bintray 2016-01-28 11:58:14 +03:00
Alexander Udalov
6b62d18da0 Mark array constructors with 'inline'
To allow non-local returns from lambdas passed to them
2016-01-28 03:15:37 +03:00
Alexander Udalov
b181e3095d Reimplement generation of intrinsic array constructors
Instead of relying on a class from the runtime (which thus cannot be deleted
from the runtime ever), rely on a class from the compiler instead. This has a
minor downside: that class is compiled by the bootstrap compiler, so if codegen
of 'for'-loops or something else used in that class changes, it won't
immediately have an effect on a local working copy (on the build server
everything will be fine because of a 2-step building process).

In the future it may make sense to just manually create all the bytecode
instructions and dump them into a MethodNode. Currently the amount of work
needed for that seems rather significant
2016-01-28 03:15:35 +03:00
Alexander Udalov
d2108f5dea Minor, prettify Kotlin code in source maps 2016-01-28 03:15:34 +03:00
Alexander Udalov
0989a202b4 Optimize getFqName calls in KotlinBuiltIns
Check the simple name first, and only then construct the full FqName, in all
'is*' methods
2016-01-28 03:15:31 +03:00
Alexander Udalov
6f7091291e Make Array<T>(size, init) a constructor of Array
It's not marked as inline, this is why 'crossinline' was added in
jaggedArray.kt/jaggedDeep.kt. Will be fixed in the following commits
2016-01-28 03:15:29 +03:00
Alexander Udalov
f08f917160 Minor, drop DescriptorRendererOptions#prettyFunctionTypes 2016-01-28 03:15:27 +03:00
Alexander Udalov
eab81dab2d Make primitive array factory functions constructors 2016-01-28 03:15:26 +03:00
Alexander Udalov
02aa1246b8 Minor, improve AbstractLazyType#toString for debug 2016-01-28 03:15:24 +03:00
Alexander Udalov
18a17249c7 Minor, fix Array kdoc 2016-01-28 03:15:22 +03:00
Ilya Gorbunov
f96265b06f Allow call assertFailsWith<T> with default message. 2016-01-28 00:17:50 +03:00
Dmitry Jemerov
23152df154 back to correct bootstrap for RC branch 2016-01-27 19:52:15 +03:00
Dmitry Jemerov
c36275787e temp revert bootstrap changes 2016-01-27 19:52:14 +03:00
Dmitry Jemerov
d729c8ce7d don't use bootstrap tag for fetching bootstrap build, use latest build 2016-01-27 19:52:13 +03:00
Dmitry Jemerov
3a19f77408 update_dependencies set up for RC branch 2016-01-27 19:52:13 +03:00
473 changed files with 10500 additions and 8915 deletions

View File

@@ -1154,6 +1154,7 @@
<delete dir="${output}/mock-runtime-src" failonerror="false"/>
<mkdir dir="${output}/mock-runtime-src"/>
<copy file="${basedir}/libraries/stdlib/src/kotlin/util/Standard.kt" todir="${output}/mock-runtime-src"/>
<copy file="${basedir}/libraries/stdlib/src/kotlin/internal/Annotations.kt" todir="${output}/mock-runtime-src"/>
<new-kotlinc output="${output}/classes/mock-runtime" moduleName="kotlin-stdlib">
<src>

View File

@@ -108,6 +108,16 @@ public abstract class AnnotationCodegen {
"Inconsistent target list for lambda annotation: " + applicableTargets + " on " + annotated;
continue;
}
if (annotated instanceof ClassDescriptor
&& !applicableTargets.contains(KotlinTarget.CLASS)
&& !applicableTargets.contains(KotlinTarget.ANNOTATION_CLASS)) {
ClassDescriptor classDescriptor = (ClassDescriptor) annotated;
if (classDescriptor.getVisibility() == Visibilities.LOCAL) {
assert applicableTargets.contains(KotlinTarget.EXPRESSION) :
"Inconsistent target list for object literal annotation: " + applicableTargets + " on " + annotated;
continue;
}
}
String descriptor = genAnnotation(annotation);
if (descriptor != null) {

View File

@@ -63,7 +63,6 @@ import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
@@ -257,8 +256,7 @@ public class AsmUtil {
Classes in byte code should be public or package private
*/
public static int getVisibilityAccessFlagForClass(ClassDescriptor descriptor) {
if (DescriptorUtils.isTopLevelDeclaration(descriptor) ||
descriptor.getVisibility() == Visibilities.PUBLIC ||
if (descriptor.getVisibility() == Visibilities.PUBLIC ||
// TODO: should be package private, but for now Kotlin's reflection can't access members of such classes
descriptor.getVisibility() == Visibilities.LOCAL ||
descriptor.getVisibility() == Visibilities.INTERNAL) {
@@ -782,39 +780,26 @@ public class AsmUtil {
}
}
public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull GenerationState state) {
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), true);
JvmCodegenUtil.writeAbiVersion(av);
av.visitEnd();
}
public static void writeAnnotationData(
@NotNull AnnotationVisitor av,
@NotNull DescriptorSerializer serializer,
@NotNull MessageLite message,
boolean old
@NotNull MessageLite message
) {
byte[] bytes = serializer.serialize(message);
AnnotationVisitor data = av.visitArray(old ? JvmAnnotationNames.DATA_FIELD_NAME : JvmAnnotationNames.METADATA_DATA_FIELD_NAME);
AnnotationVisitor data = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME);
for (String string : BitEncoding.encodeBytes(bytes)) {
data.visit(null, string);
}
data.visitEnd();
AnnotationVisitor strings = av.visitArray(
old ? JvmAnnotationNames.STRINGS_FIELD_NAME : JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME
);
AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME);
for (String string : ((JvmStringTable) serializer.getStringTable()).getStrings()) {
strings.visit(null, string);
}
strings.visitEnd();
}
@NotNull
public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor();
}
@NotNull
public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName));

View File

@@ -286,13 +286,23 @@ public class ClassFileFactory implements OutputFileCollection {
@NotNull
@Override
public byte[] asByteArray() {
return generators.get(relativeClassFilePath).asBytes(builderFactory);
try {
return generators.get(relativeClassFilePath).asBytes(builderFactory);
}
catch (RuntimeException e) {
throw new RuntimeException("Error generating class file " + this.toString() + ": " + e.getMessage(), e);
}
}
@NotNull
@Override
public String asText() {
return generators.get(relativeClassFilePath).asText(builderFactory);
try {
return generators.get(relativeClassFilePath).asText(builderFactory);
}
catch (RuntimeException e) {
throw new RuntimeException("Error generating class file " + this.toString() + ": " + e.getMessage(), e);
}
}
@NotNull

View File

@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -60,7 +59,6 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.ExpressionCodegen.generateClassLiteralReference;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.writeAbiVersion;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
@@ -219,9 +217,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
}
@Override
protected void generateKotlinAnnotation() {
writeKotlinSyntheticClassAnnotation(v, state);
protected void generateKotlinMetadataAnnotation() {
final DescriptorSerializer serializer =
DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
@@ -230,15 +226,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.SYNTHETIC_CLASS, new Function1<AnnotationVisitor, Unit>() {
@Override
public Unit invoke(AnnotationVisitor av) {
writeAnnotationData(av, serializer, functionProto, false);
writeAnnotationData(av, serializer, functionProto);
return Unit.INSTANCE;
}
});
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FUNCTION), true);
writeAbiVersion(av);
writeAnnotationData(av, serializer, functionProto, true);
av.visitEnd();
}
@Override

View File

@@ -25,8 +25,8 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.Stack;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import kotlin.Unit;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -2118,7 +2118,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FieldAccessorKind fieldAccessorKind = FieldAccessorKind.NORMAL;
boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
if (isBackingFieldInClassCompanion && forceField) {
if (isBackingFieldInClassCompanion && (forceField || propertyDescriptor.isConst() && Visibilities.isPrivate(propertyDescriptor.getVisibility()))) {
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
}
else if (syntheticBackingField && context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration) {
@@ -2425,24 +2425,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private CallGenerator getOrCreateCallGenerator(
@NotNull CallableDescriptor descriptor,
@Nullable KtElement callElement,
@Nullable TypeParameterMappings typeParameterMappings
@Nullable TypeParameterMappings typeParameterMappings,
boolean isDefaultCompilation
) {
if (callElement == null) return defaultCallGenerator;
// We should inline callable containing reified type parameters even if inline is disabled
// because they may contain something to reify and straight call will probably fail at runtime
boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) &&
InlineUtil.isInline(descriptor);
(InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor));
if (!isInline) return defaultCallGenerator;
SimpleFunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((SimpleFunctionDescriptor) descriptor.getOriginal());
return new InlineCodegen(this, state, original, callElement, typeParameterMappings);
FunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal());
return new InlineCodegen(this, state, original, callElement, typeParameterMappings, isDefaultCompilation);
}
@NotNull
protected CallGenerator getOrCreateCallGeneratorForDefaultImplBody(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) {
return getOrCreateCallGenerator(descriptor, function, null);
return getOrCreateCallGenerator(descriptor, function, null, true);
}
@NotNull
@@ -2454,6 +2455,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
KotlinType type = TypeUtils.uncaptureTypeForInlineMapping(entry.getValue());
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
if (typeParameterAndReificationArgument == null) {
// type is not generic
@@ -2461,21 +2464,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
mappings.addParameterMappingToType(
key.getName().getIdentifier(),
type,
asmType,
signatureWriter.toString(),
key.isReified());
key.getName().getIdentifier(), type, asmType, signatureWriter.toString(), isReified
);
}
else {
mappings.addParameterMappingForFurtherReification(
key.getName().getIdentifier(), type,
typeParameterAndReificationArgument.getSecond(), key.isReified());
key.getName().getIdentifier(), type, typeParameterAndReificationArgument.getSecond(), isReified
);
}
}
return getOrCreateCallGenerator(
resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings
);
resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings, false);
}
@@ -3345,7 +3344,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type type = expressionType(expression);
if (type.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
return generateNewArray(expression, bindingContext.getType(expression));
return generateNewArray(expression, bindingContext.getType(expression), resolvedCall);
}
return generateConstructorCall(resolvedCall, type);
@@ -3391,20 +3390,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
});
}
public StackValue generateNewArray(@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType) {
assert expression.getValueArguments().size() == 1 : "Size argument expected";
public StackValue generateNewArray(
@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType, @NotNull ResolvedCall<?> resolvedCall
) {
List<KtValueArgument> args = expression.getValueArguments();
assert args.size() == 1 || args.size() == 2 : "Unknown constructor called: " + args.size() + " arguments";
final KtExpression sizeExpression = expression.getValueArguments().get(0).getArgumentExpression();
Type type = typeMapper.mapType(arrayType);
if (args.size() == 1) {
final KtExpression sizeExpression = args.get(0).getArgumentExpression();
return StackValue.operation(typeMapper.mapType(arrayType), new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
gen(sizeExpression, Type.INT_TYPE);
newArrayInstruction(arrayType);
return Unit.INSTANCE;
}
});
}
return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
gen(sizeExpression, Type.INT_TYPE);
newArrayInstruction(arrayType);
return Unit.INSTANCE;
}
});
return invokeFunction(resolvedCall, StackValue.none());
}
public void newArrayInstruction(@NotNull KotlinType arrayType) {

View File

@@ -22,6 +22,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import kotlin.jvm.functions.Function1;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
@@ -672,18 +673,9 @@ public class FunctionCodegen {
}
else {
mv.visitCode();
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen);
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
}
generateOldDefaultForFun(defaultMethod,
JvmDeclarationOriginKt.Synthetic(function, functionDescriptor),
flags,
getThrownExceptions(functionDescriptor, typeMapper),
(owner.getContextKind() == OwnerKind.DEFAULT_IMPLS ?
typeMapper.mapDefaultImpls((ClassDescriptor) functionDescriptor.getContainingDeclaration()) :
typeMapper.mapImplementationOwner(functionDescriptor)).getInternalName()
);
}
}
@@ -693,7 +685,8 @@ public class FunctionCodegen {
@NotNull MethodVisitor mv,
@NotNull DefaultParameterValueLoader loadStrategy,
@Nullable KtNamedFunction function,
@NotNull MemberCodegen<?> parentCodegen
@NotNull MemberCodegen<?> parentCodegen,
@NotNull Method defaultMethod
) {
GenerationState state = parentCodegen.state;
JvmMethodSignature signature = state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());
@@ -705,6 +698,9 @@ public class FunctionCodegen {
CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);
InstructionAdapter iv = new InstructionAdapter(mv);
genDefaultSuperCallCheckIfNeeded(iv, defaultMethod);
loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
@@ -714,8 +710,6 @@ public class FunctionCodegen {
capturedArgumentsCount++;
}
InstructionAdapter iv = new InstructionAdapter(mv);
int maskIndex = 0;
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
for (int index = 0; index < valueParameters.size(); index++) {
@@ -748,36 +742,20 @@ public class FunctionCodegen {
iv.areturn(signature.getReturnType());
}
private void generateOldDefaultForFun(
Method newDefaultMethod,
JvmDeclarationOrigin origin,
int flags,
String[] exceptions,
String owner
) {
if ("<init>".equals(newDefaultMethod.getName())) {
private static void genDefaultSuperCallCheckIfNeeded(@NotNull InstructionAdapter iv, @NotNull Method defaultMethod) {
String defaultMethodName = defaultMethod.getName();
if ("<init>".equals(defaultMethodName)) {
return;
}
String oldSignature = newDefaultMethod.getDescriptor().replaceFirst("Ljava/lang/Object;\\)", ")");
MethodVisitor mv = v.newMethod(
origin,
flags,
newDefaultMethod.getName(),
oldSignature,
null,
exceptions
);
mv.visitCode();
int index = 0;
InstructionAdapter iv = new InstructionAdapter(mv);
for (Type type: Type.getArgumentTypes(oldSignature)) {
iv.load(index, type);
index += type.getSize();
}
iv.aconst(null);
iv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, newDefaultMethod.getName(), newDefaultMethod.getDescriptor(), false);
iv.areturn(newDefaultMethod.getReturnType());
mv.visitEnd();
Label end = new Label();
int handleIndex = (Type.getArgumentsAndReturnSizes(defaultMethod.getDescriptor()) >> 2) - 2; /*-1 for this, and -1 for handle*/
iv.load(handleIndex, OBJECT_TYPE);
iv.ifnull(end);
AsmUtil.genThrow(iv,
"java/lang/UnsupportedOperationException",
"Super calls with default arguments not supported in this target, function: " +
StringsKt.substringBeforeLast(defaultMethodName, JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodName));
iv.visitLabel(end);
}
@NotNull

View File

@@ -110,7 +110,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
if (referencedFunction instanceof ConstructorDescriptor) {
if (returnType.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType());
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType(), fakeResolvedCall);
}
else {
result = codegen.generateConstructorCall(fakeResolvedCall, returnType);

View File

@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.name.FqName;
@@ -248,7 +247,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
protected void generateKotlinAnnotation() {
protected void generateKotlinMetadataAnnotation() {
final DescriptorSerializer serializer =
DescriptorSerializer.create(descriptor, new JvmSerializerExtension(v.getSerializationBindings(), state));
@@ -257,15 +256,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.CLASS, new Function1<AnnotationVisitor, Unit>() {
@Override
public Unit invoke(AnnotationVisitor av) {
writeAnnotationData(av, serializer, classProto, false);
writeAnnotationData(av, serializer, classProto);
return Unit.INSTANCE;
}
});
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
writeAbiVersion(av);
writeAnnotationData(av, serializer, classProto, true);
av.visitEnd();
}
private void writeEnclosingMethod() {

View File

@@ -146,11 +146,9 @@ class InterfaceImplBodyCodegen(
})
}
override fun generateKotlinAnnotation() {
override fun generateKotlinMetadataAnnotation() {
(v as InterfaceImplClassBuilder).stopCounting()
AsmUtil.writeKotlinSyntheticClassAnnotation(v, state)
writeSyntheticClassMetadata(v);
}

View File

@@ -30,8 +30,6 @@ import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.RootContext;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion;
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
import org.jetbrains.kotlin.psi.KtFile;
@@ -43,7 +41,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import java.io.File;
@@ -220,8 +217,4 @@ public class JvmCodegenUtil {
public static String getMappingFileName(@NotNull String moduleName) {
return "META-INF/" + moduleName + "." + ModuleMapping.MAPPING_FILE_EXT;
}
public static void writeAbiVersion(@NotNull AnnotationVisitor av) {
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmMetadataVersion.INSTANCE.toArray());
}
}

View File

@@ -119,7 +119,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
generateSyntheticParts();
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generateKotlinAnnotation();
generateKotlinMetadataAnnotation();
}
done();
@@ -132,7 +132,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
protected void generateSyntheticParts() {
}
protected abstract void generateKotlinAnnotation();
protected abstract void generateKotlinMetadataAnnotation();
@Nullable
protected ClassDescriptor classForInnerClassRecord() {
@@ -601,12 +601,13 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
boolean forceField = (JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
!isCompanionObject(accessor.getContainingDeclaration())) ||
boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
!isCompanionObject(accessor.getContainingDeclaration());
boolean forceField = forceFieldForCompanionProperty ||
syntheticBackingField ||
original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
StackValue property = codegen.intermediateValueForProperty(
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), true, StackValue.none()
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), forceFieldForCompanionProperty, StackValue.none()
);
InstructionAdapter iv = codegen.v;

View File

@@ -49,7 +49,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -113,7 +112,7 @@ class MultifileClassCodegen(
generateDelegatesToPreviouslyCompiledParts(generateCallableMemberTasks, partFqNames)
if (!generateCallableMemberTasks.isEmpty()) {
if (!partFqNames.isEmpty()) {
generateMultifileFacadeClass(generateCallableMemberTasks, partFqNames)
}
}
@@ -213,7 +212,8 @@ class MultifileClassCodegen(
if (declaration is KtNamedFunction || declaration is KtProperty) {
val descriptor = state.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
assert(descriptor is CallableMemberDescriptor) { "Expected callable member, was " + descriptor + " for " + declaration.text }
if (!Visibilities.isPrivate((descriptor as CallableMemberDescriptor).visibility)) {
if (!Visibilities.isPrivate((descriptor as CallableMemberDescriptor).visibility)
&& AsmUtil.getVisibilityAccessFlag(descriptor) != Opcodes.ACC_PRIVATE) {
generateCallableMemberTasks.put(descriptor, { memberCodegen.genFunctionOrProperty(declaration) })
}
}
@@ -273,31 +273,20 @@ class MultifileClassCodegen(
if (state.classBuilderMode != ClassBuilderMode.FULL) return
if (files.any { it.isScript }) return
val partInternalNames = partFqNames.map(AsmUtil::internalNameByFqNameWithoutInnerClasses).sorted()
fun writePartNames(av: AnnotationVisitor, fieldName: String) {
val arv = av.visitArray(fieldName)
for (internalName in partInternalNames) {
writeKotlinMetadata(classBuilder, KotlinClassHeader.Kind.MULTIFILE_CLASS) { av ->
val arv = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME)
for (internalName in partFqNames.map(AsmUtil::internalNameByFqNameWithoutInnerClasses).sorted()) {
arv.visit(null, internalName)
}
arv.visitEnd()
}
writeKotlinMetadata(classBuilder, KotlinClassHeader.Kind.MULTIFILE_CLASS) { av ->
writePartNames(av, JvmAnnotationNames.METADATA_DATA_FIELD_NAME)
}
val av = classBuilder.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS), true)
JvmCodegenUtil.writeAbiVersion(av)
writePartNames(av, JvmAnnotationNames.FILE_PART_CLASS_NAMES_FIELD_NAME)
av.visitEnd()
}
private fun createCodegenForPartOfMultifileFacade(facadeContext: FieldOwnerContext<*>): MemberCodegen<KtFile> =
object : MemberCodegen<KtFile>(state, null, facadeContext, null, classBuilder) {
override fun generateDeclaration() = throw UnsupportedOperationException()
override fun generateBody() = throw UnsupportedOperationException()
override fun generateKotlinAnnotation() = throw UnsupportedOperationException()
override fun generateKotlinMetadataAnnotation() = throw UnsupportedOperationException()
}
fun done() {

View File

@@ -69,7 +69,7 @@ class MultifileClassPartCodegen(
}
}
override fun generateKotlinAnnotation() {
override fun generateKotlinMetadataAnnotation() {
val members = ArrayList<DeclarationDescriptor>()
for (declaration in element.declarations) {
when (declaration) {
@@ -88,15 +88,9 @@ class MultifileClassPartCodegen(
val packageProto = serializer.packagePartProto(members).build()
writeKotlinMetadata(v, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART) { av ->
AsmUtil.writeAnnotationData(av, serializer, packageProto, false)
AsmUtil.writeAnnotationData(av, serializer, packageProto)
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassType.internalName)
}
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true)
JvmCodegenUtil.writeAbiVersion(av)
AsmUtil.writeAnnotationData(av, serializer, packageProto, true)
av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassType.internalName)
av.visitEnd()
}
override fun generateSyntheticParts() {

View File

@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -43,9 +42,7 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
import static org.jetbrains.kotlin.codegen.AsmUtil.writeAnnotationData;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.writeAbiVersion;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackagePartCodegen extends MemberCodegen<KtFile> {
@@ -109,7 +106,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
}
@Override
protected void generateKotlinAnnotation() {
protected void generateKotlinMetadataAnnotation() {
List<DeclarationDescriptor> members = new ArrayList<DeclarationDescriptor>();
for (KtDeclaration declaration : element.getDeclarations()) {
if (declaration instanceof KtNamedFunction) {
@@ -128,15 +125,10 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.FILE_FACADE, new Function1<AnnotationVisitor, Unit>() {
@Override
public Unit invoke(AnnotationVisitor av) {
writeAnnotationData(av, serializer, packageProto, false);
writeAnnotationData(av, serializer, packageProto);
return Unit.INSTANCE;
}
});
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
writeAbiVersion(av);
writeAnnotationData(av, serializer, packageProto, true);
av.visitEnd();
}
@Override

View File

@@ -114,7 +114,7 @@ public class PropertyCodegen {
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
if (CodegenContextUtil.isImplClassOwner(context)) {
if (isBackingFieldOwner(descriptor)) {
assert declaration != null : "Declaration is null for different context: " + context;
genBackingFieldAndAnnotations(declaration, descriptor, false);
@@ -128,6 +128,13 @@ public class PropertyCodegen {
}
}
private boolean isBackingFieldOwner(@NotNull PropertyDescriptor descriptor) {
if (descriptor.isConst()) {
return !(context instanceof MultifileClassPartContext);
}
return CodegenContextUtil.isImplClassOwner(context);
}
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
boolean hasBackingField = hasBackingField(declaration, descriptor);
boolean hasDelegate = declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate();

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.AsmUtil.method
import org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation
import org.jetbrains.kotlin.codegen.context.ClassContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
@@ -158,9 +157,7 @@ class PropertyReferenceCodegen(
}
}
override fun generateKotlinAnnotation() {
writeKotlinSyntheticClassAnnotation(v, state)
override fun generateKotlinMetadataAnnotation() {
writeSyntheticClassMetadata(v)
}

View File

@@ -39,7 +39,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collections;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
import static org.jetbrains.kotlin.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -94,8 +95,6 @@ public class SamWrapperCodegen {
);
cv.visitSource(file.getName(), null);
writeKotlinSyntheticClassAnnotation(cv, state);
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv);
// e.g. ASM type for Function2

View File

@@ -104,7 +104,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
}
@Override
protected void generateKotlinAnnotation() {
protected void generateKotlinMetadataAnnotation() {
// TODO
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2010-2016 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.kotlin.codegen.inline
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
internal class FictitiousArrayConstructor(arrayClass: ClassDescriptor) : SimpleFunctionDescriptorImpl(
arrayClass.containingDeclaration, null, Annotations.EMPTY, arrayClass.name, CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
) {
companion object Factory {
@JvmStatic
fun create(arrayConstructor: ConstructorDescriptor): FictitiousArrayConstructor {
val arrayClass = arrayConstructor.containingDeclaration
return FictitiousArrayConstructor(arrayClass).apply {
this.initialize(null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType,
Modality.FINAL, Visibilities.PUBLIC)
this.isInline = true
}
}
}
}

View File

@@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
@@ -69,7 +70,7 @@ public class InlineCodegen extends CallGenerator {
private final GenerationState state;
private final JetTypeMapper typeMapper;
private final SimpleFunctionDescriptor functionDescriptor;
private final FunctionDescriptor functionDescriptor;
private final JvmMethodSignature jvmSignature;
private final KtElement callElement;
private final MethodContext context;
@@ -84,6 +85,7 @@ public class InlineCodegen extends CallGenerator {
private final ReifiedTypeInliner reifiedTypeInliner;
@Nullable private final TypeParameterMappings typeParameterMappings;
private final boolean isDefaultCompilation;
private LambdaInfo activeLambda;
@@ -92,17 +94,22 @@ public class InlineCodegen extends CallGenerator {
public InlineCodegen(
@NotNull ExpressionCodegen codegen,
@NotNull GenerationState state,
@NotNull SimpleFunctionDescriptor functionDescriptor,
@NotNull FunctionDescriptor function,
@NotNull KtElement callElement,
@Nullable TypeParameterMappings typeParameterMappings
@Nullable TypeParameterMappings typeParameterMappings,
boolean isDefaultCompilation
) {
assert InlineUtil.isInline(functionDescriptor) : "InlineCodegen could inline only inline function: " + functionDescriptor;
assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) :
"InlineCodegen can inline only inline functions and array constructors: " + function;
this.isDefaultCompilation = isDefaultCompilation;
this.state = state;
this.typeMapper = state.getTypeMapper();
this.codegen = codegen;
this.callElement = callElement;
this.functionDescriptor = functionDescriptor.getOriginal();
this.functionDescriptor =
InlineUtil.isArrayConstructorWithLambda(function)
? FictitiousArrayConstructor.create((ConstructorDescriptor) function)
: function.getOriginal();
this.typeParameterMappings = typeParameterMappings;
reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);
@@ -119,13 +126,14 @@ public class InlineCodegen extends CallGenerator {
isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
if (!(functionDescriptor instanceof FictitiousArrayConstructor)) {
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
}
}
@Override
public void genCallWithoutAssertions(
@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen
) {
public void genCallWithoutAssertions(@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen) {
genCall(callableMethod, null, false, codegen);
}
@@ -176,19 +184,25 @@ public class InlineCodegen extends CallGenerator {
}
@NotNull
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws ClassNotFoundException, IOException {
JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());
Method asmMethod;
if (callDefault) {
asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
}
else {
asmMethod = jvmSignature.getAsmMethod();
}
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException {
Method asmMethod = callDefault
? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind())
: jvmSignature.getAsmMethod();
SMAPAndMethodNode nodeAndSMAP;
if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
if (functionDescriptor instanceof FictitiousArrayConstructor) {
nodeAndSMAP = InlineCodegenUtil.getMethodNode(
IntrinsicArrayConstructorsKt.getBytecode(),
asmMethod.getName(),
asmMethod.getDescriptor(),
IntrinsicArrayConstructorsKt.getClassId()
);
if (nodeAndSMAP == null) {
throw new IllegalStateException("Couldn't obtain array constructor body for " + descriptorName(functionDescriptor));
}
}
else if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
JetTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable(
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
@@ -203,14 +217,14 @@ public class InlineCodegen extends CallGenerator {
);
if (nodeAndSMAP == null) {
throw new RuntimeException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
throw new IllegalStateException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
}
}
else {
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
if (element == null || !(element instanceof KtNamedFunction)) {
throw new RuntimeException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
if (!(element instanceof KtNamedFunction)) {
throw new IllegalStateException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
}
KtNamedFunction inliningFunction = (KtNamedFunction) element;
@@ -233,7 +247,7 @@ public class InlineCodegen extends CallGenerator {
implementationOwner.getInternalName());
FunctionCodegen.generateDefaultImplBody(
methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
inliningFunction, parentCodegen
inliningFunction, parentCodegen, asmMethod
);
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
}
@@ -260,14 +274,10 @@ public class InlineCodegen extends CallGenerator {
Parameters parameters = invocationParamBuilder.buildParameters();
InliningContext info = new RootInliningContext(expressionMap,
state,
codegen.getInlineNameGenerator()
.subGenerator(functionDescriptor.getName().asString()),
codegen.getContext(),
callElement,
getInlineCallSiteInfo(), reifiedTypeInliner,
typeParameterMappings);
InliningContext info = new RootInliningContext(
expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()),
codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings, isDefaultCompilation
);
MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
"Method inlining " + callElement.getText(),
@@ -415,7 +425,7 @@ public class InlineCodegen extends CallGenerator {
}
@Override
protected void generateKotlinAnnotation() {
protected void generateKotlinMetadataAnnotation() {
throw new IllegalStateException();
}
@@ -529,13 +539,11 @@ public class InlineCodegen extends CallGenerator {
@Override
public void putHiddenParams() {
List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters();
if (!isStaticMethod(functionDescriptor, context)) {
if ((getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) == 0) {
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null);
}
for (JvmMethodParameterSignature param : valueParameters) {
for (JvmMethodParameterSignature param : jvmSignature.getValueParameters()) {
if (param.getKind() == JvmMethodParameterKind.VALUE) {
break;
}
@@ -643,10 +651,6 @@ public class InlineCodegen extends CallGenerator {
throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor));
}
private static boolean isStaticMethod(FunctionDescriptor functionDescriptor, MethodContext context) {
return (getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) != 0;
}
private static String descriptorName(DeclarationDescriptor descriptor) {
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
}

View File

@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
@@ -84,7 +85,7 @@ public class InlineCodegenUtil {
final String methodName,
final String methodDescriptor,
ClassId classId
) throws ClassNotFoundException, IOException {
) throws IOException {
ClassReader cr = new ClassReader(classData);
final MethodNode[] node = new MethodNode[1];
final String[] debugInfo = new String[2];
@@ -127,6 +128,15 @@ public class InlineCodegenUtil {
}
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
if (node[0] == null) {
return null;
}
if (classId.equals(IntrinsicArrayConstructorsKt.getClassId())) {
// Don't load source map for intrinsic array constructors
debugInfo[0] = null;
}
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
return new SMAPAndMethodNode(node[0], smap);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2010-2016 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.kotlin.codegen.inline
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
class InstructionsAndFrames(val frames: Array<Frame<SourceValue>>, ins: InsnList) {
val indexes = (0..ins.size() - 1).associate { Pair(ins.get(it), it) }
operator fun get(node: AbstractInsnNode): Frame<SourceValue>? = frames[indexes[node]!!]
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen.inline;
import com.google.common.collect.Lists;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.SmartHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.ClosureCodegen;
@@ -370,7 +371,10 @@ public class MethodInliner {
@NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index
) {
if (isInliningLambda || InlineCodegenUtil.GENERATE_SMAP) {
String varSuffix = inliningContext.isRoot() && !InlineCodegenUtil.isFakeLocalVariableForInline(name) ? INLINE_FUN_VAR_SUFFIX : "";
String varSuffix = inliningContext.isRoot() &&
!((RootInliningContext) inliningContext).isDefaultCompilation &&
!InlineCodegenUtil.isFakeLocalVariableForInline(name) ?
INLINE_FUN_VAR_SUFFIX : "";
String varName = !varSuffix.isEmpty() && name.equals("this") ? name + "_" : name;
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index));
}
@@ -424,7 +428,8 @@ public class MethodInliner {
catch (AnalyzerException e) {
throw wrapException(e, node, "couldn't inline method call");
}
Set<AbstractInsnNode> toDelete = new SmartHashSet<AbstractInsnNode>();
InstructionsAndFrames instructionsAndFrames = new InstructionsAndFrames(sources, node.instructions);
AbstractInsnNode cur = node.instructions.getFirst();
int index = 0;
@@ -465,7 +470,7 @@ public class MethodInliner {
if (insnNode.getOpcode() == Opcodes.SWAP) {
processingInstruction = InlineCodegenUtil.getPrevMeaningful(insnNode);
}
lambdaInfo = getLambdaIfExists(processingInstruction);
lambdaInfo = getLambdaIfExistsAndMarkInstructions(processingInstruction, frame, instructionsAndFrames, toDelete);
if (lambdaInfo != null) {
//remove inlinable access
assert processingInstruction != null;
@@ -483,7 +488,7 @@ public class MethodInliner {
SourceValue sourceValue = frame.getStack(firstParameterIndex + i);
if (sourceValue.insns.size() == 1) {
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
LambdaInfo lambdaInfo = getLambdaIfExists(insnNode);
LambdaInfo lambdaInfo = getLambdaIfExistsAndMarkInstructions(insnNode, frame, instructionsAndFrames, toDelete);
if (lambdaInfo != null) {
lambdaMapping.put(offset, lambdaInfo);
node.instructions.remove(insnNode);
@@ -530,6 +535,10 @@ public class MethodInliner {
}
}
for (AbstractInsnNode insnNode : toDelete) {
node.instructions.remove(insnNode);
}
//clean dead try/catch blocks
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
for (Iterator<TryCatchBlockNode> iterator = blocks.iterator(); iterator.hasNext(); ) {
@@ -572,7 +581,41 @@ public class MethodInliner {
}
@Nullable
public LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
private LambdaInfo getLambdaIfExistsAndMarkInstructions(
@Nullable AbstractInsnNode insnNode,
@NotNull Frame<SourceValue> localFrame,
@NotNull InstructionsAndFrames insAndFrames,
@NotNull Set<AbstractInsnNode> toDelete
) {
LambdaInfo lambdaInfo = getLambdaIfExists(insnNode);
if (lambdaInfo == null && insnNode instanceof VarInsnNode && insnNode.getOpcode() == Opcodes.ALOAD) {
int varIndex = ((VarInsnNode) insnNode).var;
SourceValue local = localFrame.getLocal(varIndex);
if (local.insns.size() == 1) {
AbstractInsnNode storeIns = local.insns.iterator().next();
if (storeIns instanceof VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) {
Frame<SourceValue> frame = insAndFrames.get(storeIns);
if (frame != null) {
SourceValue topOfStack = frame.getStack(frame.getStackSize() - 1);
if(topOfStack.insns.size() == 1) {
AbstractInsnNode lambdaAload = topOfStack.insns.iterator().next();
lambdaInfo = getLambdaIfExistsAndMarkInstructions(lambdaAload, frame, insAndFrames, toDelete);
if (lambdaInfo != null) {
toDelete.add(storeIns);
toDelete.add(lambdaAload);
}
}
}
}
}
}
return lambdaInfo;
}
@Nullable
private LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
if (insnNode == null) {
return null;
}

View File

@@ -28,6 +28,7 @@ public class RootInliningContext extends InliningContext {
public final CodegenContext startContext;
private final InlineCallSiteInfo inlineCallSiteInfo;
public final TypeParameterMappings typeParameterMappings;
public final boolean isDefaultCompilation;
public final KtElement callElement;
public RootInliningContext(
@@ -38,13 +39,15 @@ public class RootInliningContext extends InliningContext {
@NotNull KtElement callElement,
@NotNull InlineCallSiteInfo classNameToInline,
@NotNull ReifiedTypeInliner inliner,
@Nullable TypeParameterMappings typeParameterMappings
@Nullable TypeParameterMappings typeParameterMappings,
boolean isDefaultCompilation
) {
super(null, map, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), inliner, false, false);
this.callElement = callElement;
this.startContext = startContext;
this.inlineCallSiteInfo = classNameToInline;
this.typeParameterMappings = typeParameterMappings;
this.isDefaultCompilation = isDefaultCompilation;
}
@Override

View File

@@ -24,11 +24,12 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
import java.util.*
//TODO join parameter
class SMAPBuilder(val source: String,
val path: String,
val fileMappings: List<FileMapping>) {
val header = "SMAP\n$source\nKotlin\n*S Kotlin"
class SMAPBuilder(
val source: String,
val path: String,
val fileMappings: List<FileMapping>
) {
private val header = "SMAP\n$source\nKotlin\n*S Kotlin"
fun build(): String? {
var realMappings = fileMappings.filter {
@@ -37,7 +38,7 @@ class SMAPBuilder(val source: String,
}
if (realMappings.isEmpty()) {
return null;
return null
}
val fileIds = "*F" + realMappings.mapIndexed { id, file -> "\n${file.toSMAPFile(id + 1)}" }.joinToString("")
@@ -46,29 +47,29 @@ class SMAPBuilder(val source: String,
return "$header\n$fileIds\n$lineMappings\n*E\n"
}
fun RangeMapping.toSMAP(fileId: Int): String {
private fun RangeMapping.toSMAP(fileId: Int): String {
return if (range == 1) "$source#$fileId:$dest" else "$source#$fileId,$range:$dest"
}
fun FileMapping.toSMAPFile(id: Int): String {
this.id = id;
private fun FileMapping.toSMAPFile(id: Int): String {
this.id = id
return "+ $id $name\n$path"
}
//TODO inline
fun FileMapping.toSMAPMapping(): String {
private fun FileMapping.toSMAPMapping(): String {
return lineMappings.joinToString("") { "\n${it.toSMAP(id)}" }
}
}
open class NestedSourceMapper(parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo) : DefaultSourceMapper(sourceInfo, parent) {
open class NestedSourceMapper(
parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo
) : DefaultSourceMapper(sourceInfo, parent) {
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) {
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
value, key ->
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
}
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
})
if (index < 0) {
parent!!.visitSource(sourceInfo.source, sourceInfo.pathOrCleanFQN)
parent!!.visitLineNumber(iv, lineNumber, start)
@@ -81,8 +82,9 @@ open class NestedSourceMapper(parent: SourceMapper, val ranges: List<RangeMappin
}
}
open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNode) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
open class InlineLambdaSourceMapper(
parent: SourceMapper, smap: SMAPAndMethodNode
) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
override fun visitSource(name: String, path: String) {
super.visitSource(name, path)
if (isOriginalVisited()) {
@@ -100,13 +102,13 @@ open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNod
}
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) {
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
value, key ->
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
}
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
})
if (index >= 0) {
val fmapping = ranges[index].parent!!
if (fmapping.path == origin.path && fmapping.name == origin.name) {
val mapping = ranges[index].parent!!
if (mapping.path == origin.path && mapping.name == origin.name) {
parent!!.visitOrigin()
parent!!.visitLineNumber(iv, lineNumber, start)
return
@@ -117,7 +119,6 @@ open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNod
}
interface SourceMapper {
val resultMappings: List<FileMapping>
val parent: SourceMapper?
@@ -138,7 +139,6 @@ interface SourceMapper {
}
companion object {
fun flushToClassBuilder(mapper: SourceMapper, v: ClassBuilder) {
for (fileMapping in mapper.resultMappings) {
v.addSMAP(fileMapping)
@@ -179,15 +179,10 @@ object IdenticalSourceMapper : SourceMapper {
}
open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: SourceMapper?): SourceMapper {
protected var maxUsedValue: Int = sourceInfo.linesInFile
var lastVisited: RawFileMapping? = null
private var lastMappedWithChanges: RawFileMapping? = null
var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
private var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
protected val origin: RawFileMapping
init {
@@ -205,7 +200,7 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent:
get() = fileMappings.values.map { it.toFileMapping() }
override fun visitSource(name: String, path: String) {
lastVisited = fileMappings.getOrPut(createKey(name, path), { RawFileMapping(name, path) })
lastVisited = fileMappings.getOrPut(createKey(name, path)) { RawFileMapping(name, path) }
}
override fun visitOrigin() {
@@ -232,7 +227,6 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent:
}
}
/*Source Mapping*/
class SMAP(val fileMappings: List<FileMapping>) {
init {
assert(fileMappings.isNotEmpty()) { "File Mappings shouldn't be empty" }
@@ -251,9 +245,7 @@ class SMAP(val fileMappings: List<FileMapping>) {
companion object {
val FILE_SECTION = "*F"
val LINE_SECTION = "*L"
val END = "*E"
}
}
@@ -262,15 +254,14 @@ class RawFileMapping(val name: String, val path: String) {
private val lineMappings = TIntIntHashMap()
private val rangeMappings = arrayListOf<RangeMapping>()
private var lastMappedWithNewIndex = -1000;
private var lastMappedWithNewIndex = -1000
fun toFileMapping(): FileMapping {
val fileMapping = FileMapping(name, path)
for (range in rangeMappings) {
fileMapping.addRangeMapping(range)
}
return fileMapping
}
fun toFileMapping() =
FileMapping(name, path).apply {
for (range in rangeMappings) {
addRangeMapping(range)
}
}
fun initRange(start: Int, end: Int) {
assert(lineMappings.isEmpty) { "initRange should only be called for empty mapping" }
@@ -315,14 +306,13 @@ class RawFileMapping(val name: String, val path: String) {
private fun couldFoldInRange(first: Int, second: Int): Boolean {
//TODO
val delta = second - first
return delta > 0 && delta <= 10;
return delta > 0 && delta <= 10
}
}
open class FileMapping(val name: String, val path: String) {
val lineMappings = arrayListOf<RangeMapping>()
var id = -1;
var id = -1
fun addRangeMapping(lineMapping: RangeMapping) {
lineMappings.add(lineMapping)
@@ -338,12 +328,10 @@ open class FileMapping(val name: String, val path: String) {
//TODO comparable
data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
var parent: FileMapping? = null;
var parent: FileMapping? = null
private val skip = source == -1 && dest == -1
fun contains(destLine: Int): Boolean {
operator fun contains(destLine: Int): Boolean {
return if (skip) true else dest <= destLine && destLine < dest + range
}
@@ -368,4 +356,4 @@ data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
companion object {
val SKIP = RangeMapping(-1, -1, 1)
}
}
}

View File

@@ -16,30 +16,26 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.org.objectweb.asm.tree.LineNumberNode
import org.jetbrains.org.objectweb.asm.Label
import kotlin.properties.Delegates
import java.util.Collections
import kotlin.properties.ReadOnlyProperty
import org.jetbrains.kotlin.codegen.SourceInfo
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
//TODO comment
class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) {
val lineNumbers =
InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map {
val index = Collections.binarySearch(classSMAP.intervals, RangeMapping(it.line, it.line, 1)) {
private val lineNumbers =
InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map { node ->
val index = classSMAP.intervals.binarySearch(RangeMapping(node.line, node.line, 1), Comparator {
value, key ->
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
})
if (index < 0) {
error("Unmapped label in inlined function $node ${node.line}")
}
if (index < 0)
throw IllegalStateException("Unmapped label in inlined function $it ${it.line}")
LabelAndMapping(it, classSMAP.intervals[index])
LabelAndMapping(node, classSMAP.intervals[index])
}.toList()
val ranges = lineNumbers.asSequence().map { it.mapper }.distinct().toList();
val ranges = lineNumbers.asSequence().map { it.mapper }.distinct().toList()
}
class LabelAndMapping(val lineNumberNode: LineNumberNode, val mapper: RangeMapping)
class LabelAndMapping(val lineNumberNode: LineNumberNode, val mapper: RangeMapping)

View File

@@ -16,51 +16,49 @@
package org.jetbrains.kotlin.codegen.inline
import com.intellij.util.SmartFMap
object SMAPParser {
/*null smap means that there is no any debug info in file (e.g. sourceName)*/
@JvmStatic
/*null smap means that there is no any debug info in file (e.g. sourceName)*/ fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
if (mappingInfo == null || mappingInfo.isEmpty()) {
val fm: FileMapping
if (source == null || source.isEmpty()) {
fm = FileMapping.SKIP
}
else {
fm = FileMapping(source, path)
if (methodStartLine <= methodEndLine) {
//one to one
fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
}
}
return SMAP(listOf(fm))
fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
if (mappingInfo != null && mappingInfo.isNotEmpty()) {
return parse(mappingInfo)
}
return parse(mappingInfo)
val mapping =
if (source == null || source.isEmpty())
FileMapping.SKIP
else
FileMapping(source, path).apply {
if (methodStartLine <= methodEndLine) {
//one to one
addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
}
}
return SMAP(listOf(mapping))
}
@JvmStatic fun parse(mappingInfo: String): SMAP {
@JvmStatic
fun parse(mappingInfo: String): SMAP {
val fileMappings = linkedMapOf<Int, FileMapping>()
val fileSectionStart = mappingInfo.indexOf(SMAP.FILE_SECTION) + SMAP.FILE_SECTION.length
val lineSectionAnchor = mappingInfo.indexOf(SMAP.LINE_SECTION)
val files = mappingInfo.substring(fileSectionStart, lineSectionAnchor)
val fileEntries = files.trim().split('+')
for (fileDeclaration in fileEntries) {
if (fileDeclaration == "") continue;
if (fileDeclaration == "") continue
val fileInternalName = fileDeclaration.trim()
val indexEnd = fileInternalName.indexOf(' ')
val fileIndex = Integer.valueOf(fileInternalName.substring(0, indexEnd))
val fileIndex = fileInternalName.substring(0, indexEnd).toInt()
val newLine = fileInternalName.indexOf('\n')
val fileName = fileInternalName.substring(indexEnd + 1, newLine)
fileMappings.put(fileIndex, FileMapping(fileName, fileInternalName.substring(newLine + 1).trim()))
fileMappings[fileIndex] = FileMapping(fileName, fileInternalName.substring(newLine + 1).trim())
}
val lines = mappingInfo.substring(lineSectionAnchor + SMAP.LINE_SECTION.length, mappingInfo.indexOf(SMAP.END)).trim().split('\n')
for (lineMapping in lines) {
/*only simple mapping now*/
@@ -69,14 +67,14 @@ object SMAPParser {
var rangeSeparator = originalPart.indexOf(',').let { if (it < 0) targetSplit else it }
val fileSeparator = lineMapping.indexOf('#')
val originalIndex = Integer.valueOf(originalPart.substring(0, fileSeparator))
val range = if (rangeSeparator == targetSplit) 1 else Integer.valueOf(originalPart.substring(rangeSeparator + 1, targetSplit))
val originalIndex = originalPart.substring(0, fileSeparator).toInt()
val range = if (rangeSeparator == targetSplit) 1 else originalPart.substring(rangeSeparator + 1, targetSplit).toInt()
val fileIndex = Integer.valueOf(lineMapping.substring(fileSeparator + 1, rangeSeparator))
val targetIndex = Integer.valueOf(lineMapping.substring(targetSplit + 1))
val fileIndex = lineMapping.substring(fileSeparator + 1, rangeSeparator).toInt()
val targetIndex = lineMapping.substring(targetSplit + 1).toInt()
fileMappings[fileIndex]!!.addRangeMapping(RangeMapping(originalIndex, targetIndex, range))
}
return SMAP(fileMappings.values.toList())
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 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.
@@ -14,14 +14,14 @@
* limitations under the License.
*/
package kotlin.jvm.internal;
package org.jetbrains.kotlin.codegen.intrinsics
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.name.FqName
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface KotlinLocalClass {
object ArrayConstructor : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable {
return object : IntrinsicCallable(method.owner, method.valueParameterTypes, null, null) {}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2010-2016 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.
*/
@file:Suppress("unused")
package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
// Bodies of methods in this file are used in InlineCodegen to inline array constructors. It is loaded via reflection at runtime.
// TODO: generate the bytecode manually instead, do not depend on the previous compiler working correctly here
internal val classId: ClassId =
ClassId.topLevel(FqName("org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt"))
internal val bytecode: ByteArray by lazy {
val stream = object {}.javaClass.classLoader.getResourceAsStream("${classId.asString()}.class")
stream.readBytes().apply {
stream.close()
}
}
private inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
val result = arrayOfNulls<T>(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result as Array<T>
}
private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
val result = DoubleArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
val result = FloatArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
val result = LongArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
val result = IntArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
val result = CharArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
val result = ShortArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
val result = ByteArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}
private inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
val result = BooleanArray(size)
for (i in 0..size - 1) {
result[i] = init(i)
}
return result
}

View File

@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class IntrinsicMethods {
@@ -150,6 +148,7 @@ public class IntrinsicMethods {
declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET);
declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE);
declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR);
declareIntrinsicFunction(arrayTypeFqName, "<init>", 2, ArrayConstructor.INSTANCE);
}
private void declareBinaryOp(@NotNull String methodName, int opcode) {

View File

@@ -159,7 +159,7 @@ public class JetTypeMapper {
if (file != null) {
Visibility visibility = descriptor.getVisibility();
if (!publicFacade ||
descriptor instanceof PropertyDescriptor ||
isNonConstProperty(descriptor) ||
Visibilities.isPrivate(visibility) ||
isAccessor/*Cause of KT-9603*/
) {
@@ -181,6 +181,12 @@ public class JetTypeMapper {
" in package fragment " + descriptor.getContainingDeclaration());
}
private static boolean isNonConstProperty(@NotNull CallableMemberDescriptor descriptor) {
if (!(descriptor instanceof PropertyDescriptor)) return false;
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
return !propertyDescriptor.isConst();
}
public static class ContainingClassesInfo {
private final ClassId facadeClassId;
private final ClassId implClassId;

View File

@@ -31,7 +31,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -58,8 +57,6 @@ public class MappingClassesForWhenByEnumCodegen {
generateFields(cb, mappings);
generateInitialization(cb, mappings);
writeKotlinSyntheticClassAnnotation(cb, state);
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cb);
cb.done();

View File

@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
fun writeKotlinMetadata(cb: ClassBuilder, kind: KotlinClassHeader.Kind, action: (AnnotationVisitor) -> Unit) {
val av = cb.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.METADATA), true)
val av = cb.newAnnotation(JvmAnnotationNames.METADATA_DESC, true)
av.visit(JvmAnnotationNames.METADATA_VERSION_FIELD_NAME, JvmMetadataVersion.INSTANCE.toArray())
av.visit(JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME, JvmBytecodeBinaryVersion.INSTANCE.toArray())
av.visit(JvmAnnotationNames.KIND_FIELD_NAME, kind.id)

View File

@@ -28,6 +28,8 @@ public class CLIConfigurationKeys {
CompilerConfigurationKey.create("compiler plugins");
public static final CompilerConfigurationKey<Boolean> ALLOW_KOTLIN_PACKAGE =
CompilerConfigurationKey.create("allow kotlin package");
public static final CompilerConfigurationKey<Boolean> REPORT_PERF =
CompilerConfigurationKey.create("report performance information");
private CLIConfigurationKeys() {
}

View File

@@ -124,10 +124,7 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
return ExitCode.OK
}
if (arguments.script) {
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
shouldReportPerf = false
}
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
if (arguments.skipMetadataVersionCheck) {
JvmMetadataVersion.skipCheck = true
@@ -238,7 +235,6 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
// allows to track GC time for each run when repeated compilation is used
private val elapsedGCTime = hashMapOf<String, Long>()
private var elapsedJITTime = 0L
private var shouldReportPerf = true
fun resetInitStartTime() {
if (initStartNanos == 0L) {
@@ -251,7 +247,9 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
fun reportPerf(configuration: CompilerConfiguration, message: String) {
if (!shouldReportPerf) return
if (!configuration.get(CLIConfigurationKeys.REPORT_PERF, false)) {
return
}
val collector = configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
collector.report(CompilerMessageSeverity.INFO, "PERF: " + message, CompilerMessageLocation.NO_LOCATION)
@@ -281,6 +279,7 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
configuration.put(JVMConfigurationKeys.MULTIFILE_FACADES_OPEN, arguments.multifileFacadesOpen);
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage);
configuration.put(CLIConfigurationKeys.REPORT_PERF, arguments.reportPerf);
}
private fun getClasspath(paths: KotlinPaths, arguments: K2JVMCompilerArguments): List<File> {

View File

@@ -69,6 +69,8 @@ messages/**)
public protected *;
}
-keep class org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt { *; }
-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; }
-keep class org.jetbrains.kotlin.codegen.extensions.** {

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
@@ -28,11 +29,14 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmSyntheticApplicabilityChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val annotation = descriptor.findJvmSyntheticAnnotation() ?: return
if (declaration is KtProperty && declaration.hasDelegate()) {
if (declaration is KtProperty && descriptor is VariableDescriptor && declaration.hasDelegate()) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
diagnosticHolder.report(ErrorsJvm.JVM_SYNTHETIC_ON_DELEGATE.on(annotationEntry))
}

View File

@@ -99,7 +99,12 @@ class PlatformStaticAnnotationChecker : DeclarationChecker {
}
class JvmNameAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val platformNameAnnotation = DescriptorUtils.getJvmNameAnnotation(descriptor)
if (platformNameAnnotation != null) {
checkDeclaration(descriptor, platformNameAnnotation, diagnosticHolder)

View File

@@ -98,7 +98,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
}
private fun doGetDescriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
return descriptorByModule[moduleInfo] ?: return delegateResolver.descriptorForModule(moduleInfo) as ModuleDescriptorImpl
return descriptorByModule[moduleInfo] ?: delegateResolver.descriptorForModule(moduleInfo) as ModuleDescriptorImpl
}
}
@@ -114,7 +114,7 @@ interface ModuleInfo {
get() = false
val name: Name
fun dependencies(): List<ModuleInfo>
fun friends(): Collection<ModuleInfo> = listOf()
fun modulesWhichInternalsAreVisible(): Collection<ModuleInfo> = listOf()
fun dependencyOnBuiltins(): DependencyOnBuiltins = DependenciesOnBuiltins.LAST
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
get() = emptyMap()
@@ -193,8 +193,8 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
modules.forEach {
module ->
val descriptor = resolverForProject.descriptorForModule(module)
module.friends().forEach {
descriptor.addFriend(resolverForProject.descriptorForModule(it as M))
module.modulesWhichInternalsAreVisible().forEach {
resolverForProject.descriptorForModule(it as M).addFriend(descriptor)
}
}
}
@@ -249,4 +249,4 @@ private class DelegatingPackageFragmentProvider(
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
return delegate().getSubPackagesOf(fqName, nameFilter)
}
}
}

View File

@@ -360,6 +360,14 @@ public class ControlFlowInformationProvider {
}
}
private boolean isDefinitelyInitialized(@NotNull PropertyDescriptor propertyDescriptor) {
if (propertyDescriptor.isLateInit()) return true;
if (trace.get(BACKING_FIELD_REQUIRED, propertyDescriptor) == Boolean.TRUE) return false;
PsiElement property = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
if (property instanceof KtProperty && ((KtProperty) property).hasDelegate()) return false;
return true;
}
private void checkIsInitialized(
@NotNull VariableInitContext ctxt,
@NotNull KtElement element,
@@ -370,11 +378,8 @@ public class ControlFlowInformationProvider {
boolean isDefinitelyInitialized = ctxt.exitInitState.definitelyInitialized();
VariableDescriptor variableDescriptor = ctxt.variableDescriptor;
if (variableDescriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
if (propertyDescriptor.isLateInit() || !trace.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
isDefinitelyInitialized = true;
}
if (!isDefinitelyInitialized && variableDescriptor instanceof PropertyDescriptor) {
isDefinitelyInitialized = isDefinitelyInitialized((PropertyDescriptor) variableDescriptor);
}
if (!isDefinitelyInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
if (!(variableDescriptor instanceof PropertyDescriptor)) {

View File

@@ -1146,6 +1146,8 @@ public class ControlFlowProcessor {
}
KtExpression delegate = property.getDelegateExpression();
if (delegate != null) {
// We do not want to have getDeferredValue(delegate) here, because delegate value will be read anyway later
visitAssignment(property, getDeferredValue(null), property);
generateInstructions(delegate);
if (builder.getBoundValue(delegate) != null) {
createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate);

View File

@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker.VarianceConflictDiagnosticData;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeProjection;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -769,7 +768,8 @@ public interface Errors {
DiagnosticFactory0<KtClass> NESTED_CLASS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, DECLARATION_NAME);
//Inline and inlinable parameters
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> NON_PUBLIC_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> PRIVATE_CLASS_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
DiagnosticFactory3<KtElement, KtElement, DeclarationDescriptor, DeclarationDescriptor> NON_LOCAL_RETURN_NOT_ALLOWED = DiagnosticFactory3.create(ERROR, CALL_ELEMENT);
DiagnosticFactory2<KtElement, KtNamedDeclaration, DeclarationDescriptor> NOT_YET_SUPPORTED_IN_INLINE = DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<PsiElement, DeclarationDescriptor> NOTHING_TO_INLINE = DiagnosticFactory1.create(WARNING);
@@ -785,7 +785,7 @@ public interface Errors {
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
UNRESOLVED_REFERENCE, NAMED_PARAMETER_NOT_FOUND, UNRESOLVED_REFERENCE_WRONG_RECEIVER);
ImmutableSet<? extends DiagnosticFactory<?>> INVISIBLE_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
INVISIBLE_MEMBER, INVISIBLE_MEMBER_FROM_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
INVISIBLE_MEMBER, NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
ImmutableSet<? extends DiagnosticFactory<?>> UNUSED_ELEMENT_DIAGNOSTICS = ImmutableSet.of(
UNUSED_VARIABLE, UNUSED_PARAMETER, ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, VARIABLE_WITH_REDUNDANT_INITIALIZER,
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS);

View File

@@ -728,7 +728,8 @@ public class DefaultErrorMessages {
MAP.put(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT, "kotlin.Array class literal requires a type argument, please specify one in angle brackets");
//Inline
MAP.put(INVISIBLE_MEMBER_FROM_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
MAP.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
MAP.put(PRIVATE_CLASS_MEMBER_FROM_INLINE, "Non-private inline function cannot access members of private classes: ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
MAP.put(NOT_YET_SUPPORTED_IN_INLINE, "''{0}'' construction is not yet supported in inline functions", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES);
MAP.put(DECLARATION_CANT_BE_INLINED, "''inline'' modifier is not allowed on virtual members. Only private or final members can be inlined");
MAP.put(NOTHING_TO_INLINE, "Expected performance impact of inlining ''{0}'' can be insignificant. Inlining works best for functions with lambda parameters", SHORT_NAMES_IN_TYPES);

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.parsing;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.WhitespacesBinders;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
@@ -112,9 +113,23 @@ public class KotlinParsing extends AbstractKotlinParsing {
parseTopLevelDeclaration();
}
checkUnclosedBlockComment();
fileMarker.done(KT_FILE);
}
private void checkUnclosedBlockComment() {
if (TokenSet.create(BLOCK_COMMENT, DOC_COMMENT).contains(myBuilder.rawLookup(-1))) {
int startOffset = myBuilder.rawTokenTypeStart(-1);
int endOffset = myBuilder.rawTokenTypeStart(0);
CharSequence tokenChars = myBuilder.getOriginalText().subSequence(startOffset, endOffset);
if (!(tokenChars.length() > 2 && tokenChars.subSequence(tokenChars.length() - 2, tokenChars.length()).toString().equals("*/"))) {
PsiBuilder.Marker marker = myBuilder.mark();
marker.error("Unclosed comment");
marker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_RIGHT_BINDER, null);
}
}
}
void parseTypeCodeFragment() {
PsiBuilder.Marker marker = mark();
parseTypeRef();
@@ -171,7 +186,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
private void checkForUnexpectedSymbols() {
while (!eof()) {
errorAndAdvance("unexpected symbol");
errorAndAdvance("Unexpected symbol");
}
}

View File

@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ErrorValue
import org.jetbrains.kotlin.resolve.inline.InlineUtil
private val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
@@ -69,5 +70,8 @@ private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly"
fun MemberDescriptor.isInlineOnly(): Boolean {
if (this !is FunctionDescriptor) return false
return typeParameters.any { it.isReified } || annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
return typeParameters.any { it.isReified } ||
annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) && InlineUtil.isInline(this).apply {
assert(this) { "Function is not inline: ${this@isInlineOnly}"; }
}
}

View File

@@ -727,12 +727,16 @@ class DeclarationsChecker(
}
private fun checkAccessors(property: KtProperty, propertyDescriptor: PropertyDescriptor) {
for (accessor in property.accessors) {
val propertyAccessorDescriptor = (if (accessor.isGetter) propertyDescriptor.getter else propertyDescriptor.setter)
?: throw AssertionError("No property accessor descriptor for ${property.text}")
accessor.checkTypeReferences()
modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor)
identifierChecker.checkDeclaration(accessor, trace)
for (accessorDescriptor in propertyDescriptor.accessors) {
val accessor = if (accessorDescriptor is PropertyGetterDescriptor) property.getter else property.setter
if (accessor != null) {
accessor.checkTypeReferences()
modifiersChecker.checkModifiersForDeclaration(accessor, accessorDescriptor)
identifierChecker.checkDeclaration(accessor, trace)
}
else {
modifiersChecker.runDeclarationCheckers(property, accessorDescriptor)
}
}
checkAccessor(propertyDescriptor, property.getter, propertyDescriptor.getter)
checkAccessor(propertyDescriptor, property.setter, propertyDescriptor.setter)

View File

@@ -228,7 +228,10 @@ public class ModifiersChecker {
}
private void runDeclarationCheckers(@NotNull KtDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
public void runDeclarationCheckers(
@NotNull KtDeclaration declaration,
@NotNull DeclarationDescriptor descriptor
) {
for (DeclarationChecker checker : declarationCheckers) {
checker.check(declaration, descriptor, trace, trace.getBindingContext());
}

View File

@@ -18,12 +18,10 @@ package org.jetbrains.kotlin.resolve
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.psi.*
object UnderscoreChecker : DeclarationChecker {
@@ -44,6 +42,7 @@ object UnderscoreChecker : DeclarationChecker {
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (declaration is KtProperty && descriptor !is VariableDescriptor) return
if (declaration is KtCallableDeclaration) {
for (parameter in declaration.valueParameters) {
checkNamed(parameter, diagnosticHolder)

View File

@@ -19,10 +19,8 @@ package org.jetbrains.kotlin.resolve.calls
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
@@ -285,7 +283,7 @@ class CallCompleter(
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression) ?: updatedType
}
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context.trace)
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context.statementFilter, context.trace)
// While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once),
// but they should be analyzed when the expected type is known (during the call completion).
@@ -320,6 +318,7 @@ class CallCompleter(
updatedType: KotlinType?,
recordedType: KotlinType?,
argumentExpression: KtExpression,
statementFilter: StatementFilter,
trace: BindingTrace
): KotlinType? {
//workaround for KT-8218
@@ -329,6 +328,11 @@ class CallCompleter(
val deparenthesized = KtPsiUtil.deparenthesizeOnce(expression)
if (deparenthesized != expression) return deparenthesized
// see KtPsiUtil.getLastElementDeparenthesized
if (expression is KtBlockExpression) {
return statementFilter.getLastStatementInABlock(expression)
}
return (expression as? KtQualifiedExpression)?.selectorExpression
}

View File

@@ -101,7 +101,7 @@ class InlineChecker implements CallChecker {
}
}
checkVisibility(targetDescriptor, expression, context);
checkVisibilityAndAccess(targetDescriptor, expression, context);
checkRecursion(context, targetDescriptor, expression);
}
@@ -248,10 +248,25 @@ class InlineChecker implements CallChecker {
return isInvoke || InlineUtil.isInline(descriptor);
}
private void checkVisibility(@NotNull CallableDescriptor declarationDescriptor, @NotNull KtElement expression, @NotNull BasicCallResolutionContext context){
private void checkVisibilityAndAccess(@NotNull CallableDescriptor declarationDescriptor, @NotNull KtElement expression, @NotNull BasicCallResolutionContext context){
boolean declarationDescriptorIsPublicApi = DescriptorUtilsKt.isEffectivelyPublicApi(declarationDescriptor) || isDefinedInInlineFunction(declarationDescriptor);
if (isEffectivelyPublicApiFunction && !declarationDescriptorIsPublicApi && declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
context.trace.report(Errors.INVISIBLE_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
context.trace.report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor));
}
else {
checkPrivateClassMemberAccess(declarationDescriptor, expression, context);
}
}
private void checkPrivateClassMemberAccess(
@NotNull DeclarationDescriptor declarationDescriptor,
@NotNull KtElement expression,
@NotNull BasicCallResolutionContext context
) {
if (!Visibilities.isPrivate(descriptor.getVisibility())) {
if (DescriptorUtilsKt.isInsidePrivateClass(declarationDescriptor)) {
context.trace.report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
}
}
}

View File

@@ -18,9 +18,8 @@ package org.jetbrains.kotlin.resolve.calls.checkers;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtExpression;
@@ -40,32 +39,40 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker {
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
TypeParameterDescriptor parameter = entry.getKey();
KotlinType argument = entry.getValue();
ClassifierDescriptor argumentDeclarationDescription = argument.getConstructor().getDeclarationDescriptor();
ClassifierDescriptor argumentDeclarationDescriptor = argument.getConstructor().getDeclarationDescriptor();
if (parameter.isReified()) {
if (argumentDeclarationDescription instanceof TypeParameterDescriptor &&
!((TypeParameterDescriptor) argumentDeclarationDescription).isReified()
) {
context.trace.report(
Errors.TYPE_PARAMETER_AS_REIFIED.on(getElementToReport(context, parameter.getIndex()), parameter)
);
}
else if (TypeUtilsKt.cannotBeReified(argument)) {
context.trace.report(
Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
}
else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
context.trace.report(
Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
}
if (!parameter.isReified() && !isTypeParameterOfKotlinArray(parameter)) {
continue;
}
if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor &&
!((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) {
context.trace.report(
Errors.TYPE_PARAMETER_AS_REIFIED.on(getElementToReport(context, parameter.getIndex()), parameter)
);
}
else if (TypeUtilsKt.cannotBeReified(argument)) {
context.trace.report(
Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
}
// REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847)
//else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
// context.trace.report(
// Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
//}
}
}
private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable");
private static boolean hasPureReifiableAnnotation(@NotNull TypeParameterDescriptor parameter) {
return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME);
return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME) ||
isTypeParameterOfKotlinArray(parameter);
}
private static boolean isTypeParameterOfKotlinArray(@NotNull TypeParameterDescriptor parameter) {
DeclarationDescriptor container = parameter.getContainingDeclaration();
return container instanceof ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray((ClassDescriptor) container);
}
@NotNull

View File

@@ -69,6 +69,7 @@ class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constr
val argumentsToParameters = hashMapOf<K, ValueParameterDescriptor>()
var parametersWithDefaultValuesCount = 0
val unsubstitutedValueParameters = call.candidateDescriptor.original.valueParameters
for ((valueParameterDescriptor, resolvedValueArgument) in call.unsubstitutedValueArguments.entries) {
if (resolvedValueArgument is DefaultValueArgument) {
parametersWithDefaultValuesCount++
@@ -76,7 +77,10 @@ class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constr
else {
val keys = resolvedArgumentToKeys(resolvedValueArgument)
for (argumentKey in keys) {
argumentsToParameters[argumentKey] = valueParameterDescriptor.original
// TODO fix 'original' for value parameters of Java generic descriptors.
// Should be able to use just 'valueParameterDescriptor' below.
// Doesn't work for Java generic descriptors. See also KT-10939.
argumentsToParameters[argumentKey] = unsubstitutedValueParameters[valueParameterDescriptor.index]
}
}
}

View File

@@ -307,9 +307,6 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
private fun getVarargElementTypeOrType(parameterDescriptor: ValueParameterDescriptor): KotlinType =
parameterDescriptor.varargElementType ?: parameterDescriptor.type
private val CallableDescriptor.hasVarargs: Boolean get() =
this.valueParameters.any { it.varargElementType != null }
private fun typeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
val isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general)

View File

@@ -300,8 +300,8 @@ internal class DelegatingDataFlowInfo private constructor(
val toDelete = newTypeInfo()
for (value in typeInfo.keys()) {
for (type in typeInfo[value]) {
// Remove original type and for not flexible type also all its supertypes (see also KT-10666)
if (if (value.type.isFlexible()) value.type == type else value.type.isSubtypeOf(type)) {
// Remove original type (see also KT-10666)
if (value.type == type) {
toDelete.put(value, type)
}
}

View File

@@ -90,7 +90,13 @@ fun Call.getValueArgumentsInParentheses(): List<ValueArgument> = valueArguments.
fun KtCallElement.getValueArgumentsInParentheses(): List<ValueArgument> = valueArguments.filterArgsInParentheses()
fun Call.getValueArgumentListOrElement(): KtElement = valueArgumentList ?: calleeExpression ?: callElement
fun Call.getValueArgumentListOrElement(): KtElement =
if (this is CallTransformer.CallForImplicitInvoke) {
outerCall.getValueArgumentListOrElement()
}
else {
valueArgumentList ?: calleeExpression ?: callElement
}
@Suppress("UNCHECKED_CAST")
private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is KtLambdaArgument } as List<ValueArgument>

View File

@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.FunctionAnalyzerExtension;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import java.util.List;
@@ -125,7 +126,7 @@ public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.Analyz
hasInlinable |= InlineUtil.containsReifiedTypeParameters(functionDescriptor);
if (!hasInlinable) {
if (!hasInlinable && !AnnotationUtilKt.isInlineOnly(functionDescriptor)) {
KtModifierList modifierList = function.getModifierList();
PsiElement inlineModifier = modifierList == null ? null : modifierList.getModifier(KtTokens.INLINE_KEYWORD);
PsiElement reportOn = inlineModifier == null ? function : inlineModifier;

View File

@@ -111,28 +111,39 @@ public class InlineUtil {
if (!canBeInlineArgument(argument)) return null;
KtExpression call = KtPsiUtil.getParentCallIfPresent(argument);
if (call != null) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(call, bindingContext);
if (resolvedCall != null && isInline(resolvedCall.getResultingDescriptor())) {
ValueArgument valueArgument = CallUtilKt.getValueArgumentForExpression(resolvedCall.getCall(), argument);
if (valueArgument != null) {
ArgumentMapping mapping = resolvedCall.getArgumentMapping(valueArgument);
if (mapping instanceof ArgumentMatch) {
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
if (isInlineLambdaParameter(parameter)) {
return parameter;
}
}
}
}
}
return null;
if (call == null) return null;
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(call, bindingContext);
if (resolvedCall == null) return null;
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (!isInline(descriptor) && !isArrayConstructorWithLambda(descriptor)) return null;
ValueArgument valueArgument = CallUtilKt.getValueArgumentForExpression(resolvedCall.getCall(), argument);
if (valueArgument == null) return null;
ArgumentMapping mapping = resolvedCall.getArgumentMapping(valueArgument);
if (!(mapping instanceof ArgumentMatch)) return null;
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
return isInlineLambdaParameter(parameter) ? parameter : null;
}
public static boolean canBeInlineArgument(@Nullable PsiElement functionalExpression) {
return functionalExpression instanceof KtFunctionLiteral || functionalExpression instanceof KtNamedFunction;
}
/**
* @return true if the descriptor is the constructor of one of 9 array classes (Array&lt;T&gt;, IntArray, FloatArray, ...)
* which takes the size and an initializer lambda as parameters. Such constructors are marked as 'inline' but they are not loaded
* as such because the 'inline' flag is not stored for constructors in the binary metadata. Therefore we pretend that they are inline
*/
public static boolean isArrayConstructorWithLambda(@NotNull CallableDescriptor descriptor) {
return descriptor.getValueParameters().size() == 2 &&
descriptor instanceof ConstructorDescriptor &&
KotlinBuiltIns.isArrayOrPrimitiveArray(((ConstructorDescriptor) descriptor).getContainingDeclaration());
}
@Nullable
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
DeclarationDescriptor current = strict ? descriptor.getContainingDeclaration() : descriptor;

View File

@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
@@ -172,8 +173,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return (syntaxKind == ClassKind.CLASS && modifierList != null && modifierList.hasModifier(KtTokens.ANNOTATION_KEYWORD)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
}
});
// Annotation entries are taken from both own annotations (if any) and object literal annotations (if any)
List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
// TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
annotationEntries.addAll(KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
}
if (modifierList != null) {
annotationEntries.addAll(modifierList.getAnnotationEntries());
}
if (!annotationEntries.isEmpty()) {
this.annotations = new LazyAnnotations(
new LazyAnnotationsContext(
c.getAnnotationResolver(),
@@ -186,7 +195,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return getOuterScope();
}
},
modifierList.getAnnotationEntries()
annotationEntries
);
}
else {

View File

@@ -940,6 +940,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (ArgumentTypeResolver.isFunctionLiteralArgument(baseExpression, context)) {
context.trace.report(NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION.on(operationSign));
if (baseTypeInfo == null) {
return TypeInfoFactoryKt.createTypeInfo(ErrorUtils.createErrorType("Unresolved lambda expression"), context);
}
return baseTypeInfo;
}
assert baseTypeInfo != null : "Base expression was not processed: " + expression;
@@ -1584,7 +1587,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
public KotlinTypeInfo visitAnnotatedExpression(KtAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
if (!(expression.getBaseExpression() instanceof KtObjectLiteralExpression)) {
// annotations on object literals are resolved later inside LazyClassDescriptor
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
}
KtExpression baseExpression = expression.getBaseExpression();
if (baseExpression == null) {

View File

@@ -187,7 +187,7 @@ public class ControlStructureTypingUtils {
@Override
public void updateInfo(@NotNull ValueArgument valueArgument, @NotNull DataFlowInfo dataFlowInfo) {
//todo
dataFlowInfoForArgumentsMap.put(valueArgument, dataFlowInfo);
}
@NotNull

View File

@@ -109,7 +109,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
if (elseBranch == null) {
if (thenBranch != null) {
KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
// If jump was possible, take condition check info as the jump info
return result.getJumpOutPossible()
? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
@@ -119,7 +119,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
}
if (thenBranch == null) {
return getTypeInfoWhenOnlyOneBranchIsPresent(
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
}
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
@@ -135,42 +135,51 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
BindingContext bindingContext = context.trace.getBindingContext();
KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
assert thenTypeInfo != null : "'Then' branch of if expression was not processed: " + ifExpression;
assert elseTypeInfo != null : "'Else' branch of if expression was not processed: " + ifExpression;
assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
KotlinType thenType = thenTypeInfo.getType();
KotlinType elseType = elseTypeInfo.getType();
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
if (resultType != null && thenType != null && elseType != null) {
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
}
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition ||
thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
DataFlowInfo resultDataFlowInfo;
if (thenType == null && elseType == null) {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
if (elseTypeInfo == null) {
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
}
else if (thenType == null || (jumpInThen && !jumpInElse)) {
resultDataFlowInfo = elseDataFlowInfo;
}
else if (elseType == null || (jumpInElse && !jumpInThen)) {
resultDataFlowInfo = thenDataFlowInfo;
else if (thenTypeInfo == null) {
loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
}
else {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
KotlinType thenType = thenTypeInfo.getType();
KotlinType elseType = elseTypeInfo.getType();
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
if (resultType != null && thenType != null && elseType != null) {
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
}
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
if (thenType == null && elseType == null) {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
else if (thenType == null || (jumpInThen && !jumpInElse)) {
resultDataFlowInfo = elseDataFlowInfo;
}
else if (elseType == null || (jumpInElse && !jumpInThen)) {
resultDataFlowInfo = thenDataFlowInfo;
}
else {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
}
// If break or continue was possible, take condition check info as the jump info
return TypeInfoFactoryKt.createTypeInfo(resultType, resultDataFlowInfo, loopBreakContinuePossible,
loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
@@ -183,8 +192,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
@NotNull DataFlowInfo presentInfo,
@NotNull DataFlowInfo otherInfo,
@NotNull ExpressionTypingContext context,
@NotNull KtIfExpression ifExpression,
boolean isStatement
@NotNull KtIfExpression ifExpression
) {
ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
.replaceContextDependency(INDEPENDENT);
@@ -561,8 +569,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
parentDeclaration = PsiTreeUtil.getParentOfType(parentDeclaration, KtDeclaration.class);
}
assert parentDeclaration != null : "Can't find parent declaration for " + expression.getText();
// Parent declaration can be null in code fragments or in some bad error expressions
DeclarationDescriptor declarationDescriptor = context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
Pair<FunctionDescriptor, PsiElement> containingFunInfo =
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(declarationDescriptor, false);
FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();

View File

@@ -194,7 +194,15 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
// todo save scope before analyze and fix debugger: see CodeFragmentAnalyzer.correctContextForExpression
BindingContextUtilsKt.recordScope(context.trace, context.scope, expression);
BindingContextUtilsKt.recordDataFlowInfo(context.replaceDataFlowInfo(result.getDataFlowInfo()), expression);
recordTypeInfo(expression, result);
try {
// Here we have to resolve some types, so the following exception is possible
// Example: val a = ::a, fun foo() = ::foo
recordTypeInfo(expression, result);
}
catch (ReenteringLazyValueComputationException e) {
context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
return TypeInfoFactoryKt.noTypeInfo(context);
}
return result;
}
catch (ProcessCanceledException e) {

View File

@@ -29,7 +29,7 @@ import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class ClsWrapperStubPsiFactory extends StubPsiFactory {
public class ClsWrapperStubPsiFactory extends StubPsiFactory {
public static final Key<LightElementOrigin> ORIGIN = Key.create("ORIGIN");
private final StubPsiFactory delegate = new ClsStubPsiFactory();
@@ -51,13 +51,19 @@ class ClsWrapperStubPsiFactory extends StubPsiFactory {
@Override
public PsiClass createClass(@NotNull PsiClassStub stub) {
final PsiElement origin = getOriginalElement(stub);
if (origin == null) return delegate.createClass(stub);
return new ClsClassImpl(stub) {
@NotNull
@Override
public PsiElement getNavigationElement() {
return origin;
if (origin != null) return origin;
return super.getNavigationElement();
}
@Nullable
@Override
public PsiClass getSourceMirrorClass() {
return null;
}
};
}

View File

@@ -284,13 +284,12 @@ open class KtLightClassForExplicitDeclaration(
}
if (classOrObject.hasModifier(PRIVATE_KEYWORD)) {
// Top-level private class has PUBLIC visibility in Java
// Top-level private class has PACKAGE_LOCAL visibility in Java
// Nested private class has PRIVATE visibility
psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PUBLIC else PsiModifier.PRIVATE)
psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE)
}
if (!psiModifiers.contains(PsiModifier.PRIVATE) && !psiModifiers.contains(PsiModifier.PROTECTED)) {
psiModifiers.add(PsiModifier.PUBLIC) // For internal (default) visibility
else if (!psiModifiers.contains(PsiModifier.PROTECTED)) {
psiModifiers.add(PsiModifier.PUBLIC)
}

View File

@@ -1,14 +1,5 @@
package-fragment kotlin
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> Array(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, T>): kotlin.Array<T>
public inline fun BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Boolean>): kotlin.BooleanArray
public inline fun ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Byte>): kotlin.ByteArray
public inline fun CharArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Char>): kotlin.CharArray
public inline fun DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Double>): kotlin.DoubleArray
public inline fun FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Float>): kotlin.FloatArray
public inline fun IntArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Int>): kotlin.IntArray
public inline fun LongArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Long>): kotlin.LongArray
public inline fun ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Short>): kotlin.ShortArray
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> arrayOf(/*0*/ vararg elements: T /*kotlin.Array<out T>*/): kotlin.Array<T>
public fun </*0*/ reified @kotlin.internal.PureReifiable() T> arrayOfNulls(/*0*/ size: kotlin.Int): kotlin.Array<T?>
public fun booleanArrayOf(/*0*/ vararg elements: kotlin.Boolean /*kotlin.BooleanArray*/): kotlin.BooleanArray
@@ -31,7 +22,7 @@ public open class Any {
}
public final class Array</*0*/ T> : kotlin.Cloneable {
/*primary*/ private constructor Array</*0*/ T>()
public constructor Array</*0*/ T>(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> T)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.Array<T>
@@ -51,6 +42,7 @@ public final class Boolean : kotlin.Comparable<kotlin.Boolean> {
public final class BooleanArray : kotlin.Cloneable {
/*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int)
public constructor BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Boolean)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.BooleanArray
@@ -124,6 +116,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte> {
public final class ByteArray : kotlin.Cloneable {
/*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int)
public constructor ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Byte)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.ByteArray
@@ -168,6 +161,7 @@ public final class Char : kotlin.Comparable<kotlin.Char> {
public final class CharArray : kotlin.Cloneable {
/*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int)
public constructor CharArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Char)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.CharArray
@@ -290,6 +284,7 @@ public final class Double : kotlin.Number, kotlin.Comparable<kotlin.Double> {
public final class DoubleArray : kotlin.Cloneable {
/*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int)
public constructor DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Double)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.DoubleArray
@@ -383,6 +378,7 @@ public final class Float : kotlin.Number, kotlin.Comparable<kotlin.Float> {
public final class FloatArray : kotlin.Cloneable {
/*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int)
public constructor FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Float)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.FloatArray
@@ -466,6 +462,7 @@ public final class Int : kotlin.Number, kotlin.Comparable<kotlin.Int> {
public final class IntArray : kotlin.Cloneable {
/*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int)
public constructor IntArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Int)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.IntArray
@@ -546,6 +543,7 @@ public final class Long : kotlin.Number, kotlin.Comparable<kotlin.Long> {
public final class LongArray : kotlin.Cloneable {
/*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int)
public constructor LongArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Long)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.LongArray
@@ -642,6 +640,7 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short> {
public final class ShortArray : kotlin.Cloneable {
/*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int)
public constructor ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Short)
public final val size: kotlin.Int
public final fun <get-size>(): kotlin.Int
public open override /*1*/ fun clone(): kotlin.ShortArray
@@ -675,10 +674,10 @@ public open class Throwable {
public constructor Throwable(/*0*/ message: kotlin.String?)
/*primary*/ public constructor Throwable(/*0*/ message: kotlin.String?, /*1*/ cause: kotlin.Throwable?)
public constructor Throwable(/*0*/ cause: kotlin.Throwable?)
public final val cause: kotlin.Throwable?
public final fun <get-cause>(): kotlin.Throwable?
public final val message: kotlin.String?
public final fun <get-message>(): kotlin.String?
public open val cause: kotlin.Throwable?
public open fun <get-cause>(): kotlin.Throwable?
public open val message: kotlin.String?
public open fun <get-message>(): kotlin.String?
}
public object Unit {

View File

@@ -54,12 +54,14 @@ val b by a
L0:
1 <START>
v(val b by a)
r(a) -> <v0>
magic[VALUE_CONSUMER](val b by a|<v0>) -> <v1>
magic[UNRECOGNIZED_WRITE_RHS](val b by a) -> <v0>
w(b|<v0>)
r(a) -> <v1>
magic[VALUE_CONSUMER](val b by a|<v1>) -> <v2>
L1:
<END> NEXT:[<SINK>]
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================

View File

@@ -19,6 +19,7 @@ Delegate() <v0>: Delegate NEW: call(Delegate(), <init>) -> <v0>
== b ==
val b by a
---------------------
<v1>: * NEW: magic[VALUE_CONSUMER](val b by a|<v0>) -> <v1>
a <v0>: Delegate NEW: r(a) -> <v0>
<v0>: Int NEW: magic[UNRECOGNIZED_WRITE_RHS](val b by a) -> <v0>
<v2>: * NEW: magic[VALUE_CONSUMER](val b by a|<v1>) -> <v2>
a <v1>: Delegate NEW: r(a) -> <v1>
=====================

View File

@@ -4,14 +4,16 @@ val foo: Int by throw NullPointerException()
L0:
1 <START>
v(val foo: Int by throw NullPointerException())
magic[UNRECOGNIZED_WRITE_RHS](val foo: Int by throw NullPointerException()) -> <v0>
w(foo|<v0>)
mark(throw NullPointerException())
mark(NullPointerException())
call(NullPointerException(), <init>) -> <v0>
throw (throw NullPointerException()|<v0>) NEXT:[<ERROR>]
call(NullPointerException(), <init>) -> <v1>
throw (throw NullPointerException()|<v1>) NEXT:[<ERROR>]
L1:
<END> NEXT:[<SINK>] PREV:[]
<END> NEXT:[<SINK>] PREV:[]
error:
<ERROR> PREV:[throw (throw NullPointerException()|<v0>)]
<ERROR> PREV:[throw (throw NullPointerException()|<v1>)]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
<SINK> PREV:[<ERROR>, <END>]
=====================

View File

@@ -1,5 +1,6 @@
== foo ==
val foo: Int by throw NullPointerException()
---------------------
NullPointerException() <v0>: {<: Throwable} NEW: call(NullPointerException(), <init>) -> <v0>
=====================
<v0>: Int NEW: magic[UNRECOGNIZED_WRITE_RHS](val foo: Int by throw NullPointerException()) -> <v0>
NullPointerException() <v1>: {<: Throwable} NEW: call(NullPointerException(), <init>) -> <v1>
=====================

View File

@@ -2,6 +2,8 @@ public fun <T> Iterable<T>.myforEach(operation: (T) -> Unit) : Unit {
for (element in this) operation(element)
}
public fun println(v: Any?) {}
fun foo1() {
(1..5).myforEach {
println(it)

View File

@@ -3,5 +3,5 @@ import wrong.*
fun foo(x: ClassWithWrongAbiVersion) {
bar()
1.printStackTrace(2, 3)
1.replaceIndent(2, 3)
}

View File

@@ -3,11 +3,9 @@ compiler/testData/cli/jvm/wrongAbiVersion.kt:4:5: error: unresolved reference: b
bar()
^
compiler/testData/cli/jvm/wrongAbiVersion.kt:6:7: error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun kotlin.Throwable.printStackTrace(): kotlin.Unit defined in kotlin
public fun kotlin.Throwable.printStackTrace(stream: java.io.PrintStream): kotlin.Unit defined in kotlin
public fun kotlin.Throwable.printStackTrace(writer: java.io.PrintWriter): kotlin.Unit defined in kotlin
public fun kotlin.String.replaceIndent(newIndent: kotlin.String = ...): kotlin.String defined in kotlin.text
(note: this may be caused by the fact that some classes compiled with an incompatible version of Kotlin were found in the classpath. Such classes cannot be loaded properly by this version of Kotlin compiler. See below for more information)
1.printStackTrace(2, 3)
1.replaceIndent(2, 3)
^
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/ClassWithWrongAbiVersion.class: error: class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 0.30.0, expected version is $ABI_VERSION$
COMPILATION_ERROR

View File

@@ -0,0 +1,10 @@
class My {
companion object {
private val my: String = "O"
get() = field + "K"
fun getValue() = my
}
}
fun box() = My.getValue()

View File

@@ -0,0 +1,10 @@
class My {
companion object {
private val my: String = "O"
get() = { field }() + "K"
fun getValue() = my
}
}
fun box() = My.getValue()

View File

@@ -0,0 +1,20 @@
class IntentionsBundle {
companion object {
fun message(key: String): String {
return key + BUNDLE
}
fun message2(key: String): String {
return { key + BUNDLE }()
}
private const val BUNDLE = "K"
}
}
fun box(): String {
if (IntentionsBundle.message("O") != "OK") return "fail 1: ${IntentionsBundle.message("O")}"
return IntentionsBundle.message2("O")
}

View File

@@ -0,0 +1,38 @@
//KT-10934 compiler throws UninferredParameterTypeConstructor in when block that covers all types
class Parser<TInput, TValue>(val f: (TInput) -> Result<TInput, TValue>) {
operator fun invoke(input: TInput): Result<TInput, TValue> = f(input)
fun <TIntermediate, TValue2> mapJoin(
selector: (TValue) -> Parser<TInput, TIntermediate>,
projector: (TValue, TIntermediate) -> TValue2
): Parser<TInput, TValue2> {
return Parser({ input ->
val res = this(input)
when (res) {
is Result.ParseError -> Result.ParseError(res.productionLabel, res.child, res.rest)
is Result.Value -> {
val v = res.value
val res2 = selector(v)(res.rest)
when (res2) {
is Result.ParseError -> Result.ParseError(res2.productionLabel, res2.child, res2.rest)
is Result.Value -> Result.Value(projector(v, res2.value), res2.rest)
}
}
}
})
}
}
/** A parser can return one of two Results */
sealed class Result<TInput, TValue> {
class Value<TInput, TValue>(val value: TValue, val rest: TInput) : Result<TInput, TValue>() {}
class ParseError<TInput, TValue>(val productionLabel: String,
val child: ParseError<TInput, *>?,
val rest: TInput) : Result<TInput, TValue>() {}
}
fun box() = "OK"

View File

@@ -0,0 +1,15 @@
class A(val s: String = "FAIL")
private fun foo(a: A?, aOther: A?): A {
return if (a == null) {
A()
}
else {
if (aOther == null) {
return A()
}
aOther
}
}
fun box() = foo(A("???"), A("OK")).s

View File

@@ -0,0 +1,21 @@
class MyThrowable(message: String? = null, cause: Throwable? = null) : Throwable(message, cause) {
override val message: String?
get() = "My message: " + super.message
override val cause: Throwable?
get() = super.cause ?: this
}
fun box(): String {
try {
throw MyThrowable("test")
} catch (t: MyThrowable) {
if (t.cause != t) return "fail t.cause"
if (t.message != "My message: test") return "fail t.message"
return "OK"
}
return "fail: MyThrowable wasn't catched."
}

View File

@@ -0,0 +1,26 @@
interface Option<out T> {
val s: String
}
class Some<T>(override val s: String) : Option<T>
class None(override val s: String = "None") : Option<Int>
fun whenTest(a: Int): Option<Any> = when (a) {
239 -> {
if (a == 239) Some("239") else None()
}
else -> if (a != 239) Some("$a") else None()
}
fun ifTest(a: Int): Option<Any> = if (a == 239) {
if (a == 239) Some("239") else None()
} else if (a != 239) Some("$a") else None()
fun box(): String {
if (whenTest(2).s != "2") return "Fail 1"
if (whenTest(239).s != "239") return "Fail 2"
if (ifTest(2).s != "2") return "Fail 3"
if (ifTest(239).s != "239") return "Fail 4"
return "OK"
}

View File

@@ -0,0 +1,5 @@
import test.*
fun box(): String {
return ContentTypeByExtension.processRecords { ext -> ext }
}

View File

@@ -0,0 +1,18 @@
package test
object ContentTypeByExtension {
inline fun processRecords(crossinline operation: (String) -> String) =
listOf("O", "K").map {
val ext = B(it)
operation(ext.toLowerCase())
}.joinToString("")
}
inline fun A.toLowerCase(): String = (this as B).value
open class A
open class B(val value: String) : A()

View File

@@ -0,0 +1,5 @@
import test.*
fun box(): String {
return ContentTypeByExtension.processRecords { ext -> ext }
}

View File

@@ -0,0 +1,18 @@
package test
object ContentTypeByExtension {
inline fun processRecords(crossinline operation: (String) -> String) =
{
val ext = B("OK")
operation(ext.toLowerCase())
}()
}
inline fun A.toLowerCase(): String = (this as B).value
open class A
open class B(val value: String) : A()

View File

@@ -0,0 +1,5 @@
import test.*
fun box(): String {
return processRecords { ext -> ext + "K" }
}

View File

@@ -0,0 +1,5 @@
package test
inline fun foo(x: String) = x
inline fun processRecords(block: (String) -> String) = block(foo("O"))

View File

@@ -0,0 +1,5 @@
import test.*
fun box(): String {
return processRecords { "O" + it }
}

View File

@@ -0,0 +1,11 @@
package test
inline fun foo(x: String) = x
class A {
fun test(s: String) = s
}
inline fun processRecords(block: (String) -> String): String {
return A().test(block(foo("K")))
}

View File

@@ -0,0 +1,7 @@
import test.*
fun box(): String {
val result = processRecords { "B" + it }
return if (result == "BOK1") "OK" else "fail: $result"
}

View File

@@ -0,0 +1,11 @@
package test
inline fun foo(x: String, y: String) = x + y
class A {
fun test(s: String) = s
}
inline fun processRecords(block: (String) -> String): String {
return A().test(block(foo("O", foo("K", "1"))))
}

View File

@@ -0,0 +1,5 @@
import test.*
fun box(): String {
return processRecords { a, b -> a + b}
}

View File

@@ -0,0 +1,10 @@
package test
inline fun foo(x: String) = x
fun test(a: String, s: String) = s
inline fun processRecords(block: (String, String) -> String): String {
return test("stub", block(foo("O"), foo("K")))
}

View File

@@ -1,3 +1,7 @@
import a.foo
import a.inlineOnly
fun box(): String = foo { "OK" }
fun box(): String {
if (!a.inlineOnly<String>("OK")) return "fail 1"
return foo { "OK" }
}

View File

@@ -3,4 +3,6 @@ package a
inline fun foo(body: () -> String): String = bar(body())
public fun bar(x: String): String = x
public fun bar(x: String): String = x
inline fun <reified T> inlineOnly(x: Any?): Boolean = x is T

View File

@@ -0,0 +1,5 @@
import test.*
fun box(): String {
return IntentionsBundle.message()
}

View File

@@ -0,0 +1,14 @@
package test
class IntentionsBundle {
companion object {
internal inline fun message(): String {
return KEY + BUNDLE
}
private const val BUNDLE = "K"
protected const val KEY = "O"
}
}

View File

@@ -0,0 +1,7 @@
import test.*
fun box(): String {
return call {
"O"
}
}

View File

@@ -0,0 +1,18 @@
package test
private class S public constructor() {
class Z {
fun a(): String {
return "K"
}
}
}
// This function exposes S.Z which is a class nested into a private class S (package-private in the byte code)
// It can be accessed outside the `test` package now that S.Z. is public in the byte code, but it may be changed later
internal inline fun call(s: () -> String): String {
return s() + test().a()
}
private fun test(): S.Z {
return S.Z()
}

View File

@@ -0,0 +1,7 @@
import test.*
fun box(): String {
return call {
"O"
}
}

View File

@@ -0,0 +1,23 @@
package test
private class S {
fun a(): String {
return "K"
}
}
// This function exposes S which is a private class (package-private in the byte code)
// It can be accessed outside the `test` package, which may lead to IllegalAccessError.
// This behavior may be changed later
internal inline fun call(s: () -> String): String {
val s = test()
return s() + test2(s)
}
private fun test(): S {
return S()
}
private fun test2(s: S): String {
return s.a()
}

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