Compare commits

..

342 Commits

Author SHA1 Message Date
Simon Ogorodnik
a2bc2cc53c Minor: Fix dokka config
Revert "Fix documentation for stdlib"

This reverts commit e14de32939.
2017-03-20 19:54:12 +03:00
Simon Ogorodnik
2e7da8fcae Minor: Add Dokka format param to build-docs script
To have an ability to change it in TeamCity between custom builds
2017-03-15 19:44:48 +03:00
Simon Ogorodnik
e14de32939 Fix documentation for stdlib
Add forgotten files to file list used by
Dokka when generating documentation
2017-03-15 18:22:54 +03:00
Mikhael Bogdanov
40b00ee5b5 Test data fix 2017-03-14 09:38:31 +01:00
Mikhail Zarechenskiy
47369d1191 Add note about JS to the changelog 2017-03-13 21:06:19 +03:00
Mikhail Zarechenskiy
e85d6d9803 Remove KT-15200 from the changelog
It was postponed until 1.1.2
2017-03-13 20:42:33 +03:00
Mikhail Zarechenskiy
4d26204ef9 Update Changelog for version 1.1.1 2017-03-13 17:18:29 +03:00
Mikhael Bogdanov
e62255b517 Fix for KT-16801: Accessors of @PublishedApi property gets mangled
#KT-16801 Fixed

(cherry picked from commit ce3b455)
2017-03-13 11:12:08 +01:00
Yan Zhulanow
073c3bd7da Do not check if the star projection contains local types to avoid stack overflow.
Fixes EA-95181.
2017-03-13 02:14:41 +03:00
Denis Zharkov
87cc248fca Add diagnostic info to assertion on type argument consistency 2017-03-10 18:22:12 +03:00
Denis Zharkov
5110affb2c Revert "Make computation of arguments for raw types lazy"
This reverts commit 9cf54bf83f.
2017-03-10 15:57:44 +03:00
Stanislav Erokhin
7a8b85a916 Fix potential CCE -- use unwrappedType after instanceof check. 2017-03-10 15:15:07 +03:00
Mikhail Glukhikh
d363ae94d8 Do not run write actions from J2K #KT-16714 Fixed
Also #EA-97363 Fixed

(cherry picked from commit 5e8afd2)
2017-03-10 14:57:22 +03:00
Denis Zharkov
9cf54bf83f Make computation of arguments for raw types lazy
See how we translate raw types to Kotlin model:
RawType(A) = A<ErasedUpperBound(T1), ...>
ErasedUpperBound(T : G<t>) = G<*> // UpperBound(T) is a type G<t> with arguments
ErasedUpperBound(T : A) = A // UpperBound(T) is a type A without arguments
ErasedUpperBound(T : F) = UpperBound(F) // UB(T) is another type parameter F

Stack overflow happens with the following classes:
class A<X extends B> // NB: raw type B in upper bound
class B<Y extends A> // NB: raw type A in upper bound

when calculating raw type for A, we start calculate ErasedUpperBound(Y),
thus starting calculating raw type for B => ErasedUpperBound(X) => RawType(A),
so we have SOE here.
The problem is that we calculating the arguments for these raw types eagerly,
while from the definition of ErasedUpperBound(Y) we only need a type constructor
of raw type B (and the number of parameters), we don't use its arguments.

The solution is to make arguments calculating for raw types lazy

 #KT-16528 Fixed
2017-03-10 13:33:50 +03:00
Ilya Gorbunov
63b6f90926 Add missing SinceKotlin to IntStream.toList.
(cherry picked from commit b83b534374)
2017-03-09 17:27:00 +03:00
Ilya Gorbunov
b8b9e43c05 Mark all api in kotlin.reflect.full package with SinceKotlin(1.1), since it actually appeared in that package only in 1.1. #KT-16557 Fixed.
It doesn't matter that some functions were since 1.0 in the old package.

(cherry picked from commit c038d3e9a3)
2017-03-09 17:27:00 +03:00
Ilya Gorbunov
98f0acdb8c Add samples for sequence building API.
(cherry picked from commit 61e8848aa2)
2017-03-09 17:27:00 +03:00
Ilya Gorbunov
ce1be19da6 Add groupingBy and eachCount sample.
(cherry picked from commit a04e6de047)
2017-03-09 17:27:00 +03:00
Ilya Gorbunov
6c1bb136ad Improve sample comments.
Improve sample for lastIndex property.

(cherry picked from commit 75ae42121b)
2017-03-09 17:27:00 +03:00
Sergey Igushkin
c6a33fb9cb Added gradle-plugins properties with fqnames
Added .property files to make the plugins available by fqnames in
order to publish them to Gradle Plugin Portal.

#KT-5756

(cherry picked from commit 991de64)

(cherry picked from commit 999ef51)
2017-03-09 14:16:45 +03:00
Mikhail Zarechenskiy
dc065cb362 Update Changelog: add link to the previous release 2017-03-09 12:07:10 +03:00
Mikhail Zarechenskiy
f3d769d8d5 Update Changelog for Kotlin 1.1.1-RC 2017-03-07 12:18:15 +03:00
Sergey Igushkin
2c235b0585 Enabled incremental compilation by default in Gradle plugin.
#KT-16546 Fixed

(cherry picked from commit 06715c5)
2017-03-07 11:38:04 +03:00
Dmitry Petrov
161c67c2ac Potential fix for KT-16673
See also:
http://stackoverflow.com/questions/42571812/unsupportedoperationexception-while-building-a-kotlin-project-in-idea

'original' for SamAdapterFunctionScope.MyFunctionDescriptor#doSubstitute should exactly match 'this.original',
so we can just provide it by default in SamAdapterFunctionScope.MyFunctionDescriptor#newCopyBuilder.
2017-03-06 22:02:15 +03:00
Mikhail Zarechenskiy
1bf290903a Disable InterfaceDefaultMethodCallChecker checker
This checker is disabled due to its incorrect behaviour and will
be available again in 1.1.2
2017-03-06 22:02:08 +03:00
Dmitry Jemerov
b7888138cf "Configure Kotlin plugin updates" shows 1.2 and doesn't show 1.0.x
(cherry picked from commit 268f7b7)
2017-03-06 19:53:45 +01:00
Ilya Chernikov
c25e26fd0d Implement verification workaround for annotation-like class InvalidScriptResolverAnnotation
fixes #KT-16621
2017-03-06 16:27:39 +01:00
Sergey Mashkov
ec6189a860 Revert "EA-88059 - assert: CompositeElement.addChild"
This reverts commit 6bcffb8289.
2017-03-06 18:06:07 +03:00
Sergey Mashkov
4c4c62e815 Revert "EA-86479 - ISE: PomFile.<init>"
This reverts commit da50776e80.
2017-03-06 18:06:01 +03:00
Sergey Mashkov
da50776e80 EA-86479 - ISE: PomFile.<init>
don't apply any inspections for inappropriate pom files
2017-03-06 17:35:50 +03:00
Sergey Mashkov
6bcffb8289 EA-88059 - assert: CompositeElement.addChild
ensure parent element for anchor elements so we never try to insert at wrong place
2017-03-06 17:35:50 +03:00
Alexander Udalov
072524946f Allow references to nested class constructors in objects in LV = 1.0
#KT-16598 Fixed

(cherry picked from commit 0111c4d581)
2017-03-06 14:20:21 +03:00
Mikhail Zarechenskiy
a02ffd6d2b Regenerate tests: add missing LightAnalysisCodegen test
This kind of tests presents in 1.1.1 but not in master
2017-03-06 14:00:30 +03:00
Anton Bannykh
20d92e161e JS: mute some tests with extension functions in external declarations
(cherry-picked 4c6b9b695c)
2017-03-03 21:55:03 +03:00
Anton Bannykh
94cbe71eff JS: prohibited extension function arguments in external functions; removed extension receiver in jQuery declarations.
(cherry-picked from fcffd190d0)
2017-03-03 20:44:26 +03:00
Sergey Igushkin
97420afb3d Fix for androidTest variants of Android Gradle build.
Added a workaround reflection call to TaskManager to create a
javac task since it is missing for androidTest variants with jack.
Added source configuration with the tested variant to make
the tested sources visible to the compiler.

#KT-16434 Fixed

(cherry picked from commit 84efd05)
2017-03-03 15:34:25 +03:00
Mikhael Bogdanov
8c2bcc6eaa Fix for KT-16581: VerifyError when calling default value parameter with jvm-target 1.8
#KT-16581 Fixed

(cherry picked from commit a03ed6f)
2017-03-03 12:00:49 +01:00
Ilya Chernikov
a4ea155d22 Do not pollute IDEA log with fake script dependencies 2017-03-03 10:54:20 +01:00
Mikhail Zarechenskiy
fe956668b3 Add test for class delegation with private constructor
#KT-16583 Obsolete
2017-03-02 18:43:06 +03:00
Mikhail Zarechenskiy
1e8e740816 Fix access to top-level declarations inside anonymous initializer
#KT-16583 Fixed
2017-03-02 18:38:42 +03:00
Denis Zharkov
f177af12d7 Fix substitutor for synthetic SAM adapters
When synthetic member comes not from the receiver type itself,
but from one of its supertypes it doesn't make sense to subsitute
the member with receiver type, we should obtain relevant supertype
and use it instead.

 #KT-16578 Fixed
2017-03-02 15:07:35 +03:00
Simon Ogorodnik
7a63d1af24 Revert "Fix Show implementation to show inheritance through type-aliases"
This reverts commit 7e59108cae.
2017-03-01 23:49:14 +03:00
Simon Ogorodnik
7e59108cae Fix Show implementation to show inheritance through type-aliases
Show implementation(Ctrl-Hover) now should show classes which inherit such class through type-alias
 #KT-15200 fixed

(cherry picked from commit 6dd75f6)
2017-03-01 23:14:20 +03:00
Simon Ogorodnik
b18f790d10 Fix of <ERROR CLASS>-es pointing to public TypeAliases
(cherry picked from commit 000da2f)
2017-03-01 16:19:28 +01:00
Dmitry Jemerov
b861a432c9 Don't generate documentation for option that doesn't work in Gradle
(cherry picked from commit 78b4cbd)
2017-03-01 16:19:28 +01:00
Alexey Andreev
951b1d527a JS: add some docs to declarations related to interop
(cherry picked from commit 0c0e0aa)
2017-03-01 16:19:28 +01:00
Dmitry Jemerov
8c3d13b31f Assorted stdlib KDocs
(cherry picked from commit 322379e)
2017-03-01 16:19:28 +01:00
Dmitry Jemerov
fc135efb21 Build multiplatform stdlib docs
(cherry picked from commit 1d86bd5)
2017-03-01 16:19:27 +01:00
Dmitry Jemerov
596adb9b1e Extract separate target for preprocessing JS stdlib sources
(cherry picked from commit adc937c)
2017-03-01 16:19:27 +01:00
Mikhail Glukhikh
c506871195 Change log: note about javaClass added
(cherry picked from commit 91cd590)

(cherry picked from commit 4c69c34)
2017-03-01 10:32:56 +03:00
Mikhail Glukhikh
15b99c3629 Change log 1.1: added link to 1.1-rc
(cherry picked from commit 4d76cc1)
2017-03-01 10:32:42 +03:00
Mikhail Glukhikh
4f859fd727 Change log for 1.1 (release)
(cherry picked from commit afd6e0d)
2017-03-01 10:32:33 +03:00
Alexey Sedunov
716d00338e Kotlin Facet: Do not concat "additional argument" string as configuration gets duplicated
KT-16548 Fixed

(cherry picked from commit 387c91f)
2017-02-28 16:29:38 +03:00
Alexey Sedunov
d2ab12bc97 Kotlin Facet: Import more configuration options from Maven
(cherry picked from commit dca696f)
2017-02-28 15:00:32 +03:00
Alexey Sedunov
cefa344a77 Kotlin Facet: Import Maven option specified in <jvmTarget> element
#KT-16329 In Progress

(cherry picked from commit 358a0ae)
2017-02-28 15:00:31 +03:00
Alexander Udalov
19814558f8 Update KotlinVersion.CURRENT to 1.1.1 2017-02-28 13:40:48 +03:00
Alexander Udalov
c8a00fc012 Specify language / API version in .idea/kotlinc.xml
(cherry picked from commit d124912c91)
2017-02-28 13:28:08 +03:00
Yan Zhulanow
9d942383f1 Force using the 'kotlin-stdlib-jre7' artifact when configuring Android modules with JDK >= 1.8 as Dex can't process our 'kotlin-stdlib-jre8' artifact.
This fixes KT-16530: Configure Kotlin in Project inserts dependency to kotlin-stdlib-jre8 in Android projects.
2017-02-27 20:21:14 +03:00
Nikolay Krasko
e81f19c30a Use doResume name for suspend lambdas context (KT-16481)
#KT-16481 Fixed

(cherry picked from commit f0be88f)
2017-02-27 15:28:09 +03:00
Nikolay Krasko
896be11aaa Count JVM class name for inlined function from base declaration
Drop code with naive removing all anonymous classes.
Breakpoints now works when inline call is in anonymous call.

(cherry picked from commit dffbe0f)
2017-02-27 15:28:02 +03:00
Nikolay Krasko
a9b5ddd7d2 Refactoring: use constants instead of string literals
(cherry picked from commit cd92e3f)
2017-02-27 15:27:55 +03:00
Mikhael Bogdanov
340036fbcb Test data fix 2017-02-27 11:05:28 +01:00
Mikhael Bogdanov
4d80738dd6 Fix for KT-16441: NoSuchFieldError: $$delegatedProperties when delegating through provideDelegate in companion object
#KT-16441 Fixed

(cherry picked from commit d24ebf7)
2017-02-27 11:02:37 +01:00
Yan Zhulanow
307a5001ac Remove kotlin-annotation-processing artifact from the serialized compiler options. It is unused in kapt3 (or if no annotation processor dependencies are provided) but is still imported into the IDEA module files. This leads to compilation error due to the plugin incompatibility.
Incompatibility reason: kotlin-annotation-processing has references to the shaded intellij-core, so, being provided to the unshaded kotlinc from the Kotlin plugin, it throws the AbstractMethodError.

This fixes #KT-16184.
2017-02-27 00:35:07 +03:00
Dmitry Jemerov
0cfaea28a1 Disable @PublishedApi quickfix
(cherry picked from commit 9356781)
2017-02-26 13:38:02 +01:00
Ilya Chernikov
6f651d7338 Use sessions with connection to eliminate asyn shutdown problems 2017-02-24 16:51:09 +01:00
Ilya Chernikov
9329eaa457 Make daemon connection more reliable by retrying on certain exceptions 2017-02-24 16:51:09 +01:00
Alexey Tsvetkov
50ffc8d0c5 Start daemon with explicit server ip address to prevent host name resolution
(cherry picked from commit 7b35ce0)
2017-02-24 16:51:09 +01:00
Ilya Chernikov
01a1aa9b62 Attempt to fix flaky parallel daemon test 2017-02-24 16:51:09 +01:00
Ilya Chernikov
4b2f4f0bc2 Fixes after review 2017-02-24 16:51:09 +01:00
Ilya Chernikov
6a449faf5d Adjust test after introducing shutdown delay 2017-02-24 16:51:09 +01:00
Ilya Chernikov
d0f7edab08 Implement more reliable daemon election, fixes KT-15562
also making shutdown more reliable
2017-02-24 16:51:09 +01:00
Ilya Chernikov
716956f917 Add test reproducing "Service is dying" problem (KT-15562) 2017-02-24 16:51:09 +01:00
Anton Bannykh
daf4711478 JS: changed BoxedChar visibility to internal
(cherry picked from commit 3eb5b3e08c)
2017-02-24 16:17:07 +03:00
Alexey Tsvetkov
30c2c2f17f Replace daemon's message after start with constant string
#KT-15783 fixed

When a daemon client cannot find an existing daemon, it starts a new one.
The client waits for a daemon to start and initialize.
Then the daemon is expected to signal that it is ready for compiling by printing message in stdout.
Before this change the message was the daemons' run path (a directory where all daemons store
their "flag" files).
However the path printed by the daemon was not matched by the path expected by the client somehow
on Windows for a user with a username containing non-English letters.
This commit replaces the message with the constant string.
2017-02-22 17:52:45 +03:00
Ilya Gorbunov
b9efc2e1ac Drop ERROR deprecations in JS library that were introduced in 1.1-rc
(cherry picked from commit 6e8f227121)
2017-02-22 17:30:51 +03:00
Ilya Gorbunov
9e0d31714c Drop ERROR deprecations from kotlin-reflect.
(cherry picked from commit b393c66426)
2017-02-22 17:30:50 +03:00
Ilya Gorbunov
1e8c4933f1 Drop HIDDEN deprecations from kotlin-stdlib.
(cherry picked from commit c0c01d6e49)
2017-02-22 17:30:48 +03:00
Ilya Gorbunov
6648a1f669 Drop remaining ERROR deprecations from kotlin-stdlib-js.
Leave only `native`, `parseInt`, `parseFloat` and `noImpl`.

(cherry picked from commit 8e951dee16)
2017-02-22 17:30:46 +03:00
Ilya Gorbunov
37f0bc1716 Do not refer to java packages in common completion tests
(cherry picked from commit eebb820060)
2017-02-22 17:30:44 +03:00
Ilya Gorbunov
8a0a9152da Drop entire java.util package from kotlin-stdlib-js
#KT-6561 Fixed

(cherry picked from commit 3cea5c4510)
2017-02-22 17:30:42 +03:00
Ilya Gorbunov
53c3e75740 [Standard Library] Take the javaClass deprecation back as its replacement is often inconvenient.
(cherry picked from commit 5867d27fb7)
2017-02-22 17:30:41 +03:00
Stanislav Erokhin
a9ef3845fd Fix type deserialization for suspend function types which was written by pre-release compiler.
Notes: if arity == 0, it means that type was `suspend () -> String` => arguments.size == 1, and it means that SuspendFunction0 has only one type argument and it is return type.

(cherry picked from commit 0a24bf1)
2017-02-21 18:07:20 +03:00
Alexander Udalov
17d05bb7fd Minor, improve error message
(cherry picked from commit 407815449a)
2017-02-21 14:04:59 +03:00
Mikhael Bogdanov
fbe67da5f1 Fix for KT-16411, KT-16412: Exception from compiler when try call SAM constructor where argument is callable reference to nested class inside object
#Fixed KT-16411
  #Fixed KT-16412

(cherry picked from commit a8625b6)
2017-02-21 11:42:04 +01:00
Denis Zharkov
02d8c193c8 Get rid of redundant not-null assertion for parameter
The problem was that in `Function<T>.apply(T)` T is now not-platform,
so when checking if not-null assertion is needed for parameter in SAM,
it's defined by the upper bounds of T that is a platform (Any..Any?),
and while it's definitely not marked as nullable it's still nullable
in a sense that it can contain null as a value.

So the solution is obvious

 #KT-16413 Fixed
2017-02-21 13:17:39 +03:00
Dmitry Jemerov
9240d7695c Don't overwrite explicitly specified language version in facet with version from dependencies; add tests for setting language version based on dependencies
(cherry picked from commit fc2b9f6)
2017-02-20 11:33:35 +01:00
Dmitry Jemerov
f16f97583f Don't replace explicitly configured project settings with autodetected ones 2017-02-17 14:04:57 +01:00
Dmitry Jemerov
50be60d71b Don't pass paths to non-existing metadata files from dependent modules
(cherry picked from commit 3225c93)
2017-02-16 19:17:10 +01:00
Mikhail Glukhikh
e30cd05bea Link fix 2017-02-16 20:40:40 +03:00
Mikhail Glukhikh
9c831cca8b Change log 1.1-RC: link to 1.1-Beta2 2017-02-16 20:40:08 +03:00
Mikhail Glukhikh
4467ac0b42 Change log update (final) for 1.1-RC
(cherry picked from commit 797813a)
2017-02-16 18:58:14 +03:00
Dmitry Jemerov
07a48b080b Disable facet detection; force detection of API/language level from dependencies on project opening 2017-02-16 15:14:53 +01:00
Dmitry Jemerov
09c6feddb6 Ask to update runtime library when increasing language version for module
(cherry picked from commit b0463fc)
2017-02-16 14:08:32 +01:00
Alexey Tsvetkov
9b44a7ea82 Minor: remove the word 'experimental' from Gradle IC description 2017-02-15 18:36:47 +03:00
Alexander Udalov
9013f50b28 Fix overload resolution ambiguity on *Array.clone() with runtime 1.0
#KT-16371 Fixed
2017-02-16 15:11:18 +03:00
Dmitry Jemerov
5614874bf7 Warn when running the compiler under Java 6 or 7
(cherry picked from commit 5537800)
2017-02-16 10:12:22 +01:00
Alexander Udalov
009f991ac3 Fix stub builder for builtins after cdeabf26b4
(cherry picked from commit 612481f0f4)
2017-02-16 10:43:53 +03:00
Alexander Udalov
9711854a2c Fix NPE from KotlinBuiltInDecompiler
This happened because of bae955aafd: similarly to the corresponding code in
the compiler, the IDE should also skip the metadata for kotlin.Cloneable when
decompiling built-ins because the deserializer is not going to resolve this
class from the metadata

(cherry picked from commit cdeabf26b4)
2017-02-16 01:36:51 +03:00
Dmitry Jemerov
ed98ff3dc0 Correctly locate build.gradle for modules created from source sets
(cherry picked from commit ecce92d)
2017-02-15 22:49:59 +01:00
Dmitry Jemerov
7e098e8827 Quickfixes to enable unsupported and experimental features handle API level correctly and support updating the runtime library
(cherry picked from commit 41c8168)
2017-02-15 22:49:48 +01:00
Vyacheslav Gerasimov
4b011767ef Fixed exception in getUastLocation of class annotation argument
#KT-16326 Fixed

(cherry picked from commit a2e429a)
2017-02-15 21:27:11 +03:00
Vyacheslav Gerasimov
324819d20b Fixed InvalidMirrorException in uast while getting annotation argument location
(cherry picked from commit 1452129)
2017-02-15 21:27:11 +03:00
Mikhail Glukhikh
4897af1ef9 Change log for 1.1-RC updated 2017-02-15 20:52:41 +03:00
Alexander Udalov
be0537f3f8 Suggest to provide explicit dependency on new kotlin-reflect
In case when there's kotlin-stdlib 1.1 and kotlin-reflect 1.0 in the classpath

(cherry picked from commit 8e407d548a)
2017-02-15 20:44:28 +03:00
Alexander Udalov
899ca8bc65 Infer API version from older runtime in compiler's classpath
For example, if you invoke kotlinc 1.1 with kotlin-stdlib 1.0 in the classpath,
we now infer -api-version 1.0 automatically

(cherry picked from commit 71fcb07fad)
2017-02-15 20:44:26 +03:00
Alexander Udalov
86ffd634ec Filter out files with the same paths in runtime version checker
To prevent listing them several times in the diagnostic message

(cherry picked from commit b56639a775)
2017-02-15 20:44:25 +03:00
Alexander Udalov
f30d0904fc Report warnings instead of errors in runtime version checker
(cherry picked from commit 8457ab7c58)
2017-02-15 20:44:23 +03:00
Alexander Udalov
d9b45f667d Support smart cast for nullability in LHS of class literal
#KT-16291 Fixed

(cherry picked from commit ba84338862)
2017-02-15 20:44:21 +03:00
Alexander Udalov
e159028c97 Serialize metadata for Cloneable and discard it during deserialization
#KT-16358 Fixed

(cherry picked from commit bae955aafd)
2017-02-15 20:44:19 +03:00
Alexander Udalov
11847c121a Rename FunctionImpl -> FunctionBase, restore abstract class FunctionImpl
This fixes the IncompatibleClassChangeError which happens when kotlin-reflect
1.0.x and kotlin-stdlib 1.1.x are in the classpath

 #KT-16358 In Progress

(cherry picked from commit 46bd64f59a)
2017-02-15 20:44:16 +03:00
Ilya Gorbunov
ba857a83ff Change log clarifications regarding stdlib 2017-02-15 18:15:02 +03:00
Dmitry Jemerov
7019dcf3b1 Fix Kotlin facet autodetection so that it actually works and stores the correct language/API level based on project dependencies
(cherry picked from commit 7704310)
2017-02-15 15:52:01 +01:00
Mikhail Glukhikh
46f7c37021 Change log for 1.1-RC updated
(cherry picked from commit 3bc322c)
2017-02-15 17:47:38 +03:00
Alexey Sedunov
70de1a7d2a Minor: Fix compilation 2017-02-15 16:42:10 +03:00
Yan Zhulanow
ec7b3c6240 Revert "Kapt3: Add generated source files to Java compile task after kapt execution. Filter only .java files."
This reverts commit 82c2ce3a33.
2017-02-15 16:26:17 +03:00
Yan Zhulanow
499b6c2b91 Kapt3: Fix annotation processor option passing 2017-02-15 16:26:16 +03:00
Alexey Sedunov
5d56da2567 Kotlin Facet: Facet migration workaround for the case pre-1.1-beta -> 1.1.rc+ (reset useProjectSettings to false for old configurations)
(cherry picked from commit 5d65e6b)
2017-02-15 14:42:42 +03:00
Alexey Sedunov
0e030241a6 Kotlin Facet: Detect language/API version by stdlib when "Use project settings" is enabled, but project-level language/api version is not specified explicitly
(cherry picked from commit 2e01f62)
2017-02-15 14:42:41 +03:00
Alexey Sedunov
1d3ff1d81a Kotlin Facet: Do not rewrite language/API version based on compiler arguments if they do not contain explicit language/API version
(cherry picked from commit 0d2122b)
2017-02-15 14:42:40 +03:00
Alexey Sedunov
358f572b1f Kotlin Facet: Synchronize version info on opening the configuration editor
(cherry picked from commit 2790fcf)
2017-02-15 14:42:39 +03:00
Anton Bannykh
5a14d97642 JS: concat vararg arguments using Kotlin.concat and Kotlin.concatPrimitive functions in order to be binary compatible with (Kotlin PrimitiveArray -> JS TypedArrays) mapping. 2017-02-15 14:32:12 +03:00
Dmitry Jemerov
d1f4c4c348 Use correct resolution facade for resolving cross-module links in KDoc comments
#KT-15647 Fixed

(cherry picked from commit 060a865)
2017-02-15 12:13:24 +01:00
Mikhail Glukhikh
44dd831e71 Change log for 1.1-RC added
(cherry picked from commit 4b7380b)
2017-02-15 12:50:28 +03:00
Alexey Sedunov
da5ddd76c8 Kotlin Facet: Fix detection of pre-1.1-beta JS-stdlib dependencies
(cherry picked from commit e1463f9)
2017-02-14 18:42:36 +03:00
Alexey Sedunov
fe62995274 Kotlin Facet: Reset all coroutine support flags before importing them frm Gradle
(cherry picked from commit 8c84717)
2017-02-14 17:26:20 +03:00
Stanislav Erokhin
f67f387daa Disable some features when LV=1.1 API=1.0.
Feature list:
 - bound callable references
 - local delegated properties
 - coroutines.

#KT-16017 Fixed

(cherry picked from commit b6fa10c)
2017-02-13 20:34:05 +03:00
Simon Ogorodnik
e9f33c4045 KT-16076 Completion inserts FQN kotlin.text.String
KT-14831 Don't add import statement and FQN on converting lambda to reference if typealias is used
KT-16088 Completion wrongly inserts FQN for `kotlin` package
 #KT-16076 fixed
 #KT-14831 fixed
 #KT-16088 fixed

(cherry picked from commit 2490318)
2017-02-13 16:53:43 +03:00
Ilya Gorbunov
5f24329dca Introduce 'takeUnless' function which is like 'takeIf' but with the predicate inverted.
#KT-7858

(cherry picked from commit fee676a281)
2017-02-13 16:11:21 +03:00
Ilya Gorbunov
c6e9e992a4 JS kotlin.dom: deprecate asElementList harder.
Minor: correct exception message.

(cherry picked from commit c6cb389591)
2017-02-13 16:10:27 +03:00
Ilya Gorbunov
c38180efa8 Make javaClass extension property inline to remove further references from Kotlin.
(cherry picked from commit 9a7405adc6)
2017-02-13 16:10:27 +03:00
Sergey Igushkin
683f61fdc2 Fixed Kotlin2Js output not being the output of the compileKotlin2Js tasks.
Therefore, fixed Kotlin2Js output not present in JAR.
Reworked the clean behavior in regard to compileKotlin2Js tasks.
Fixed duplicate source roots passed to the compiler.

Issues:
- #KT-15829 Fixed
- #KT-16267 Fixed
- #KT-15902 Fixed
2017-02-13 15:50:47 +03:00
Alexey Sedunov
8e5853e5c3 Kotlin Gradle Plugin: Extend implicit argument set
(cherry picked from commit 1452d7e)
2017-02-13 14:58:23 +03:00
Alexey Sedunov
4bbdeb00be Line Markers: Do not attempt to resolve suspend call candidates which are not call-like expressions
(cherry picked from commit 75c56d5)
2017-02-13 14:58:14 +03:00
Alexey Sedunov
45b060d0dd Kotlin Facet: Fix stdlib dependency detection
(cherry picked from commit 574a0e6)
2017-02-13 14:57:58 +03:00
Alexey Sedunov
5c065efa20 Kotlin Facet: Scan classpath backwards when looking for kotlin-gradle-plugin dependency
#KT-15899 Fixed

(cherry picked from commit 7fbca4e)
2017-02-13 14:57:47 +03:00
Alexey Sedunov
83ca7d9b64 Extract Function: Fix detection of suspend calls containing extracted parameters
#KT-16251 Fixed

(cherry picked from commit 3c6f329)
2017-02-13 14:56:54 +03:00
Alexey Sedunov
9166f5ba9d Kotlin Facet: Check contradictory values of "coroutine support" option
#KT-16109 Fixed

(cherry picked from commit ee120a6)
2017-02-13 14:56:53 +03:00
Stanislav Erokhin
7a65e59d39 Reserve yield if it isn't function call.
(cherry picked from commit 3efda0e)
2017-02-13 07:08:51 +03:00
Dmitry Jemerov
c91f6fabd1 Ugly deadlock workaround for KT-16149: members of DataBindingComponent are calculated via annotations search which causes resolve reentrering
(cherry picked from commit 1d225ebae30bc8de811344bac804f79d2279859f)
2017-02-11 08:53:21 +01:00
Stanislav Erokhin
49f1c95171 Change IS_PRE_RELEASE to false. 2017-02-10 20:31:33 +03:00
Ilya Gorbunov
d77f20dc63 Introduce ItemArrayLike interface and replace multiple asList adapters with the single one.
(cherry picked from commit ec01200997)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
f9fb6c6a34 Massive deprecations in kotlin.dom
(cherry picked from commit 41c980bcab)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
29eb286df4 Drop pre-1.0 deprecated dom helpers.
(cherry picked from commit 365f8d0256)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
becd00f33d Provide KDoc for js collection implementations.
(cherry picked from commit 287a513f23)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
9beabdeb34 Restrict visibility of AbstractMap.SimpleEntry in JS
(cherry picked from commit 2269b9839f)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
9c738177b8 KDoc for mutable abstract collections.
Document abstract overrides.

(cherry picked from commit fc7b1c8611)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
8f3cfb5b1b KDoc for read-only abstract collections
(cherry picked from commit ef5e53b37b)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
c2fd91da65 Add a note about generic parameter variance to Iterable, Collection, List, Set, Map and their mutable counterparts.
Minor: correct docs, code formatting.

(cherry picked from commit 7c54c48e00)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
a574943696 Deprecate javaClass with replacement this::class.java.
Suppress deprecation in diagnostics tests.

(cherry picked from commit b8de78dd43)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
69b302e4f6 Remove public synthetic annotation holder methods from public API dump.
(cherry picked from commit d4d647ab00)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
9eb3925048 Add deprecated parseInt overload without radix parameter to provide better replacement.
(cherry picked from commit 84f324e04f)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
ee977bc0a1 Add LowPriority annotation to deprecated functions to allow star-importing their replacements from kotlin.reflect.full.
(cherry picked from commit da81fb3)
2017-02-10 18:23:06 +03:00
Ilya Gorbunov
07629e8a48 Search java version in java.specification.version, prepare to that starting from java 9 it will contain only a single component.
(cherry picked from commit af443ac046)
2017-02-10 18:23:06 +03:00
Ilya Chernikov
8197240eec Make maven/aether dependencies optional in the script-util 2017-02-10 15:59:11 +01:00
Ilya Chernikov
175d74ce5f Get rid of daemon-client dependency on openapi, making others "provided" 2017-02-10 15:59:10 +01:00
Ilya Chernikov
c06592ed6c Move scripting options into separate panel 2017-02-10 14:41:31 +01:00
Alexey Sedunov
b34363317a Kotlin Facet: Do not show implicit compiler arguments in "Additional arguments" field
(cherry picked from commit ba73269)
2017-02-09 15:48:31 +03:00
Alexey Sedunov
2ab47b4d6b Kotlin Gradle Plugin: Expose default compiler arguments via compilation task API
(cherry picked from commit 52102d3)
2017-02-09 15:48:30 +03:00
Alexey Sedunov
aee36ac552 Kotlin Gradle Plugin: Postpone friend dependency collection until the actual compilation as it may cause an error during Gradle-IDEA project synchronization
#KT-16174 Fixed

(cherry picked from commit 615c316)
2017-02-09 15:48:29 +03:00
Alexey Sedunov
48c64e9b43 Kotlin Facet: Always parse argument string to proper compiler arguments bean
#KT-16137 Fixed
 #KT-16157 Fixed
 #KT-16206 Fixed

(cherry picked from commit 4325632)
2017-02-09 15:48:28 +03:00
Alexey Sedunov
d2284af69d Compiler Configuration: Minor UI improvements
(cherry picked from commit 396e9af)
2017-02-09 15:48:27 +03:00
Alexey Sedunov
f9e45a1cea Kotlin Facet: Support multiple configuration editor
#KT-15914 Fixed

(cherry picked from commit 0c331a3)
2017-02-09 15:48:26 +03:00
Alexey Sedunov
7710d4576d Kotlin Facet: Combine "General" and "Compiler" tabs
(cherry picked from commit 8849d0e)
2017-02-09 15:48:25 +03:00
Alexey Sedunov
733f1166af Rename/Find Usages: Disable text occurrence search for KtParameter
(cherry picked from commit 59fe744)
2017-02-09 15:48:24 +03:00
Alexey Sedunov
b98b2b6846 Kotlin Facet: Support multiple artifact Ids corresponding to target platform
(cherry picked from commit 79e67f4)
2017-02-09 15:48:24 +03:00
Anton Bannykh
f0fcb4c513 JS: companion object dispatch receiver translation fixed (KT-16160); imported function inlining fixed.
(cherry picked fom commit a74fffeac8)
2017-02-09 15:46:56 +03:00
Anton Bannykh
d265383968 JS: fixed inlining functions called through inheritor ("fake" override) from another module (#KT-16144)
(cherry picked from commit a2431f0d85)
2017-02-09 15:46:56 +03:00
Mikhael Bogdanov
103cd381f4 Fix for KT-16225: enumValues non-reified stub implementation references nonexistent method
#KT-16225 Fixed

(cherry picked from commit b1e2db2)
2017-02-09 10:59:54 +01:00
Dmitry Petrov
c8c8894f91 Fix https://ea.jetbrains.com/browser/ea_reports/1337846:
Properly handle AbbreviatedTypeBinding for error types.
Get rid of code duplication.
2017-02-09 12:39:02 +03:00
Denis Zharkov
8c829564f1 Initialize JvmBuiltins for module configuration used in test
This method is only used within tests, and they didn't fail
mostly by coincidence.

But because of more eager reading of
JvmBuiltIns.isAdditionalBuiltInsFeatureSupported (that checks if built-ins
have been initialized) these tests started failing

(cherry picked from commit f4690eb)
2017-02-09 09:59:23 +03:00
Denis Zharkov
9d1fec77b8 Simplify compatibility mode with ll=1.0 on JDK dependent built-ins
A lot of problem arise with current solution
(loading them with lowpriority annotation + additional call checkers):
- We errorneously treated ArrayList.stream as an existing method, while
  it's just a fake override from List
- The same problem arises when creating a class delegating to List.
  Also the latter case is failing with codegen internal error
  (see issue KT-16171)

The negative side of this solution is that instead of reporting meaningful
diagnostic, there will be UNRESOLVED_REFERENCE.
But it seems to be better than having strange problems like ones described above.

 #KT-16073 Fixed
 #KT-16171 Fixed

(cherry picked from commit 1bb40af)
2017-02-09 09:59:23 +03:00
Denis Zharkov
7000b3ef33 Prohibit unsupported suspend operators
contains/get/set operators don't work properly on both backends

Also add box test checking that 'compareTo' operator works just fine

 #KT-16219 Fixed

(cherry picked from commit 80638eb)
2017-02-09 09:59:23 +03:00
Denis Zharkov
8ab204819d Mark as UNSUPPORTED suspension points in default parameters
#KT-16124 Fixed
 #KT-16218 Open

(cherry picked from commit 4921bd8)
2017-02-09 09:59:23 +03:00
Denis Zharkov
6a31cd834a Add callee name to diagnostic about illegal suspension call
#KT-15938 Fixed

(cherry picked from commit 4ee818a)
2017-02-09 09:59:23 +03:00
Denis Zharkov
8ba9e0271f Refine cc7f0e2d83
getDispatchReceiver/getExtensionReceiver always return not-null value,
but in the absence of receiver this value is equal StackValue.none(), i.e.
has a size 1

The tests were passing because of the problems with the test framework:
4b9e20ab8c

(cherry picked from commit 81c3edf)
2017-02-09 09:59:23 +03:00
Denis Zharkov
9391ff4141 Fix codegen problem with safe-call on suspension point with two receivers
#KT-16145 Fixed

(cherry picked from commit cc7f0e2)
2017-02-09 09:59:23 +03:00
Denis Zharkov
d73d42cc23 Put startCoroutineUninterceptedOrReturn header to common stdlib
(cherry picked from commit 9697196)
2017-02-09 09:59:23 +03:00
Denis Zharkov
832e777b2a Introduce createCoroutineUnchecked intrinsic
Also use it for buildSequence implenentation

 #KT-16155 Fixed

(cherry picked from commit 4f6a77c)
2017-02-09 09:59:23 +03:00
Denis Zharkov
c1cd139396 Minor. Get rid of code duplications for resume call wrapping in stdlib
Use processBareContinuationResume instead

(cherry picked from commit 230564f)
2017-02-09 09:59:23 +03:00
Denis Zharkov
09a6e9c591 Optimize startCoroutine impls, move them to common stdlib
Do not wrap initial continuation for startCoroutine in SafeContinuation

This changes leaves only internal declarations and intrinsics as platform
dependent parts of the coroutine library, the rest parts (public API)
is implemented through them in common module

(cherry picked from commit 6dde567)
2017-02-09 09:59:23 +03:00
Denis Zharkov
4101206e12 Improve coroutines library layout
- Split CoroutinesLibrary into common and JVM parts
- Get rid of startCoroutine duplications
- Make suspendCoroutine implementation to be platform independent

(cherry picked from commit a65d862)
2017-02-09 09:59:23 +03:00
Denis Zharkov
fbe49d0cc9 Introduce startCoroutineUninterceptedOrReturn coroutine intrinsic
#KT-15716 Fixed

(cherry picked from commit 258ee0d)
2017-02-09 09:59:23 +03:00
Denis Zharkov
78e4295c2c Make createCoroutine return a safe continuation
#KT-15718 Fixed

(cherry picked from commit 29b0b30)
2017-02-09 09:59:23 +03:00
Denis Zharkov
426944744d Fix VerifyError in coroutines caused by null spilling
While within a method by the JVM spec null-value has a special
Nothing-like type, when we spill it for a coroutine, we must choose
some real type to CHECKCAST to after restoring the variable's value.

But the problem is that such a real type depends on usage of that null value,
and there may be more than one usage.

The solution is not to spill such variables into fields, but instead
init them with ACONST_NULL after each suspension point

 #KT-16122 Fixed

(cherry picked from commit cc28fec)
2017-02-09 09:59:23 +03:00
Denis Zharkov
52a310f202 Support parameter destructuring in suspend lambdas
#KT-16092 Fixed

(cherry picked from commit 529b526)
2017-02-09 09:59:23 +03:00
Ilya Chernikov
894ee4ce4f Convert line endings when creating ReplCodeLine, fixes KT-15861 2017-02-08 20:54:27 +01:00
Simon Ogorodnik
08915389e2 Fix for complete slowdown of DefaultImportProvider after introducing languageVersion for default imports
KT-16243 Very slow completion after variable of type `ArrayList`
 #KT-16243 fixed

(cherry picked from commit a9f2f5c)
2017-02-08 21:32:48 +03:00
Anton Bannykh
fc6465084b JPS review fixes: simplified the code and fixed a bug in JpsJsModuleUtils.getDependencyModulesAndSources 2017-02-08 21:22:37 +03:00
Anton Bannykh
beff463a92 JPS: fixed duplicate meta.js in case of multiple source roots in the same module.
(cherry picked from commit f0e3c87b84)
2017-02-08 21:22:37 +03:00
Anton Bannykh
b67e3f824c JS: fixed support for test source roots (KT-6627)
(cherry picked from commit 289a7a9cc3)
2017-02-08 21:22:37 +03:00
Yan Zhulanow
c578e8b8f1 Kapt3: Generate import statements in stubs 2017-02-08 19:29:31 +03:00
Yan Zhulanow
0395d90ef7 Kapt3: Serialize annotation processor options to base64 to support spaces in option values 2017-02-08 19:29:25 +03:00
Yan Zhulanow
dfb21a81a0 Kapt3: Invoke integration tests with the Kotlin runtime in the compile classpath (this fixes integration tests, nullability annotations from org.jetbrains were not found) 2017-02-08 19:29:18 +03:00
Yan Zhulanow
4c69df28b4 Kapt3: Allow users to disable error type correction (and now it's disabled by default) 2017-02-08 19:28:40 +03:00
Yan Zhulanow
da1dc9cfe7 Kapt3: Use the javac's finalCompiler log to determine if there were any annotation processing errors (KT-16176) 2017-02-08 19:28:29 +03:00
Yan Zhulanow
3413cb977c Minor: Update test data because of KT-15697 2017-02-08 19:28:20 +03:00
Yan Zhulanow
d9c54449a4 Minor: Remove obsolete JAVA_FILE_PARSING_ERROR constant, fix corresponding test 2017-02-08 19:28:13 +03:00
Yan Zhulanow
cc6127a343 Kapt3: Ignore declarations with illegal Java identifiers (KT-16153) 2017-02-08 19:28:05 +03:00
Yan Zhulanow
e44d0c4d5d Kapt3: Fix working in verbose mode (NPE in JavacFiler.java:597) (KT-16146) 2017-02-08 19:27:53 +03:00
Yan Zhulanow
e6c27e7f32 Kapt3: Write Intellij annotations (NotNull/Nullable) to stubs 2017-02-08 19:26:07 +03:00
Yan Zhulanow
82c2ce3a33 Kapt3: Add generated source files to Java compile task after kapt execution. Filter only .java files.
This is needed to generate Kotlin files using kapt.
2017-02-08 19:08:43 +03:00
Sergey Igushkin
679efb61ab Fixed Kotlin2JsCompile not picking dependencies from configurations other than compile.
Example:

	apply plugin: 'kotlin2js'

    dependencies {
    	...
    	testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
    }

Here, the `:compileTestKotlin2Js` task did not pick the dependency and used the `compile` classpath.
This has been fixed.

Also, fixed `testCompileTestCouldAccessProduction` and added `testJsCustomSourceSet`.
2017-02-08 17:29:50 +03:00
Alexander Udalov
ab44f5cc0e Deprecate kotlin.reflect.findAnnotation with ERROR
(cherry picked from commit cfe159181d)
2017-02-08 13:08:12 +03:00
Alexander Udalov
277b1cbf1e Annotate findAnnotation and IllegalPropertyDelegateAccessException with SinceKotlin(1.1)
(cherry picked from commit 5987e8a47c)
2017-02-08 13:07:17 +03:00
Alexander Udalov
1ceb7f5656 Annotate new API in runtime.jvm with SinceKotlin(1.1)
(cherry picked from commit 845d6526b0)
2017-02-08 13:07:08 +03:00
Alexey Andreev
ccffa26add JS: don't treat library without JS metadata as error, report warning and continue instead. See KT-16158 2017-02-08 12:01:08 +03:00
Alexey Andreev
cfc08328e0 JS: escape quotes in some diagnostics with parametrized messages 2017-02-08 11:52:25 +03:00
Mikhael Bogdanov
f53c5ed30e Use appropriate ApiVersion if LanguageVersion is specified in test
(cherry picked from commit 37a94ea)
2017-02-08 09:11:52 +01:00
Mikhael Bogdanov
fe44159962 Revert 'Temporary disable new intrinsics usage in ieee754 arithmetic'
(cherry picked from commit 5095ef1)
2017-02-08 09:11:49 +01:00
Simon Ogorodnik
74e9a632a9 KT-16110 Missing suspend keyword completion inside generic arguments
#KT-16110 fixed

(cherry picked from commit be7158e)
2017-02-07 20:53:56 +03:00
Roman Elizarov
bb1354660d Fixed corotine context performance by using reference equality for contexts and keys
Added documentation explaining that keys are compared by reference
2017-02-07 19:38:34 +03:00
Nikolay Krasko
b95875536f Return old hack with returning null as file scope for standard scripts
(cherry picked from commit ef55bd1)
2017-02-07 15:14:49 +01:00
Ilya Chernikov
fb74040dde Fix version calculation code 2017-02-07 13:39:49 +01:00
Ilya Chernikov
4cf2bce003 Set jvmTarget property for repl compilation from sys prop or java version, fixes KT-16126 2017-02-07 13:39:49 +01:00
Mikhail Glukhikh
982e67276f Join declaration and assignment: extra descriptor check for assignment of the same property
(cherry picked from commit 81e083a)
2017-02-07 12:48:06 +03:00
Mikhail Glukhikh
9a255169ee Join declaration & assignment: do not suggest for non-first line of init / constructor #KT-15545 Fixed
(cherry picked from commit 153bc79)
2017-02-07 12:47:53 +03:00
Mikhail Glukhikh
cdeb2e80b5 Join declaration & assignment: treat assignment with this. correctly #KT-16000 Fixed
(cherry picked from commit ea6e3c8)
2017-02-07 12:47:40 +03:00
Mikhail Glukhikh
b2c7521277 Correct order added for 'suspend' modifier #KT-16104 Fixed
(cherry picked from commit 6db698f)
2017-02-07 12:47:00 +03:00
Alexander Udalov
b416769434 Update stdlib reference and binary compatibility test data
After 5cffb38
2017-02-07 10:20:34 +03:00
Alexander Udalov
ad5e3a52ff Do not import "kotlin.comparisons" by default for language version 1.0
#KT-16199 Fixed

(cherry picked from commit b780e6d374)
2017-02-07 10:19:12 +03:00
Alexander Udalov
0a54b6104a Update stdlib reference and binary compatibility test data
After 5cffb38
2017-02-06 19:46:42 +03:00
Alexander Udalov
f516b21e5b Rename DoubleColonLHS.Expression.isObject -> isObjectQualifier
(cherry picked from commit e58baa51ae)
2017-02-06 19:44:51 +03:00
Alexander Udalov
f64a25801f Fix callable reference to constructor of nested class in object
#KT-15951 Fixed

(cherry picked from commit 478352b7e7)
2017-02-06 19:44:47 +03:00
Alexander Udalov
77fc61ce73 Improve error on runtime of version different than API version
Include the actual runtime version in the error message

(cherry picked from commit ca1ed850b8)
2017-02-06 19:44:41 +03:00
Alexander Udalov
eaaf656ec9 Report different runtime versions earlier than incompatibility with API version
Previously if you had kotlin-reflect 1.0 and kotlin-runtime 1.1 in the
classpath, checkCompatibleWithApiVersion was invoked first, and an error was
reported that suggested to pass "-api-version" to the compiler. However, no
correct "-api-version" can be passed in this case, because
checkMatchingVersions would then report that the two libraries have different
versions anyway. So, now we first ensure that all libraries have the same
version, and only then do check if the version is correct

(cherry picked from commit 57f8ef372f)
2017-02-06 19:44:35 +03:00
Alexander Udalov
bb892a8510 Check API version instead of language in JVM runtime versions checker
It should be a valid case to invoke the 1.1 compiler with the 1.0 runtime in
the classpath and "-api-version 1.0". However, previously it was an error and
the message suggested to specify "-language-version 1.0". Language version 1.0
implies API version 1.0, so this effectively made the "-api-version" option
useless

(cherry picked from commit 3a7eec8635)
2017-02-06 19:44:31 +03:00
Alexander Udalov
936e787d58 Do not use LanguageVersionSettings.languageVersion directly
(cherry picked from commit 389ddf26b3)
2017-02-06 19:44:24 +03:00
Simon Ogorodnik
b82ad57472 KT-15744 Intention to import sleep wrongly suggests Thread.sleep
#KT-15744 fixed

(cherry picked from commit 98269c1)
2017-02-06 15:12:28 +03:00
Denis Zharkov
1c4ac5a74b Fix annotation deserialization on suspend functions
Use proper initial/frontend version of suspend descriptor
when writing METHOD_FOR_FUNCTION, because serializer uses this version

Also this commit contains adjustments of neighboring code to the describe
change

 #KT-16093 Fixed
2017-02-03 17:43:42 +03:00
Dmitry Jemerov
1a74058dc8 Find Usages checks that the signature of the method a property usage resolves to matches the signature of the method being searched
#KT-15291 Fixed

(cherry picked from commit 9594147)
2017-02-03 14:42:21 +01:00
Dmitry Jemerov
5ed5008db4 When calculating import candidates, skip redundant deduplication performed by PsiShortNamesCacheImpl
#KT-16071 Fixed

(cherry picked from commit faac1c3)
2017-02-03 14:42:21 +01:00
Dmitry Jemerov
34192a1785 Calculate autoimport candidates in daemon thread when import fix is created, not in EDT
(cherry picked from commit 1d37c8c)
2017-02-03 14:42:21 +01:00
Dmitry Jemerov
9ce396ad54 Look at parent project when checking whether the Kotlin Maven plugin is applied in a module
#KT-15954 Fixed

(cherry picked from commit f73d32a)
2017-02-03 14:42:21 +01:00
Mikhail Glukhikh
04364f4b3e Generate test support: error hints moved out of write action
(cherry picked from commit 4c2ae5e)
2017-02-03 14:38:12 +03:00
Mikhail Glukhikh
6028a4facc Let implement interface: create write action manually to avoid AWT events inside
(cherry picked from commit d8f0167)
2017-02-03 14:37:58 +03:00
Mikhail Glukhikh
1aba4fe4da Generate equals or hash code: do not run in write action to avoid AWT events inside
(cherry picked from commit b839e52)
2017-02-03 14:37:45 +03:00
Mikhail Glukhikh
54367bd8e8 Move file to package matching directory: run write action manually to avoid AWT events inside
(cherry picked from commit a204e57)
2017-02-03 14:37:31 +03:00
Mikhail Glukhikh
5c73c59b9e Create kotlin sub class: run write action manually to avoid AWT events inside
(cherry picked from commit 72b8b85)
2017-02-03 14:37:18 +03:00
Mikhail Glukhikh
a0c3187a93 Generate test support: ask everything before write action to avoid AWT events inside
(cherry picked from commit 9664a06)
2017-02-03 14:37:04 +03:00
Mikhail Glukhikh
9b118ff81d Create test intention: do not start in write action to avoid AWT events inside
(cherry picked from commit 70c5d8b)
2017-02-03 14:36:50 +03:00
Mikhail Glukhikh
483b59516c if-then --> safe access: run write action manually to avoid AWT events inside
(cherry picked from commit 07f0635)
2017-02-03 14:36:36 +03:00
Mikhail Glukhikh
607db11011 if-then --> elvis: run write action manually to avoid AWT events inside
(cherry picked from commit 834c3f5)
2017-02-03 14:36:21 +03:00
Mikhael Bogdanov
d04b7e9784 Temporary disable new intrinsics usage in ieee754 arithmetic
(cherry picked from commit aa3f64b)
2017-02-03 09:01:14 +01:00
Mikhael Bogdanov
0320fe8261 Use proper type for nullability check in 'calcTypeForIEEE754ArithmeticIfNeeded'
(cherry picked from commit 560226c)
2017-02-03 09:01:11 +01:00
Mikhael Bogdanov
cf99fc4908 Added intrinsics for nullable Double/Float equals check
(cherry picked from commit 5cffb38)
2017-02-03 09:01:05 +01:00
Mikhael Bogdanov
52c7bdf280 Update for "Fix for KT-15868: NPE when comparing nullable doubles"
(cherry picked from commit 87529f9)
2017-02-03 09:00:58 +01:00
Mikhael Bogdanov
7ab3afd00d Test data update 2017-02-02 09:37:05 +01:00
Mikhail Glukhikh
f49ef8e919 Stub creation from cls fixed for suspend function types 2017-02-02 00:47:05 +03:00
Mikhail Glukhikh
0e1b61b422 Change log: last-shot issues for 1.1-Beta2
(cherry picked from commit 5f6d65c)
2017-02-01 21:08:15 +03:00
Dmitry Jemerov
aaddfa8561 Advance binary stub version due to coroutine metadata format changes
(cherry picked from commit 66f7382)
2017-02-01 18:13:30 +01:00
Mikhael Bogdanov
05cfe4ca39 Fix for KT-15868: NPE when comparing nullable doubles
#KT-15868 Fixed

(cherry picked from commit a2c5c94)
2017-02-01 17:45:13 +01:00
Alexey Tsvetkov
65437a5c21 Increment data container cache version
Reason: coroutines metadata format has been changed (since 1.1-beta-1)
2017-02-01 18:51:11 +03:00
Alexey Tsvetkov
1026605627 Avoid checking incremental caches versions if corresponding property is set 2017-02-01 18:51:11 +03:00
Alexey Tsvetkov
a08bc11064 Refactoring: extract checking caches versions to function 2017-02-01 18:51:11 +03:00
Stanislav Erokhin
5c694bf95b Change IS_PRE_RELEASE to true 2017-02-01 18:27:42 +03:00
Stanislav Erokhin
44ea407de5 Advance JvmMetadataVersion to 1.1.5 after change serialization format for suspend function types. 2017-02-01 18:27:41 +03:00
Yan Zhulanow
a455b46073 Kapt: Fix error messages map name 2017-02-01 18:13:43 +03:00
Yan Zhulanow
3c22087a50 Kapt3: Allow annotations with Kotlin-only targets, such as PROPERTY (KT-15697) 2017-02-01 18:13:42 +03:00
Yan Zhulanow
52aead1143 Kapt: Fix javac error reporting in Kotlin daemon, also fix parsing error reporting (KT-15524) 2017-02-01 18:13:41 +03:00
Mikhail Glukhikh
7ee259de02 Change log: 1.1-RC --> 1.1-Beta2 2017-02-01 18:11:05 +03:00
Alexey Sedunov
1102517554 Kotlin Facet: Test longer afrifact name first when detecting module platform to prevent false positive on artifact name which is a prefix of another afrifact name
(cherry picked from commit 9adc183)
2017-02-01 16:57:10 +03:00
Stanislav Erokhin
3518cbeb12 Fix serialization for suspend function types.
Since now `suspend (Int) -> String` will be serialized as `(Int, Continuation<String>) -> Any?` + suspend flag.

Before this change such type serialized like this: Function2<Int, String> + suspend flag. And yes, type `Function2<Int, String>` isn't correct, because Function2 expect 3 type arguments.
We have special logic for this case and we deserialize such error-written types correctly.
2017-02-01 16:39:51 +03:00
Mikhail Glukhikh
ef519dc14f Minor change log fix 2017-02-01 14:39:50 +03:00
Alexey Sedunov
d6663a0c77 Kotlin Facet: Ignore invalid platform-specific compiler arguments
(cherry picked from commit 55e7391)
2017-02-01 12:41:11 +03:00
Mikhail Glukhikh
536181bf06 1.1-RC change log polishing
(cherry picked from commit dc57f97)
2017-01-31 19:13:30 +03:00
Alexey Tsvetkov
0e30e13dec Update ChangeLog.md 2017-01-31 19:10:06 +03:00
Alexey Tsvetkov
8a345be259 Fix kapt1 with stubs test to main internal references 2017-01-31 19:07:11 +03:00
Alexey Tsvetkov
1608fde341 Revert "Avoid having -d and -module set at the same time"
This reverts commit ac241e2676.
2017-01-31 19:07:11 +03:00
Ilya Gorbunov
f7d731d1b9 Edit 1.1-RC changelog regarding Standard Library and JS 2017-01-31 18:44:09 +03:00
Stanislav Erokhin
00018650f8 Use LanguageVersionSettings from project instead of LanguageVersionSettingsImpl.DEFAULT for sdk and library resolver.
General effect will be the following:
- all member scopes for libraries and JDK will be constructed with -language-version/-api-version specified in project settings
- for modules with another (not like in project settings) -api-version or -language-version we will have not correct member scope -- for example we will see typealiases from such libraries.

#KT-15979 Fixed
2017-01-31 18:13:32 +03:00
Mikhail Glukhikh
cc4ee6d888 1.1-RC: change log (final?) update
(cherry picked from commit 8d48452)
2017-01-31 17:31:41 +03:00
Alexey Tsvetkov
ac241e2676 Avoid having -d and -module set at the same time
#KT-14619 fixed
2017-01-31 16:52:32 +03:00
Alexey Tsvetkov
d59b9e7059 Fix annotation processors outputting to classes dir with kapt 3
#KT-15915 fixed

 Annotation processor can access a classes directory provided by AP environment.
Previously kapt 3 was using kotlin-classes directory as a a classes directory.
However compileKotlin task does not expect this.
Also having multiple tasks with the same output dir is a bad practise in Gradle.

This change introduces a separate directory for classes generated by kapt 3.
Its output is copied to a resulting classes dir (just as a kotlin-classes dir).
2017-01-31 16:52:27 +03:00
Alexey Tsvetkov
10079ceba3 Fix downgrading from 1.1 to 1.0.x in Gradle
If @Input property is added in new plugin version
and this property has a new type (a class/enum which is not presented in previous plugin)
then downgrading leads to an exception,
because Gradle tries to deserialize the property value from its caches,
but the type of value does not exist.

Workaround: add new String property.
2017-01-31 16:52:23 +03:00
Alexey Tsvetkov
4c3f221c38 Fix exception when Groovy lazy string (GString) is in freeCompilerArgs
#KT-15500 fixed

GString is an object that represents string literal like `"${project.name}"`
in Groovy. It is not an instance of string.
Groovy automatically converts GString to String when it is passed where String is expected.
However freeCompilerArgs is a List<String>, so type parameter info is lost at runtime.
When iterating freeCompilerArgs in Kotlin as a list of string, an exception
is thrown because GString cannot be casted to String (toString should be called instead).
2017-01-31 16:52:19 +03:00
Dmitry Jemerov
66db1449d1 Make sure that we don't have multiple coroutine status flags in the facet settings if one flag was set before parsing the command line options and another is specified through the command line options.
#KT-16075 Fixed

(cherry picked from commit 62e1d49)
2017-01-31 14:33:14 +01:00
Alexander Udalov
0bbb53a03d JS: rename "-library-files" argument to "-libraries" and change separator
Use the system separator (':' or ';') instead of commas

 #KT-16083 Fixed

(cherry picked from commit 464820458e)
2017-01-31 16:27:44 +03:00
Dmitry Jemerov
e069aad656 Don't show "Convert lambda to reference" for lambdas passed to suspend functions
#KT-16072 Fixed

(cherry picked from commit ffa3cf0)
2017-01-31 13:43:38 +01:00
Mikhail Glukhikh
5823d05d32 1.1.0: change log from previous releases changed to the reference link 2017-01-31 15:23:29 +03:00
Mikhail Glukhikh
a8c35f3cb7 Change log update for 1.1.0
(cherry picked from commit 7021b0b)
2017-01-31 15:22:08 +03:00
Simon Ogorodnik
3befac7138 KT-14252 Completion could suggest constructors available via typealiases
#KT-14252 fixed

(cherry picked from commit c2ba4e3)
2017-01-31 15:17:05 +03:00
Denis Zharkov
b4e2705a99 Prohibit inline lambda parameters of suspend function type
#KT-16068 Fixed
2017-01-31 14:57:56 +03:00
Stanislav Erokhin
b22044216a Do not show url for multi platform projects.
(cherry picked from commit 67835b6)
2017-01-31 13:12:27 +03:00
Mikhail Zarechenskiy
1531915c1b Introduce language feature for type inference on generics for callable references
#KT-16061 Fixed
2017-01-31 01:43:26 +03:00
Ilya Gorbunov
273ea38e01 Fix tests after introducing exlcusions to default imports of kotlin.js package.
(cherry picked from commit 38b79a5)
2017-01-31 00:12:35 +03:00
Ilya Gorbunov
0b5baabfb2 Do not use Math in common code.
(cherry picked from commit 33f3106)
2017-01-31 00:12:34 +03:00
Ilya Gorbunov
d4a82ffafe Add explicit imports of kotlin.js.* to stdlib where required.
(cherry picked from commit 66abea1)
2017-01-31 00:12:32 +03:00
Ilya Gorbunov
6d489f2d17 Add explicit imports of kotlin.js.* to generated files.
(cherry picked from commit 25c3064)
2017-01-31 00:12:30 +03:00
Ilya Gorbunov
4eca1585e7 Add exclusions to JS platform default imports
(cherry picked from commit cd5f68f)
2017-01-31 00:12:28 +03:00
Ilya Gorbunov
0ada85d692 Remove test for named native
(cherry picked from commit f4ef98c)
2017-01-31 00:12:27 +03:00
Ilya Gorbunov
7726e01bcc Change LoadBuiltinsTest testData, add runtime and import to box tests.
#KT-16030

(cherry picked from commit c4a0bb7)
2017-01-31 00:12:25 +03:00
Ilya Gorbunov
44867affbe Retract bitwise operators from builtins for Byte and Short and add them as extensions in kotlin.experimental package in stdlib.
#KT-16030

(cherry picked from commit 4ac7be9)
2017-01-31 00:12:23 +03:00
Dmitry Jemerov
42dd6453fe Minor fixes for stdlb kdoc
(cherry picked from commit 8968d56)
2017-01-31 00:12:22 +03:00
Nikolay Krasko
cf9af05420 Stop in the method with suitable name if no descriptor found
Absence of descriptor is possible when sources are outdated or absent.
Early stop is better than iterating in step into till the program end.

(cherry picked from commit 563196a)
2017-01-30 21:47:56 +03:00
Nikolay Krasko
db77866cb7 Fix smart step into functions call with suspend lambdas (KT-14700)
#KT-14700 Fixed

(cherry picked from commit 4a4a825)
2017-01-30 21:47:47 +03:00
Nikolay Krasko
3e40bc15b3 Exclude errors descriptors from the set of conflicting declarations
Resolve hanging in evaluate expression

(cherry picked from commit 2add36e)
2017-01-30 21:47:24 +03:00
Alexander Udalov
1bf7e9cbad Increase SOURCE_STUB_VERSION
Because of a974ed1 and b9f9894

(cherry picked from commit ad0178ee64)
2017-01-30 20:33:21 +03:00
Alexander Udalov
f516a08415 Report error on callable reference or class literal with "-no-stdlib"
Also workaround the NoSuchElementException that was happening because error
type never has any type arguments

 #KT-14547 Fixed

(cherry picked from commit 8811165de8)
2017-01-30 20:33:21 +03:00
Alexander Udalov
c6ad7ffeca Minor, fix typo in assertion message
(cherry picked from commit 7371dc9b54)
2017-01-30 20:33:21 +03:00
Alexander Udalov
2fe8f449b3 Add hint to use "-language-version", when applicable, in JVM runtime checker
(cherry picked from commit 424afba246)
2017-01-30 20:33:21 +03:00
Alexander Udalov
d5f692c206 Refactor JvmRuntimeVersionsConsistencyChecker for readability
(cherry picked from commit 7167139c2e)
2017-01-30 20:33:21 +03:00
Alexander Udalov
24c0e4fea8 Do not report error on libraries that bundle Kotlin runtime in classpath
Instead, report a strong warning, suggesting to remove such libraries from the
classpath

 #KT-15995 Fixed

(cherry picked from commit 9e877b4a9e)
2017-01-30 20:33:21 +03:00
Alexander Udalov
9b75934b47 Slightly refactor inline functions at serializationUtils.kt
Extract large bodies to separate functions, use KType.classifier instead of
KClass.createType

(cherry picked from commit 2d975d74cb)
2017-01-30 20:33:21 +03:00
Alexander Udalov
70703c6184 Fix JvmBuildMetaInfoTest.testSerialization
Do not check against hard-coded values of parameters, because they might be
changed a lot in the future

(cherry picked from commit f6c3aa0807)
2017-01-30 20:33:21 +03:00
Mikhail Glukhikh
d0cb701907 Change log update for 1.1.0
(cherry picked from commit 8bf233e)
2017-01-30 20:22:33 +03:00
Yan Zhulanow
4b41ccdb72 Generate enum values with bodies properly (KT-15803) 2017-01-30 20:14:56 +03:00
Yan Zhulanow
d7640a7047 Kapt: Allow empty .kt files list in kapt in order to support kapt with Java-only source files. (KT-15675) 2017-01-30 20:14:50 +03:00
Alexey Andreev
5adc19e4da JS: don't fail when generating signature for function which refers to undefined type
(cherry picked from commit d0b7dc8)
2017-01-30 19:57:05 +03:00
Alexey Sedunov
9f9287368c Spring Support: Consider declaration open if it's supplemented with a preconfigured annotation in corresponding compiler plugin
#KT-15444 Fixed
2017-01-30 17:46:11 +03:00
Alexey Andreev
f1970ac7c8 JS: don't report error when FAKE function overrides external function with optional parameters. Report only when it overrides at least two such functions. See KT-15961
(cherry picked from commit 06e8f7b328)
2017-01-30 17:28:48 +03:00
Anton Bannykh
141803b156 JS: char boxing
(cherry picked from commit 77aa685496)
2017-01-30 17:03:44 +03:00
Denis Zharkov
fbca946420 Exclude coroutine inrinsics and internal packages
#KT-16018
2017-01-30 16:49:14 +03:00
Denis Zharkov
a7054bce15 Fix coroutine-related VerifyError
The problem was that we spilled the `origin` variable (see test) as Object, because
we determined the type of merge(null, String) incorrectly.

 #KT-15973 Fixed
2017-01-30 16:49:14 +03:00
Dmitry Petrov
0d8a4b61a6 Fix testData in smart completion test
(abbreviation is preserved for 'arrayListOf').
2017-01-30 16:49:14 +03:00
Simon Ogorodnik
fd349ae104 Revert "KT-14252 Completion could suggest constructors available via typealiases"
Reverted due problems with test
This reverts commit 0ad979823e.
2017-01-30 16:47:38 +03:00
Simon Ogorodnik
0ad979823e KT-14252 Completion could suggest constructors available via typealiases
#KT-14252 fixed

(cherry picked from commit 55eeb74)
2017-01-30 16:25:42 +03:00
Dmitry Jemerov
fcb2e5ed19 Register ControlFlowFactory in KotlinCoreProjectEnvironment
#KT-16047 Fixed

(cherry picked from commit 3a3cf04)
2017-01-30 14:14:17 +01:00
Alexander Udalov
57a9ec8b29 Rename JsBinaryVersion -> JsMetadataVersion
For consistency with JvmMetadataVersion

(cherry picked from commit 167155388d)
2017-01-30 16:13:21 +03:00
Alexander Udalov
3373e49fd0 Promote severity of configuration warnings to STRONG_WARNING
The reason is that these configuration problems may be the reason of
compilation errors, but they were hidden from the output because warnings are
not reported when there's at least one error

(cherry picked from commit e9a737b85a)
2017-01-30 16:13:18 +03:00
Alexander Udalov
a008a4e8c3 Introduce CompilerMessageSeverity.STRONG_WARNING
This is a severity for mandatory warnings, i.e. those which should be reported
in any case, even if there are compilation errors

(cherry picked from commit 7ac96163ac)
2017-01-30 16:13:15 +03:00
Alexander Udalov
17d0daff86 Advance JvmMetadataVersion to 1.1.4, change IS_PRE_RELEASE to false
Kotlin 1.1 is no longer considered a pre-release

(cherry picked from commit 268d10d3f0)
2017-01-30 16:13:12 +03:00
Alexander Udalov
2be9922b71 Minor, remove unnecessary logging for valid erroneous case
It seems that it's normal for VirtualFile in this place to be invalid in this
way

(cherry picked from commit 1025fe9307)
2017-01-30 16:13:08 +03:00
Alexander Udalov
e25ce9548e JS: do not require "id" in the File protobuf message
(cherry picked from commit 933bcb3511)
2017-01-30 16:13:05 +03:00
Zalim Bashorov
45a7fa9f08 KJS: mark as inline only some functions form js stdlib
(cherry picked from commit 0dd3f11)
2017-01-30 15:44:27 +03:00
Zalim Bashorov
b1bf048295 KJS: change visibility of subSequence helper function to internal to avoid to use it directly from kotlin
(cherry picked from commit a49ad3c)
2017-01-30 15:44:18 +03:00
Zalim Bashorov
4f906ac65f KJS: rename baseClass field in metadata to interfaces since we plan to store there only implemented interfaces (see KT-15037)
(cherry picked from commit d5dca38)
2017-01-30 15:44:10 +03:00
Zalim Bashorov
eb03c50ca8 KJS: turn Json class into external interface
#KT-12712 Fixed

(cherry picked from commit 1b8b6be)
2017-01-30 15:43:52 +03:00
Dmitry Jemerov
44b156e1a7 Disable "Create type alias from usage" fix when language level doesn't support type aliases
#KT-16036 Fixed

(cherry picked from commit f0e8907)
2017-01-30 12:40:30 +01:00
Dmitry Jemerov
b3754e7194 Disable "Introduce type alias" refactoring when type aliases aren't supported by the current language level
(cherry picked from commit 17c73ce)
2017-01-30 12:40:21 +01:00
Dmitry Jemerov
fde2b7607d Exclude keywords from completion if the corresponding feature is unsupported by the language level selected for the module
(cherry picked from commit 720da17)
2017-01-30 12:36:27 +01:00
Alexander Udalov
51c510fb0c Make KTypeProjection's constructor public
To make it easier to create a KTypeProjection instance given a KVariance
instance (otherwise you currently need to do a "when" on it). Also it's exposed
via automatically generated "copy" anyway
2017-01-30 11:37:38 +03:00
Alexander Udalov
770cbad36f JS: drop "-kjsm" flag, merge logic with "-meta-info"
#KT-16049 Fixed
2017-01-30 11:37:37 +03:00
Alexander Udalov
350b89e14e JS: minor, drop obsolete VFS_PROTOCOL 2017-01-30 11:37:36 +03:00
Alexander Udalov
5002f7159a JS: write full version (major.minor.patch) to .meta.js 2017-01-30 11:37:35 +03:00
Alexander Udalov
34ca29cee7 Do not crash JS decompiler on non-existing .jar entries
See the comment for clarification
2017-01-30 11:37:34 +03:00
Alexander Udalov
2db2c449f5 Update tests on decompiled text for JS
Because .kjsm files now contain all declarations from the package (contrary to
the JVM decompiler which produces one file for one class/package facade), some
common decompiled text tests started to behave differently on JVM and JS.
Update two of them (Modifiers, ClassWithClassObject) to make results the same,
copy another (TypeAliases) to JVM-/JS-specific tests with different outputs
2017-01-30 11:37:33 +03:00
Alexander Udalov
1fe5fbff5b Drop tests on JS decompiled text / stub consistency
They're no longer needed because the logic of the decompiler / stub builder is
now trivial (see KotlinJavaScriptDeserializerForDecompiler,
KotlinJavaScriptStubBuilder) and after it's merged to the decompiler for
built-ins, it's going to be tested anyway with BuiltInDecompilerConsistencyTest
2017-01-30 11:37:32 +03:00
Alexander Udalov
3ede93d496 JS: simplify KotlinJavascriptSerializationUtil
Inline recently introduced SerializerCallbacks
2017-01-30 11:37:32 +03:00
Alexander Udalov
00ffa08659 JS: serialize .kjsm package-wise, adapt decompiler & stub builder
Instead of multiple .kjsm files for different classes and .kotlin_string_table,
.kotlin_file_table, .kotlin_classes files for each package, serialize the
contents of each package to a single foo/bar/baz/baz.kjsm file. The short name
of the file is the last segment in the FQ name of the package, or
"root-package" if the package is root.

There are two main reasons for this change:
1) Such structure takes less space, is more IO-friendly and will not cause
   multiple exceptions as the old one, where we sometimes tried to read
   non-existing files
2) This is exactly the same format that is used to serialize built-in
   declarations (.kotlin_builtins) at the moment, which will allow us to reuse
   some code

Also write a separate Header protobuf message to the beginning of the .kjsm
file. This will be used as arguments of the kotlin.Metadata annotation are used
in the JVM-specific parts of the compiler: to be able to provide some general
information about the binary file without parsing the whole protobuf data.

This commit breaks decompiled text & stub builder consistency tests. This is OK
because they're removed in a future commit.

Fixes EA-79605, EA-81947, EA-84277 and maybe EA-86787

 #KT-10894 Fixed
 #KT-14124 Fixed
 #KT-15755 Fixed
2017-01-30 11:37:31 +03:00
Alexander Udalov
4cc3212c9a JS: do not generate .meta.js and .kjsm for built-ins 2017-01-30 11:37:30 +03:00
Alexander Udalov
b1b0770a86 JS: improve binary representation format of metadata in .meta.js
Instead of writing many different files and serializing this "virtual file
system" to a byte array in a protobuf message, just write the needed stuff
directly, as fields in the Library message. Make it consist of many Part
messages, where the Part message is equivalent to the BuiltIns message in
builtins.proto. The next step would be to combine Library.Part and BuiltIns,
which will allow us to simplify some serialization-related code soon.

In this commit, no changes happened to the .kjsm format. But since the code
that serialized the abovementioned files was shared, a temporary abstraction
over two serialization formats was made, see SerializerCallbacks.

This commit temporarily breaks .kjsm decompiler and stub builder
2017-01-30 11:37:29 +03:00
833 changed files with 23483 additions and 11803 deletions

View File

@@ -3,13 +3,11 @@
<CLASSES>
<root url="jar://$PROJECT_DIR$/dependencies/uast-common.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/uast-java.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/uast-tests.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/uast-common-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/uast-java-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/uast-tests-sources.jar!/" />
</SOURCES>
</library>
</component>

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,10 @@ import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
import org.jetbrains.kotlin.build.deserializeFromPlainText
import org.jetbrains.kotlin.build.serializeToPlainText
/**
* If you want to add a new field, check its type is supported by [serializeToPlainText], [deserializeFromPlainText]
@@ -59,7 +62,7 @@ data class JvmBuildMetaInfo(
}
fun JvmBuildMetaInfo(args: CommonCompilerArguments): JvmBuildMetaInfo =
JvmBuildMetaInfo(isEAP = KotlinCompilerVersion.isPreRelease(),
JvmBuildMetaInfo(isEAP = DeserializedDescriptorResolver.IS_PRE_RELEASE,
compilerBuildVersion = KotlinCompilerVersion.VERSION,
languageVersionString = args.languageVersion ?: LanguageVersion.LATEST.versionString,
apiVersionString = args.apiVersion ?: ApiVersion.LATEST.versionString,
@@ -72,4 +75,4 @@ fun JvmBuildMetaInfo(args: CommonCompilerArguments): JvmBuildMetaInfo =
metadataVersionPatch = JvmMetadataVersion.INSTANCE.patch,
bytecodeVersionMajor = JvmBytecodeBinaryVersion.INSTANCE.major,
bytecodeVersionMinor = JvmBytecodeBinaryVersion.INSTANCE.minor,
bytecodeVersionPatch = JvmBytecodeBinaryVersion.INSTANCE.patch)
bytecodeVersionPatch = JvmBytecodeBinaryVersion.INSTANCE.patch)

View File

@@ -406,9 +406,12 @@
byline="true" encoding="UTF-8" />
</target>
<target name="js-stdlib">
<property environment="env"/>
<target name="js-stdlib-preprocess">
<kotlin-pp src="libraries/stdlib/src" output="${intermediate-sources}/stdlib/js" profile="JS" />
</target>
<target name="js-stdlib" depends="js-stdlib-preprocess">
<property environment="env"/>
<cleandir dir="${js.stdlib.output.dir}"/>
<!-- We don't want descriptors for built-ins to be serialized, so we compile these files separately. -->
@@ -474,7 +477,7 @@
<copy file="${kotlin-home}/lib/kotlin-stdlib-js.jar" tofile="${kotlin-home}/lib/kotlin-jslib.jar" />
</target>
<target name="pack-js-stdlib-sources">
<target name="pack-js-stdlib-sources" depends="js-stdlib-preprocess">
<jar destfile="${kotlin-home}/lib/kotlin-stdlib-js-sources.jar" duplicate="fail">
<resources refid="js.lib.files" />
<fileset refid="kotlin.builtin.files" />
@@ -617,6 +620,13 @@
</target>
<target name="compiler">
<taskdef resource="proguard/ant/task.properties">
<classpath>
<pathelement path="${dependencies}/proguard.jar"/>
<pathelement path="${dependencies}/proguard-anttask.jar"/>
</classpath>
</taskdef>
<cleandir dir="${output}/classes/compiler"/>
<javac2 destdir="${output}/classes/compiler" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false"
@@ -638,32 +648,17 @@
unless:true="${shrink}" />
<sequential if:true="${shrink}">
<shrink configuration="${basedir}/compiler/compiler.pro"/>
</sequential>
<pack-compiler-for-maven/>
</target>
<macrodef name="shrink">
<attribute name="configuration"/>
<sequential>
<taskdef resource="proguard/ant/task.properties">
<classpath>
<pathelement path="${dependencies}/proguard.jar"/>
<pathelement path="${dependencies}/proguard-anttask.jar"/>
</classpath>
</taskdef>
<available property="rtjar" value="${java.home}/lib/rt.jar" file="${java.home}/lib/rt.jar"/>
<available property="rtjar" value="${java.home}/../Classes/classes.jar" file="${java.home}/../Classes/classes.jar"/>
<available property="jssejar" value="${java.home}/lib/jsse.jar" file="${java.home}/lib/jsse.jar"/>
<available property="jssejar" value="${java.home}/../Classes/jsse.jar" file="${java.home}/../Classes/jsse.jar"/>
<proguard configuration="@{configuration}"/>
<proguard configuration="${basedir}/compiler/compiler.pro"/>
</sequential>
</macrodef>
<pack-compiler-for-maven/>
</target>
<macrodef name="pack-compiler-for-maven">
<sequential>
@@ -1032,13 +1027,13 @@
<sequential>
<java classname="org.jetbrains.kotlin.preloading.Preloader" failonerror="true" fork="true" maxmemory="${max.heap.size.for.forked.jvm}">
<classpath>
<pathelement location="${kotlin-home}/lib/kotlin-preloader.jar"/>
<pathelement location="${bootstrap.compiler.home}/lib/kotlin-preloader.jar"/>
</classpath>
<assertions>
<enable/>
</assertions>
<arg value="-cp"/>
<arg value="${kotlin-home}/lib/kotlin-compiler.jar"/>
<arg value="${bootstrap.compiler.home}/lib/kotlin-compiler.jar"/>
<arg value="org.jetbrains.kotlin.preprocessor.PreprocessorCLI"/>
<arg value="@{src}"/>
<arg value="@{output}"/>
@@ -1232,10 +1227,11 @@
</manifest>
</jar>
<delete file="${output}/kotlin-reflect-jarjar.jar" failonerror="false"/>
<sequential if:true="${obfuscate.reflect}">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="dependencies/jarjar.jar"/>
<delete file="${output}/kotlin-reflect-after-jarjar.jar" failonerror="false"/>
<jarjar jarfile="${output}/kotlin-reflect-after-jarjar.jar" filesonly="true" filesetmanifest="merge">
<jarjar jarfile="${output}/kotlin-reflect-jarjar.jar" filesonly="true" filesetmanifest="merge">
<zipfileset src="${output}/kotlin-reflect-before-jarjar.jar"/>
<rule pattern="org.jetbrains.kotlin.**" result="kotlin.reflect.jvm.internal.impl.@1"/>
<rule pattern="javax.inject.**" result="kotlin.reflect.jvm.internal.impl.javax.inject.@1"/>
@@ -1246,18 +1242,17 @@
<compilerarg value="-script"/>
<compilerarg value="kotlin/Metadata"/> <!-- Annotation to strip -->
<compilerarg value="kotlin/reflect/jvm/internal/impl/.*"/> <!-- Classes to strip from -->
<compilerarg value="${output}/kotlin-reflect-after-jarjar.jar"/>
<compilerarg value="${output}/kotlin-reflect-before-proguard.jar"/>
<compilerarg value="${output}/kotlin-reflect-jarjar.jar"/>
<compilerarg value="${kotlin-home}/lib/kotlin-reflect.jar"/>
<classpath>
<pathelement location="${idea.sdk}/lib/asm-all.jar"/>
</classpath>
</kotlinc>
<shrink configuration="${basedir}/core/reflection.jvm/reflection.pro"/>
</sequential>
<sequential unless:true="${obfuscate.reflect}">
<echo message="Obfuscation of kotlin-reflect is disabled"/>
<copy file="${output}/kotlin-reflect-before-jarjar.jar" tofile="${output}/kotlin-reflect-jarjar.jar" overwrite="true"/>
<copy file="${output}/kotlin-reflect-before-jarjar.jar" tofile="${kotlin-home}/lib/kotlin-reflect.jar" overwrite="true"/>
</sequential>
</target>

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
@@ -32,12 +31,7 @@ abstract class ArgumentGenerator {
*
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
*/
open fun generate(
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
// may be null for a constructor of an object literal
calleeDescriptor: CallableDescriptor?
): DefaultCallArgs {
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallArgs {
assert(valueArgumentsByIndex.size == actualArgs.size) {
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
}
@@ -54,8 +48,7 @@ abstract class ArgumentGenerator {
}
}
// Use unwrapped version, because additional synthetic parameters can't have default values
val defaultArgs = DefaultCallArgs(calleeDescriptor?.unwrapFrontendVersion()?.valueParameters?.size ?: 0)
val defaultArgs = DefaultCallArgs(valueArgumentsByIndex.size)
for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
val argument = argumentWithDeclIndex.arg

View File

@@ -770,7 +770,6 @@ public class AsmUtil {
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
if (left == Type.CHAR_TYPE || right == Type.CHAR_TYPE) return Type.CHAR_TYPE;
return Type.INT_TYPE;
}

View File

@@ -210,12 +210,7 @@ class NumberCompare(
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int {
// Opcode takes one int operand from the stack
assert(opcode in IFEQ..IFLE) {
"Opcode for comparing must be in range ${IFEQ..IFLE}, but $opcode was found"
}
return when (operandType) {
when (operandType) {
Type.FLOAT_TYPE, Type.DOUBLE_TYPE -> {
if (opToken == KtTokens.GT || opToken == KtTokens.GTEQ) {
v.cmpl(operandType)
@@ -223,19 +218,17 @@ class NumberCompare(
else {
v.cmpg(operandType)
}
opcode
}
Type.LONG_TYPE -> {
v.lcmp()
opcode
}
else -> {
opcode + (IF_ICMPEQ - IFEQ)
return opcode + (IF_ICMPEQ - IFEQ)
}
}
return opcode
}
companion object {
fun getNumberCompareOpcode(opToken: IElementType): Int {
return when (opToken) {
@@ -269,4 +262,4 @@ class ObjectCompare(
}
}
}
}
}

View File

@@ -17,13 +17,10 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.ValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.List;
@@ -56,12 +53,11 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
@Override
public DefaultCallArgs generate(
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
@NotNull List<? extends ResolvedValueArgument> valueArgs,
@Nullable CallableDescriptor calleeDescriptor
@NotNull List<? extends ResolvedValueArgument> valueArgs
) {
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
this.codegen.setShouldMarkLineNumbers(false);
DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs, calleeDescriptor);
DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs);
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
return defaultArgs;
}
@@ -88,9 +84,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
protected void generateVararg(int i, @NotNull VarargValueArgument argument) {
ValueParameterDescriptor parameter = valueParameters.get(i);
Type type = valueParameterTypes.get(i);
// Upper bound for type of vararg parameter should always have a form of 'Array<out T>',
// while its lower bound may be Nothing-typed after approximation
codegen.genVarargs(argument, FlexibleTypesKt.upperIfFlexible(parameter.getType()));
codegen.genVarargs(argument, parameter.getType());
callGenerator.afterParameterPut(type, null, i);
}

View File

@@ -26,7 +26,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.context.ClosureContext;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
@@ -35,11 +34,13 @@ import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
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.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
@@ -62,6 +63,7 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
@@ -396,9 +398,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
}
else if (container instanceof PackageFragmentDescriptor) {
iv.aconst(state.getTypeMapper().mapOwner(descriptor));
// Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead,
// but there's no nice API to obtain that name here yet
// TODO: write the referenced declaration's module name and use it in reflection
iv.aconst(state.getModuleName());
iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
@@ -470,6 +469,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
@NotNull CalculatedClosure closure,
@NotNull Type ownerType
) {
BindingContext bindingContext = typeMapper.getBindingContext();
List<FieldInfo> args = Lists.newArrayList();
ClassDescriptor captureThis = closure.getCaptureThis();
if (captureThis != null) {
@@ -481,15 +481,23 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), CAPTURED_RECEIVER_FIELD));
}
for (EnclosedValueDescriptor enclosedValueDescriptor : closure.getCaptureVariables().values()) {
DeclarationDescriptor descriptor = enclosedValueDescriptor.getDescriptor();
if ((descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) ||
ExpressionTypingUtils.isLocalFunction(descriptor)) {
args.add(
FieldInfo.createForHiddenField(
ownerType, enclosedValueDescriptor.getType(), enclosedValueDescriptor.getFieldName()
)
);
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
Type type = typeMapper.getSharedVarType(descriptor);
if (type == null && descriptor instanceof LocalVariableDescriptor) {
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType((LocalVariableDescriptor) descriptor, bindingContext);
if (delegateType != null) {
type = typeMapper.mapType(delegateType);
}
}
if (type == null) {
type = typeMapper.mapType((VariableDescriptor) descriptor);
}
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().asString()));
}
else if (ExpressionTypingUtils.isLocalFunction(descriptor)) {
Type classType = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
args.add(FieldInfo.createForHiddenField(ownerType, classType, "$" + descriptor.getName().asString()));
}
else if (descriptor instanceof FunctionDescriptor) {
assert captureReceiverType != null;

View File

@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -128,13 +129,11 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
) {
val typeMapper = state.typeMapper
val isStatic = AsmUtil.isStaticMethod(contextKind, functionDescriptor)
val baseMethodFlags = AsmUtil.getCommonCallableFlags(functionDescriptor) and Opcodes.ACC_VARARGS.inv()
val remainingParameters = getRemainingParameters(functionDescriptor.original, substituteCount)
val flags =
baseMethodFlags or
val flags = AsmUtil.getCommonCallableFlags(functionDescriptor) or
(if (isStatic) Opcodes.ACC_STATIC else 0) or
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0) or
(if (remainingParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0)
(if (functionDescriptor.modality == Modality.FINAL && functionDescriptor !is ConstructorDescriptor) Opcodes.ACC_FINAL else 0)
val remainingParameters = getRemainingParameters(functionDescriptor.original, substituteCount)
val signature = typeMapper.mapSignature(functionDescriptor, contextKind, remainingParameters, false)
val mv = classBuilder.newMethod(OtherOrigin(methodElement, functionDescriptor), flags,
signature.asmMethod.name,

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2017 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.
@@ -1518,10 +1518,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
KotlinType expectedType = bindingContext.getType(expression);
if (expectedType == null) {
return null;
}
return compileTimeValue.toConstantValue(expectedType);
}
@@ -1709,7 +1705,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ArgumentGenerator argumentGenerator =
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
argumentGenerator.generate(valueArguments, valueArguments, null);
argumentGenerator.generate(valueArguments, valueArguments);
}
Collection<ClassConstructorDescriptor> constructors = classDescriptor.getConstructors();
@@ -2502,14 +2498,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
public int lookupLocalIndex(DeclarationDescriptor descriptor) {
int index = myFrameMap.getIndex(descriptor);
if (index != -1) return index;
return myFrameMap.getIndex(getParameterSynonymOrThis(descriptor));
}
private DeclarationDescriptor getParameterSynonymOrThis(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ValueParameterDescriptor)) return descriptor;
if (!(descriptor instanceof ValueParameterDescriptor)) return -1;
DeclarationDescriptor synonym = bindingContext.get(CodegenBinding.PARAMETER_SYNONYM, (ValueParameterDescriptor) descriptor);
if (synonym == null) return -1;
return myFrameMap.getIndex(synonym);
return synonym != null ? synonym : descriptor;
}
@NotNull
@@ -2867,11 +2863,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
DefaultCallArgs defaultArgs =
argumentGenerator.generate(
valueArguments,
new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()),
resolvedCall.getResultingDescriptor()
);
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()));
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
tailRecursionCodegen.generateTailRecursion(resolvedCall);
@@ -3029,8 +3021,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull
CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableDescriptor descriptor) {
Map<TypeParameterDescriptor, KotlinType> typeArguments = getTypeArgumentsForResolvedCall(resolvedCall, descriptor);
Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments();
TypeParameterMappings mappings = new TypeParameterMappings();
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
TypeParameterDescriptor key = entry.getKey();
@@ -3055,38 +3046,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
);
}
}
return getOrCreateCallGenerator(descriptor, resolvedCall.getCall().getCallElement(), mappings, false);
}
@NotNull
private static Map<TypeParameterDescriptor, KotlinType> getTypeArgumentsForResolvedCall(
@NotNull ResolvedCall<?> resolvedCall,
@NotNull CallableDescriptor descriptor
) {
if (!(descriptor instanceof TypeAliasConstructorDescriptor)) {
return resolvedCall.getTypeArguments();
}
TypeAliasConstructorDescriptor typeAliasConstructorDescriptor = (TypeAliasConstructorDescriptor) descriptor;
ClassConstructorDescriptor underlyingConstructorDescriptor = typeAliasConstructorDescriptor.getUnderlyingConstructorDescriptor();
KotlinType resultingType = typeAliasConstructorDescriptor.getReturnType();
List<TypeProjection> typeArgumentsForReturnType = resultingType.getArguments();
List<TypeParameterDescriptor> typeParameters = underlyingConstructorDescriptor.getTypeParameters();
assert typeParameters.size() == typeArgumentsForReturnType.size() :
"Type parameters of the underlying constructor " + underlyingConstructorDescriptor +
"should correspond to type arguments for the resulting type " + resultingType;
Map<TypeParameterDescriptor, KotlinType> typeArgumentsMap = Maps.newHashMapWithExpectedSize(typeParameters.size());
for (TypeParameterDescriptor typeParameter: typeParameters) {
KotlinType typeArgument = typeArgumentsForReturnType.get(typeParameter.getIndex()).getType();
typeArgumentsMap.put(typeParameter, typeArgument);
}
return typeArgumentsMap;
}
@Nullable
private static Pair<TypeParameterDescriptor, ReificationArgument> extractReificationArgument(@NotNull KotlinType type) {
@@ -3196,7 +3158,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
if (isSingleton) {
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getFunctionDescriptor())) {
!CodegenUtilKt.isJvmStaticInObjectOrClass(context.getContextDescriptor())) {
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
}
else if (isEnumEntry(calleeContainingClass)) {

View File

@@ -231,7 +231,7 @@ public class FunctionCodegen {
boolean staticInCompanionObject = CodegenUtilKt.isJvmStaticInCompanionObject(functionDescriptor);
if (staticInCompanionObject) {
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
parentBodyCodegen.addAdditionalTask(new JvmStaticInCompanionObjectGenerator(functionDescriptor, origin, state, parentBodyCodegen));
parentBodyCodegen.addAdditionalTask(new JvmStaticGenerator(functionDescriptor, origin, state, parentBodyCodegen));
}
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
@@ -256,8 +256,7 @@ public class FunctionCodegen {
else if (staticInCompanionObject) {
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
mv.visitCode();
FunctionDescriptor staticFunctionDescriptor = JvmStaticInCompanionObjectGenerator
.createStaticFunctionDescriptor(functionDescriptor);
FunctionDescriptor staticFunctionDescriptor = JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
Method accessorMethod =
typeMapper.mapAsmMethod(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());

View File

@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class JvmStaticInCompanionObjectGenerator(
class JvmStaticGenerator(
val descriptor: FunctionDescriptor,
val declarationOrigin: JvmDeclarationOrigin,
val state: GenerationState,

View File

@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.fileClasses.FileClasses;
@@ -238,20 +237,14 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
Annotations annotations = typeAliasDescriptor.getAnnotations();
if (!isAnnotationsMethodOwner || annotations.getAllAnnotations().isEmpty()) return;
int flags = ACC_DEPRECATED | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
String name = JvmAbi.getSyntheticMethodNameForAnnotatedTypeAlias(typeAliasDescriptor.getName());
generateSyntheticAnnotationsMethod(typeAliasDescriptor, new Method(name, "()V"), annotations, null);
}
String desc = "()V";
Method syntheticMethod = new Method(name, desc);
protected void generateSyntheticAnnotationsMethod(
@NotNull MemberDescriptor descriptor,
@NotNull Method syntheticMethod,
@NotNull Annotations annotations,
@Nullable AnnotationUseSiteTarget allowedTarget
) {
int flags = ACC_DEPRECATED | ACC_STATIC | ACC_SYNTHETIC | AsmUtil.getVisibilityAccessFlag(descriptor);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), flags, syntheticMethod.getName(),
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(typeAliasDescriptor), flags, syntheticMethod.getName(),
syntheticMethod.getDescriptor(), null, null);
AnnotationCodegen.forMethod(mv, this, typeMapper).genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, allowedTarget);
AnnotationCodegen.forMethod(mv, this, typeMapper).genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, null);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();

View File

@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithFakeAnnotations;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -60,6 +61,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPropertyWithBackingFieldCopyInOuterClass;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.FIELD_FOR_PROPERTY;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
@@ -271,7 +273,7 @@ public class PropertyCodegen {
}
// Annotations on properties are stored in bytecode on an empty synthetic method. This way they're still
// accessible via reflection, and 'deprecated' and 'synthetic' flags prevent this method from being called accidentally
// accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, @NotNull Annotations annotations) {
if (annotations.getAllAnnotations().isEmpty()) return;
@@ -279,9 +281,15 @@ public class PropertyCodegen {
if (!isInterface(contextDescriptor) ||
(FunctionCodegen.processInterface(contextDescriptor, kind, state) ||
(kind == OwnerKind.DEFAULT_IMPLS && state.getGenerateDefaultImplsForJvm8()))) {
memberCodegen.generateSyntheticAnnotationsMethod(
descriptor, getSyntheticMethodSignature(descriptor), annotations, AnnotationUseSiteTarget.PROPERTY
);
int flags = ACC_DEPRECATED | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
Method syntheticMethod = getSyntheticMethodSignature(descriptor);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), flags, syntheticMethod.getName(),
syntheticMethod.getDescriptor(), null, null);
AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper)
.genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
}
}

View File

@@ -281,33 +281,24 @@ public abstract class StackValue {
}
private static void box(Type type, Type toType, InstructionAdapter v) {
if (type == Type.BYTE_TYPE || toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME) && type == Type.INT_TYPE) {
v.cast(type, Type.BYTE_TYPE);
v.invokestatic(NULLABLE_BYTE_TYPE_NAME, "valueOf", "(B)L" + NULLABLE_BYTE_TYPE_NAME + ";", false);
}
else if (type == Type.SHORT_TYPE || toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME) && type == Type.INT_TYPE) {
v.cast(type, Type.SHORT_TYPE);
v.invokestatic(NULLABLE_SHORT_TYPE_NAME, "valueOf", "(S)L" + NULLABLE_SHORT_TYPE_NAME + ";", false);
}
else if (type == Type.LONG_TYPE || toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME) && type == Type.INT_TYPE) {
v.cast(type, Type.LONG_TYPE);
v.invokestatic(NULLABLE_LONG_TYPE_NAME, "valueOf", "(J)L" + NULLABLE_LONG_TYPE_NAME + ";", false);
}
else if (type == Type.INT_TYPE) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
}
else if (type == Type.BOOLEAN_TYPE) {
v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
}
else if (type == Type.CHAR_TYPE) {
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
}
else if (type == Type.FLOAT_TYPE) {
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
}
else if (type == Type.DOUBLE_TYPE) {
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
if (type == Type.INT_TYPE) {
if (toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME)) {
type = Type.BYTE_TYPE;
}
else if (toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME)) {
type = Type.SHORT_TYPE;
}
else if (toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME)) {
type = Type.LONG_TYPE;
}
v.cast(Type.INT_TYPE, type);
}
Type boxedType = AsmUtil.boxType(type);
if (boxedType == type) return;
v.invokestatic(boxedType.getInternalName(), "valueOf", Type.getMethodDescriptor(boxedType, type), false);
coerce(boxedType, toType, v);
}
private static void unbox(Type type, InstructionAdapter v) {
@@ -883,7 +874,7 @@ public abstract class StackValue {
newReceiver.put(newReceiver.type, v);
callGenerator.processAndPutHiddenParameters(false);
defaultArgs = generator.generate(valueArguments, valueArguments, call.getResultingDescriptor());
defaultArgs = generator.generate(valueArguments, valueArguments);
}
private ArgumentGenerator createArgumentGenerator() {

View File

@@ -20,7 +20,6 @@ import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cfg.TailRecursionKind;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
@@ -66,7 +65,7 @@ public class TailRecursionCodegen {
}
public void generateTailRecursion(ResolvedCall<?> resolvedCall) {
CallableDescriptor fd = CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(resolvedCall.getResultingDescriptor());
CallableDescriptor fd = resolvedCall.getResultingDescriptor();
assert fd instanceof FunctionDescriptor : "Resolved call doesn't refer to the function descriptor: " + fd;
CallableMethod callable = (CallableMethod) codegen.resolveToCallable((FunctionDescriptor) fd, false, resolvedCall);
@@ -74,11 +73,6 @@ public class TailRecursionCodegen {
if (arguments == null) {
throw new IllegalStateException("Failed to arrange value arguments by index: " + fd);
}
if (((FunctionDescriptor) fd).isSuspend()) {
AsmUtil.pop(v, callable.getValueParameters().get(callable.getValueParameters().size() - 1).getAsmType());
}
assignParameterValues(fd, callable, arguments);
if (callable.getExtensionReceiverType() != null) {
if (resolvedCall.getExtensionReceiver() != fd.getExtensionReceiverParameter().getValue()) {

View File

@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.binding;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.types.KotlinType;
@@ -138,7 +137,7 @@ public final class MutableClosure implements CalculatedClosure {
isSuspendLambda = true;
}
private void recordField(String name, Type type) {
public void recordField(String name, Type type) {
if (recordedFields == null) {
recordedFields = new LinkedList<Pair<String, Type>>();
}
@@ -146,8 +145,6 @@ public final class MutableClosure implements CalculatedClosure {
}
public void captureVariable(EnclosedValueDescriptor value) {
recordField(value.getFieldName(), value.getType());
if (captureVariables == null) {
captureVariables = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
}

View File

@@ -40,7 +40,7 @@ private fun Iterable<PackageParts>.addCompiledParts(state: GenerationState): Lis
val incrementalCache = state.incrementalCacheForThisTarget ?: return this.toList()
val moduleMappingData = incrementalCache.getModuleMappingData() ?: return this.toList()
val mapping = ModuleMapping.create(moduleMappingData, "<incremental>", state.deserializationConfiguration)
val mapping = ModuleMapping.create(moduleMappingData, "<incremental>")
incrementalCache.getObsoletePackageParts().forEach { internalName ->
val qualifier = internalName.substringBeforeLast('/', "").replace('/', '.')

View File

@@ -75,6 +75,7 @@ public interface LocalLookup {
enclosedValueDescriptor = new EnclosedValueDescriptor(fieldName, d, innerValue, type);
}
closure.recordField(fieldName, type);
closure.captureVariable(enclosedValueDescriptor);
return innerValue;
@@ -114,6 +115,7 @@ public interface LocalLookup {
StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field(localType, classType, fieldName, false,
StackValue.LOCAL_0, vd);
closure.recordField(fieldName, localType);
closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, localType));
return innerValue;

View File

@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
@@ -40,10 +41,11 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -72,7 +74,7 @@ class CoroutineCodegen private constructor(
// protected fun doResume(result, throwable)
private val doResumeDescriptor =
SimpleFunctionDescriptorImpl.create(
classDescriptor, Annotations.EMPTY, Name.identifier(DO_RESUME_METHOD_NAME), CallableMemberDescriptor.Kind.DECLARATION,
classDescriptor, Annotations.EMPTY, Name.identifier("doResume"), CallableMemberDescriptor.Kind.DECLARATION,
funDescriptor.source
).apply doResume@{
initialize(
@@ -114,7 +116,7 @@ class CoroutineCodegen private constructor(
}
override fun generateClosureBody() {
for (parameter in allFunctionParameters()) {
for (parameter in allLambdaParameters()) {
val fieldInfo = parameter.getFieldInfoForCoroutineLambdaParameter()
v.newField(
OtherOrigin(parameter),
@@ -153,7 +155,7 @@ class CoroutineCodegen private constructor(
}
})
if (allFunctionParameters().size <= 1) {
if (allLambdaParameters().size <= 1) {
val delegate = typeMapper.mapSignatureSkipGeneric(createCoroutineDescriptor).asmMethod
val bridgeParameters = (1..delegate.argumentTypes.size - 1).map { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
@@ -239,7 +241,7 @@ class CoroutineCodegen private constructor(
}
// load resultContinuation
load(allFunctionParameters().map { typeMapper.mapType(it.type).size }.sum() + 1, AsmTypes.OBJECT_TYPE)
load(allLambdaParameters().map { typeMapper.mapType(it.type).size }.sum() + 1, AsmTypes.OBJECT_TYPE)
invokespecial(owner.internalName, constructorToUseFromInvoke.name, constructorToUseFromInvoke.descriptor, false)
@@ -248,7 +250,7 @@ class CoroutineCodegen private constructor(
// Pass lambda parameters to 'invoke' call on newly constructed object
var index = 1
for (parameter in allFunctionParameters()) {
for (parameter in allLambdaParameters()) {
val fieldInfoForCoroutineLambdaParameter = parameter.getFieldInfoForCoroutineLambdaParameter()
load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
AsmUtil.genAssignInstanceFieldFromParam(fieldInfoForCoroutineLambdaParameter, index, this, cloneIndex)
@@ -261,36 +263,27 @@ class CoroutineCodegen private constructor(
}
private fun ExpressionCodegen.initializeCoroutineParameters() {
if (!isSuspendLambda && !originalSuspendFunctionDescriptor.isTailrec) return
for (parameter in allFunctionParameters()) {
val fieldStackValue =
if (isSuspendLambda)
StackValue.field(
parameter.getFieldInfoForCoroutineLambdaParameter(), generateThisOrOuter(context.thisDescriptor, false)
)
else
closureContext.lookupInContext(parameter, null, state, /* ignoreNoOuter = */ false)
for (parameter in allLambdaParameters()) {
val mappedType = typeMapper.mapType(parameter.type)
fieldStackValue.put(mappedType, v)
val newIndex = myFrameMap.enter(parameter, mappedType)
generateLoadField(parameter.getFieldInfoForCoroutineLambdaParameter())
v.store(newIndex, mappedType)
}
// necessary for proper tailrec codegen
val actualMethodStartLabel = Label()
v.visitLabel(actualMethodStartLabel)
context.setMethodStartLabel(actualMethodStartLabel)
if (isSuspendLambda) {
initializeVariablesForDestructuredLambdaParameters(this, originalSuspendFunctionDescriptor.valueParameters)
}
}
private fun allFunctionParameters() =
originalSuspendFunctionDescriptor.extensionReceiverParameter.singletonOrEmptyList() +
originalSuspendFunctionDescriptor.valueParameters.orEmpty()
private fun allLambdaParameters() =
if (isSuspendLambda)
originalSuspendFunctionDescriptor.extensionReceiverParameter.singletonOrEmptyList() + originalSuspendFunctionDescriptor.valueParameters.orEmpty()
else
emptyList()
private fun ExpressionCodegen.generateLoadField(fieldInfo: FieldInfo) {
StackValue.field(fieldInfo, generateThisOrOuter(context.thisDescriptor, false)).put(fieldInfo.fieldType, v)
}
private fun ParameterDescriptor.getFieldInfoForCoroutineLambdaParameter() =
createHiddenFieldInfo(type, COROUTINE_LAMBDA_PARAMETER_PREFIX + (this.safeAs<ValueParameterDescriptor>()?.index ?: ""))

View File

@@ -141,12 +141,12 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
List<CapturedParamInfo> additionalFakeParams =
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
transformationInfo, parentRemapper);
List<DeferredMethodVisitor> deferringMethods = new ArrayList<DeferredMethodVisitor>();
List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, parentRemapper, additionalFakeParams);
for (MethodNode next : methodsToTransform) {
DeferredMethodVisitor deferringVisitor = newMethod(classBuilder, next);
MethodVisitor deferringVisitor = newMethod(classBuilder, next);
InlineResult funResult =
inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false);
@@ -161,8 +161,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
deferringMethods.add(deferringVisitor);
}
for (DeferredMethodVisitor method : deferringMethods) {
InlineCodegenUtil.removeFinallyMarkers(method.getIntermediate());
for (MethodVisitor method : deferringMethods) {
method.visitEnd();
}
@@ -314,7 +313,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
MethodNode intermediateMethodNode =
new MethodNode(AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY);
inlineMethodAndUpdateGlobalResult(parentRemapper, intermediateMethodNode, constructor, constructorInlineBuilder, true);
InlineCodegenUtil.removeFinallyMarkers(intermediateMethodNode);
AbstractInsnNode first = intermediateMethodNode.instructions.getFirst();
final Label oldStartLabel = first instanceof LabelNode ? ((LabelNode) first).getLabel() : null;

View File

@@ -466,9 +466,7 @@ public class InlineCodegen extends CallGenerator {
adapter, infos, ((StackValue.Local) remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index
);
removeStaticInitializationTrigger(adapter);
if (!InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) {
InlineCodegenUtil.removeFinallyMarkers(adapter);
}
removeFinallyMarkers(adapter);
adapter.accept(new MethodBodyVisitor(codegen.v));
@@ -1026,6 +1024,25 @@ public class InlineCodegen extends CallGenerator {
//processor.substituteLocalVarTable(intoNode);
}
private void removeFinallyMarkers(@NotNull MethodNode intoNode) {
if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return;
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (InlineCodegenUtil.isFinallyMarker(curInstr)) {
AbstractInsnNode marker = curInstr;
//just to assert
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
@NotNull
public static SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap, @NotNull SourceMapper parent) {
return new NestedSourceMapper(parent, nodeAndSmap.getSortedRanges(), nodeAndSmap.getClassSMAP().getSourceInfo());

View File

@@ -466,23 +466,6 @@ public class InlineCodegenUtil {
}
}
public static void removeFinallyMarkers(@NotNull MethodNode intoNode) {
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (isFinallyMarker(curInstr)) {
AbstractInsnNode marker = curInstr;
//just to assert
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) {
v.visitMethodInsn(
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,

View File

@@ -463,7 +463,6 @@ public class MethodInliner {
Map<Integer, LambdaInfo> lambdaMapping = new HashMap<Integer, LambdaInfo>();
int offset = 0;
boolean capturesAnonymousObjectThatMustBeRegenerated = false;
for (int i = 0; i < paramCount; i++) {
SourceValue sourceValue = frame.getStack(firstParameterIndex + i);
LambdaInfo lambdaInfo = MethodInlinerUtilKt.getLambdaIfExistsAndMarkInstructions(
@@ -472,17 +471,12 @@ public class MethodInliner {
if (lambdaInfo != null) {
lambdaMapping.put(offset, lambdaInfo);
}
else if (i < argTypes.length && isAnonymousClassThatMustBeRegenerated(argTypes[i])) {
capturesAnonymousObjectThatMustBeRegenerated = true;
}
offset += i == 0 ? 1 : argTypes[i - 1].getSize();
}
transformations.add(
buildConstructorInvocation(
owner, desc, lambdaMapping, awaitClassReification, capturesAnonymousObjectThatMustBeRegenerated
)
buildConstructorInvocation(owner, desc, lambdaMapping, awaitClassReification)
);
awaitClassReification = false;
}
@@ -544,12 +538,6 @@ public class MethodInliner {
return node;
}
private boolean isAnonymousClassThatMustBeRegenerated(@Nullable Type type) {
if (type == null || type.getSort() != Type.OBJECT) return false;
AnonymousObjectTransformationInfo info = inliningContext.findAnonymousObjectTransformationInfo(type.getInternalName());
return info != null && info.shouldRegenerate(true);
}
@NotNull
private Frame<SourceValue>[] analyzeMethodNodeBeforeInline(@NotNull MethodNode node) {
try {
@@ -596,8 +584,7 @@ public class MethodInliner {
@NotNull String anonymousType,
@NotNull String desc,
@NotNull Map<Integer, LambdaInfo> lambdaMapping,
boolean needReification,
boolean capturesAnonymousObjectThatMustBeRegenerated
boolean needReification
) {
boolean memoizeAnonymousObject = inliningContext.findAnonymousObjectTransformationInfo(anonymousType) == null;
@@ -607,8 +594,7 @@ public class MethodInliner {
isAlreadyRegenerated(anonymousType),
desc,
false,
inliningContext.nameGenerator,
capturesAnonymousObjectThatMustBeRegenerated
inliningContext.nameGenerator
);
if (memoizeAnonymousObject) {

View File

@@ -68,8 +68,7 @@ class AnonymousObjectTransformationInfo internal constructor(
private val alreadyRegenerated: Boolean,
val constructorDesc: String?,
private val isStaticOrigin: Boolean,
parentNameGenerator: NameGenerator,
private val capturesAnonymousObjectThatMustBeRegenerated: Boolean = false
parentNameGenerator: NameGenerator
) : TransformationInfo {
override val nameGenerator by lazy {
@@ -94,8 +93,7 @@ class AnonymousObjectTransformationInfo internal constructor(
) : this(ownerInternalName, needReification, hashMapOf(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator)
override fun shouldRegenerate(sameModule: Boolean): Boolean =
!alreadyRegenerated &&
(!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification || capturesAnonymousObjectThatMustBeRegenerated)
!alreadyRegenerated && (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification)
override fun canRemoveAfterTransformation(): Boolean {
// Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda

View File

@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class CompareTo : IntrinsicMethod() {
private fun genInvoke(type: Type?, v: InstructionAdapter) {
when (type) {
Type.INT_TYPE, Type.CHAR_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false)

View File

@@ -47,12 +47,12 @@ class Concat : IntrinsicMethod() {
codegen.invokeAppend(element.right)
}
else {
// Explicit plus call LHS?.plus(RHS) or LHS.plus(RHS)
receiver.put(AsmTypes.JAVA_STRING_TYPE, v)
// LHS?.plus(RHS)
receiver.put(AsmTypes.OBJECT_TYPE, v)
genStringBuilderConstructor(v)
v.swap()
genInvokeAppendMethod(v, returnType)
codegen.invokeAppend(arguments[0])
codegen.invokeAppend(arguments.get(0))
}
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)

View File

@@ -20,53 +20,35 @@ import com.intellij.openapi.util.Pair
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.toReadOnlyList
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import java.util.*
abstract class BoxedBasicValue(type: Type) : StrictBasicValue(type) {
abstract val descriptor: BoxedValueDescriptor
abstract fun taint(): BoxedBasicValue
override fun equals(other: Any?) = this === other
override fun hashCode() = System.identityHashCode(this)
}
class CleanBoxedValue(
class BoxedBasicValue(
boxedType: Type,
boxingInsn: AbstractInsnNode,
progressionIterator: ProgressionIteratorBasicValue?
) : BoxedBasicValue(boxedType) {
override val descriptor = BoxedValueDescriptor(boxedType, boxingInsn, progressionIterator)
private var tainted: TaintedBoxedValue? = null
override fun taint(): BoxedBasicValue = tainted ?: TaintedBoxedValue(this).also { tainted = it }
}
class TaintedBoxedValue(val boxedBasicValue: CleanBoxedValue) : BoxedBasicValue(boxedBasicValue.type) {
override val descriptor get() = boxedBasicValue.descriptor
override fun taint(): BoxedBasicValue = this
}
class BoxedValueDescriptor(
val boxedType: Type,
val boxingInsn: AbstractInsnNode,
val progressionIterator: ProgressionIteratorBasicValue?
) {
) : StrictBasicValue(boxedType) {
private val associatedInsns = HashSet<AbstractInsnNode>()
private val unboxingWithCastInsns = HashSet<Pair<AbstractInsnNode, Type>>()
private val associatedVariables = HashSet<Int>()
private val mergedWith = HashSet<BoxedValueDescriptor>()
private val mergedWith = HashSet<BoxedBasicValue>()
val primitiveType: Type = unboxType(boxedType)
var isSafeToRemove = true; private set
val unboxedType: Type = getUnboxedType(boxedType)
fun getAssociatedInsns() = associatedInsns.toReadOnlyList()
override fun equals(other: Any?) =
this === other
fun typeEquals(other: BasicValue) =
other is BoxedBasicValue && type == other.type
override fun hashCode() =
System.identityHashCode(this)
fun getAssociatedInsns(): List<AbstractInsnNode> =
ArrayList(associatedInsns)
fun addInsn(insnNode: AbstractInsnNode) {
associatedInsns.add(insnNode)
@@ -79,20 +61,22 @@ class BoxedValueDescriptor(
fun getVariablesIndexes(): List<Int> =
ArrayList(associatedVariables)
fun addMergedWith(descriptor: BoxedValueDescriptor) {
mergedWith.add(descriptor)
fun addMergedWith(value: BoxedBasicValue) {
mergedWith.add(value)
}
fun getMergedWith(): Iterable<BoxedValueDescriptor> =
fun getMergedWith(): Iterable<BoxedBasicValue> =
mergedWith
fun markAsUnsafeToRemove() {
isSafeToRemove = false
}
fun isDoubleSize() = unboxedType.size == 2
fun isDoubleSize() =
primitiveType.size == 2
fun isFromProgressionIterator() = progressionIterator != null
fun isFromProgressionIterator() =
progressionIterator != null
fun addUnboxingWithCastTo(insn: AbstractInsnNode, type: Type) {
unboxingWithCastInsns.add(Pair.create(insn, type))
@@ -100,14 +84,15 @@ class BoxedValueDescriptor(
fun getUnboxingWithCastInsns(): Set<Pair<AbstractInsnNode, Type>> =
unboxingWithCastInsns
}
fun getUnboxedType(boxedType: Type): Type {
val primitiveType = AsmUtil.unboxPrimitiveTypeOrNull(boxedType)
if (primitiveType != null) return primitiveType
if (boxedType == AsmTypes.K_CLASS_TYPE) return AsmTypes.JAVA_CLASS_TYPE
throw IllegalArgumentException("Expected primitive type wrapper or KClass, got: $boxedType")
companion object {
private fun unboxType(boxedType: Type): Type {
val primitiveType = AsmUtil.unboxPrimitiveTypeOrNull(boxedType)
if (primitiveType != null) return primitiveType
if (boxedType == AsmTypes.K_CLASS_TYPE) return AsmTypes.JAVA_CLASS_TYPE
throw IllegalArgumentException("Expected primitive type wrapper or KClass, got: $boxedType")
}
}
}

View File

@@ -29,6 +29,7 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import java.util.*
@@ -38,23 +39,14 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
protected open fun createNewBoxing(insn: AbstractInsnNode, type: Type, progressionIterator: ProgressionIteratorBasicValue?): BasicValue {
val index = insnList.indexOf(insn)
return boxingPlaces.getOrPut(index) {
val boxedBasicValue = CleanBoxedValue(type, insn, progressionIterator)
val boxedBasicValue = BoxedBasicValue(type, insn, progressionIterator)
onNewBoxedValue(boxedBasicValue)
boxedBasicValue
}
}
protected fun checkUsedValue(value: BasicValue) {
if (value is TaintedBoxedValue) {
onMergeFail(value)
}
}
@Throws(AnalyzerException::class)
override fun naryOperation(insn: AbstractInsnNode, values: List<BasicValue>): BasicValue? {
values.forEach {
checkUsedValue(it)
}
val value = super.naryOperation(insn, values)
val firstArg = values.firstOrNull() ?: return value
@@ -88,39 +80,36 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
}
}
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? {
checkUsedValue(value)
return if (insn.opcode == Opcodes.CHECKCAST && isExactValue(value))
value
else
super.unaryOperation(insn, value)
}
@Throws(AnalyzerException::class)
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? =
if (insn.opcode == Opcodes.CHECKCAST && isExactValue(value))
value
else
super.unaryOperation(insn, value)
protected open fun isExactValue(value: BasicValue) =
value is ProgressionIteratorBasicValue ||
value is CleanBoxedValue ||
value is BoxedBasicValue ||
value.type != null && isProgressionClass(value.type.internalName)
override fun merge(v: BasicValue, w: BasicValue) =
when {
v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE ->
v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE -> {
StrictBasicValue.UNINITIALIZED_VALUE
v is BoxedBasicValue && w is BoxedBasicValue -> {
onMergeSuccess(v, w)
when {
v is TaintedBoxedValue -> v
w is TaintedBoxedValue -> w
v.type != w.type -> v.taint()
else -> v
}
}
v is BoxedBasicValue ->
v.taint()
w is BoxedBasicValue ->
w.taint()
else ->
v is BoxedBasicValue && v.typeEquals(w) -> {
onMergeSuccess(v, w as BoxedBasicValue)
v
}
else -> {
if (v is BoxedBasicValue) {
onMergeFail(v)
}
if (w is BoxedBasicValue) {
onMergeFail(w)
}
super.merge(v, w)
}
}
protected open fun onNewBoxedValue(value: BoxedBasicValue) {}
@@ -208,5 +197,7 @@ private fun isProgressionClass(internalClassName: String) =
RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(internalClassName))
private fun getValuesTypeOfProgressionClass(progressionClassInternalName: String) =
RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(buildFqNameByInternal(progressionClassInternalName))
?.typeName?.asString() ?: error("type should be not null")
RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(buildFqNameByInternal(progressionClassInternalName))?.let {
type ->
type.typeName.asString()
} ?: error("type should be not null")

View File

@@ -22,25 +22,25 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class RedundantBoxedValuesCollection implements Iterable<BoxedValueDescriptor> {
private final Set<BoxedValueDescriptor> safeToDeleteValues = new HashSet<BoxedValueDescriptor>();
public class RedundantBoxedValuesCollection implements Iterable<BoxedBasicValue> {
private final Set<BoxedBasicValue> safeToDeleteValues = new HashSet<BoxedBasicValue>();
public void add(@NotNull BoxedValueDescriptor descriptor) {
safeToDeleteValues.add(descriptor);
public void add(@NotNull BoxedBasicValue value) {
safeToDeleteValues.add(value);
}
public void remove(@NotNull BoxedValueDescriptor descriptor) {
if (safeToDeleteValues.contains(descriptor)) {
safeToDeleteValues.remove(descriptor);
descriptor.markAsUnsafeToRemove();
public void remove(@NotNull BoxedBasicValue value) {
if (safeToDeleteValues.contains(value)) {
safeToDeleteValues.remove(value);
value.markAsUnsafeToRemove();
for (BoxedValueDescriptor mergedValueDescriptor : descriptor.getMergedWith()) {
remove(mergedValueDescriptor);
for (BoxedBasicValue mergedValue : value.getMergedWith()) {
remove(mergedValue);
}
}
}
public void merge(@NotNull BoxedValueDescriptor v, @NotNull BoxedValueDescriptor w) {
public void merge(@NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w) {
v.addMergedWith(w);
w.addMergedWith(v);
@@ -59,7 +59,7 @@ public class RedundantBoxedValuesCollection implements Iterable<BoxedValueDescri
@NotNull
@Override
public Iterator<BoxedValueDescriptor> iterator() {
public Iterator<BoxedBasicValue> iterator() {
return safeToDeleteValues.iterator();
}
}

View File

@@ -23,12 +23,30 @@ import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterpreter(insnList) {
val candidatesBoxedValues = RedundantBoxedValuesCollection()
@Throws(AnalyzerException::class)
override fun binaryOperation(insn: AbstractInsnNode, value1: BasicValue, value2: BasicValue): BasicValue? {
processOperationWithBoxedValue(value1, insn)
processOperationWithBoxedValue(value2, insn)
return super.binaryOperation(insn, value1, value2)
}
@Throws(AnalyzerException::class)
override fun ternaryOperation(insn: AbstractInsnNode, value1: BasicValue, value2: BasicValue, value3: BasicValue): BasicValue? {
// in a valid code only aastore could happen with boxed value
processOperationWithBoxedValue(value3, insn)
return super.ternaryOperation(insn, value1, value2, value3)
}
@Throws(AnalyzerException::class)
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? {
if ((insn.opcode == Opcodes.CHECKCAST || insn.opcode == Opcodes.INSTANCEOF) && value is BoxedBasicValue) {
val typeInsn = insn as TypeInsnNode
@@ -43,23 +61,10 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
return super.unaryOperation(insn, value)
}
override fun binaryOperation(insn: AbstractInsnNode, value1: BasicValue, value2: BasicValue): BasicValue? {
processOperationWithBoxedValue(value1, insn)
processOperationWithBoxedValue(value2, insn)
return super.binaryOperation(insn, value1, value2)
}
override fun ternaryOperation(insn: AbstractInsnNode, value1: BasicValue, value2: BasicValue, value3: BasicValue): BasicValue? {
// in a valid code only aastore could happen with boxed value
processOperationWithBoxedValue(value3, insn)
return super.ternaryOperation(insn, value1, value2, value3)
}
@Throws(AnalyzerException::class)
override fun copyOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue {
if (value is BoxedBasicValue && insn.opcode == Opcodes.ASTORE) {
value.descriptor.addVariableIndex((insn as VarInsnNode).`var`)
if (value is BoxedBasicValue && insn.opcode === Opcodes.ASTORE) {
value.addVariableIndex((insn as VarInsnNode).`var`)
}
processOperationWithBoxedValue(value, insn)
@@ -72,15 +77,15 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
}
override fun onNewBoxedValue(value: BoxedBasicValue) {
candidatesBoxedValues.add(value.descriptor)
candidatesBoxedValues.add(value)
}
override fun onUnboxing(insn: AbstractInsnNode, value: BoxedBasicValue, resultType: Type) {
value.descriptor.run {
if (unboxedType == resultType)
addAssociatedInsn(value, insn)
else
addUnboxingWithCastTo(insn, resultType)
if (value.primitiveType == resultType) {
addAssociatedInsn(value, insn)
}
else {
value.addUnboxingWithCastTo(insn, resultType)
}
}
@@ -93,13 +98,11 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
}
override fun onMergeSuccess(v: BoxedBasicValue, w: BoxedBasicValue) {
candidatesBoxedValues.merge(v.descriptor, w.descriptor)
candidatesBoxedValues.merge(v, w)
}
private fun processOperationWithBoxedValue(value: BasicValue?, insnNode: AbstractInsnNode) {
if (value is BoxedBasicValue) {
checkUsedValue(value)
if (!PERMITTED_OPERATIONS_OPCODES.contains(insnNode.opcode)) {
markValueAsDirty(value)
}
@@ -110,7 +113,7 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
}
private fun markValueAsDirty(value: BoxedBasicValue) {
candidatesBoxedValues.remove(value.descriptor)
candidatesBoxedValues.remove(value)
}
companion object {
@@ -124,15 +127,17 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
when (targetInternalName) {
Type.getInternalName(Any::class.java) ->
true
Type.getInternalName(Number::class.java) ->
PRIMITIVE_TYPES_SORTS_WITH_WRAPPER_EXTENDS_NUMBER.contains(value.descriptor.unboxedType.sort)
Type.getInternalName(Number::class.java) -> {
PRIMITIVE_TYPES_SORTS_WITH_WRAPPER_EXTENDS_NUMBER.contains(
value.primitiveType.sort)
}
else ->
value.type.internalName == targetInternalName
value.type.internalName.equals(targetInternalName)
}
private fun addAssociatedInsn(value: BoxedBasicValue, insn: AbstractInsnNode) {
value.descriptor.run {
if (isSafeToRemove) addInsn(insn)
if (value.isSafeToRemove) {
value.addInsn(insn)
}
}
}

View File

@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.codegen.optimization.boxing;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.intellij.openapi.util.Pair;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
@@ -36,8 +38,9 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
@Override
public void transform(@NotNull String internalClassName, @NotNull MethodNode node) {
RedundantBoxingInterpreter interpreter = new RedundantBoxingInterpreter(node.instructions);
Frame<BasicValue>[] frames = analyze(internalClassName, node, interpreter);
Frame<BasicValue>[] frames = analyze(
internalClassName, node, interpreter
);
interpretPopInstructionsForBoxedValues(interpreter, node, frames);
RedundantBoxedValuesCollection valuesToOptimize = interpreter.getCandidatesBoxedValues();
@@ -96,25 +99,32 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
continue;
}
List<BasicValue> variableValues = getValuesStoredOrLoadedToVariable(localVariableNode, node, frames);
List<BasicValue> usedValues = getValuesStoredOrLoadedToVariable(localVariableNode, node, frames);
Collection<BasicValue> boxed = CollectionsKt.filter(variableValues, new Function1<BasicValue, Boolean>() {
Collection<BasicValue> boxed = Collections2.filter(usedValues, new Predicate<BasicValue>() {
@Override
public Boolean invoke(BasicValue value) {
return value instanceof BoxedBasicValue;
public boolean apply(BasicValue input) {
return input instanceof BoxedBasicValue;
}
});
if (boxed.isEmpty()) continue;
BoxedValueDescriptor firstBoxed = ((BoxedBasicValue) boxed.iterator().next()).getDescriptor();
if (isUnsafeToRemoveBoxingForConnectedValues(variableValues, firstBoxed.getUnboxedType())) {
for (BasicValue value : variableValues) {
if (!(value instanceof BoxedBasicValue)) continue;
final BoxedBasicValue firstBoxed = (BoxedBasicValue) boxed.iterator().next();
BoxedValueDescriptor descriptor = ((BoxedBasicValue) value).getDescriptor();
if (descriptor.isSafeToRemove()) {
values.remove(descriptor);
if (CollectionsKt.any(usedValues, new Function1<BasicValue, Boolean>() {
@Override
public Boolean invoke(BasicValue input) {
if (input == StrictBasicValue.UNINITIALIZED_VALUE) return false;
return input == null ||
!(input instanceof BoxedBasicValue) ||
!((BoxedBasicValue) input).isSafeToRemove() ||
!((BoxedBasicValue) input).getPrimitiveType().equals(firstBoxed.getPrimitiveType());
}
})) {
for (BasicValue value : usedValues) {
if (value instanceof BoxedBasicValue && ((BoxedBasicValue) value).isSafeToRemove()) {
values.remove((BoxedBasicValue) value);
needToRepeat = true;
}
}
@@ -124,20 +134,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
return needToRepeat;
}
private static boolean isUnsafeToRemoveBoxingForConnectedValues(List<BasicValue> usedValues, final Type unboxedType) {
return CollectionsKt.any(usedValues, new Function1<BasicValue, Boolean>() {
@Override
public Boolean invoke(BasicValue input) {
if (input == StrictBasicValue.UNINITIALIZED_VALUE) return false;
if (!(input instanceof BoxedBasicValue)) return true;
BoxedValueDescriptor descriptor = ((BoxedBasicValue) input).getDescriptor();
return !descriptor.isSafeToRemove() ||
!(descriptor.getUnboxedType().equals(unboxedType));
}
});
}
private static void adaptLocalVariableTableForBoxedValues(@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
for (LocalVariableNode localVariableNode : node.localVariables) {
if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) {
@@ -145,11 +141,8 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
for (BasicValue value : getValuesStoredOrLoadedToVariable(localVariableNode, node, frames)) {
if (!(value instanceof BoxedBasicValue)) continue;
BoxedValueDescriptor descriptor = ((BoxedBasicValue) value).getDescriptor();
if (!descriptor.isSafeToRemove()) continue;
localVariableNode.desc = descriptor.getUnboxedType().getDescriptor();
if (value == null || !(value instanceof BoxedBasicValue) || !((BoxedBasicValue) value).isSafeToRemove()) continue;
localVariableNode.desc = ((BoxedBasicValue) value).getPrimitiveType().getDescriptor();
}
}
}
@@ -200,9 +193,9 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
@NotNull
private static int[] buildVariablesRemapping(@NotNull RedundantBoxedValuesCollection values, @NotNull MethodNode node) {
Set<Integer> doubleSizedVars = new HashSet<Integer>();
for (BoxedValueDescriptor valueDescriptor : values) {
if (valueDescriptor.isDoubleSize()) {
doubleSizedVars.addAll(valueDescriptor.getVariablesIndexes());
for (BoxedBasicValue value : values) {
if (value.getPrimitiveType().getSize() == 2) {
doubleSizedVars.addAll(value.getVariablesIndexes());
}
}
@@ -240,12 +233,12 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
@NotNull MethodNode node,
@NotNull RedundantBoxedValuesCollection values
) {
for (BoxedValueDescriptor value : values) {
for (BoxedBasicValue value : values) {
adaptInstructionsForBoxedValue(node, value);
}
}
private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedValueDescriptor value) {
private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedBasicValue value) {
adaptBoxingInstruction(node, value);
for (Pair<AbstractInsnNode, Type> cast : value.getUnboxingWithCastInsns()) {
@@ -257,7 +250,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
}
private static void adaptBoxingInstruction(@NotNull MethodNode node, @NotNull BoxedValueDescriptor value) {
private static void adaptBoxingInstruction(@NotNull MethodNode node, @NotNull BoxedBasicValue value) {
if (!value.isFromProgressionIterator()) {
node.instructions.remove(value.getBoxingInsn());
}
@@ -287,12 +280,12 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
private static void adaptCastInstruction(
@NotNull MethodNode node,
@NotNull BoxedValueDescriptor value,
@NotNull BoxedBasicValue value,
@NotNull Pair<AbstractInsnNode, Type> castWithType
) {
AbstractInsnNode castInsn = castWithType.getFirst();
MethodNode castInsnsListener = new MethodNode(Opcodes.ASM5);
new InstructionAdapter(castInsnsListener).cast(value.getUnboxedType(), castWithType.getSecond());
new InstructionAdapter(castInsnsListener).cast(value.getPrimitiveType(), castWithType.getSecond());
for (AbstractInsnNode insn : castInsnsListener.instructions.toArray()) {
node.instructions.insertBefore(castInsn, insn);
@@ -302,7 +295,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
private static void adaptInstruction(
@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedValueDescriptor value
@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value
) {
boolean isDoubleSize = value.isDoubleSize();
@@ -329,7 +322,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
node.instructions.set(
insn,
new VarInsnNode(
value.getUnboxedType().getOpcode(intVarOpcode),
value.getPrimitiveType().getOpcode(intVarOpcode),
((VarInsnNode) insn).var
)
);

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.signature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.AsmUtil;
import org.jetbrains.kotlin.load.kotlin.JvmDescriptorTypeWriter;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
@@ -58,7 +57,7 @@ public class JvmSignatureWriter extends JvmDescriptorTypeWriter<Type> {
return;
case Type.ARRAY:
writeArrayType();
writeAsmType(AsmUtil.correctElementType(asmType));
writeAsmType(asmType.getElementType());
writeArrayEnd();
return;
default:

View File

@@ -41,10 +41,12 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.BindingTraceFilter
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.org.objectweb.asm.Opcodes
import java.io.File
@@ -92,7 +94,6 @@ class GenerationState @JvmOverloads constructor(
val incrementalCacheForThisTarget: IncrementalCache?
val packagesWithObsoleteParts: Set<FqName>
val obsoleteMultifileClasses: List<FqName>
val deserializationConfiguration: DeserializationConfiguration = CompilerDeserializationConfiguration(configuration)
init {
val icComponents = configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS)
@@ -166,7 +167,7 @@ class GenerationState @JvmOverloads constructor(
val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA)
val languageVersionSettings = configuration.languageVersionSettings
val languageVersionSettings = configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
val shouldInlineConstVals = languageVersionSettings.supportsFeature(LanguageFeature.InlineConstVals)
init {

View File

@@ -958,7 +958,7 @@ public class KotlinTypeMapper {
if (!(descriptor instanceof ConstructorDescriptor) &&
descriptor.getVisibility() == Visibilities.INTERNAL &&
!descriptor.getAnnotations().hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi)) {
!DescriptorUtilsKt.isPublishedApi(descriptor)) {
return name + "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName);
}
@@ -1154,13 +1154,13 @@ public class KotlinTypeMapper {
}
@NotNull
private static String getDefaultDescriptor(
@NotNull Method method,
@Nullable String dispatchReceiverDescriptor,
@NotNull CallableDescriptor callableDescriptor
) {
private static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
String descriptor = method.getDescriptor();
int maskArgumentsCount = (callableDescriptor.getValueParameters().size() + Integer.SIZE - 1) / Integer.SIZE;
int argumentsCount = Type.getArgumentTypes(descriptor).length;
if (isExtension) {
argumentsCount--;
}
int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
additionalArgs += (isConstructor(method) ? DEFAULT_CONSTRUCTOR_MARKER : OBJECT_TYPE).getDescriptor();
String result = descriptor.replace(")", additionalArgs + ")");
@@ -1186,7 +1186,7 @@ public class KotlinTypeMapper {
String descriptor = getDefaultDescriptor(
jvmSignature,
isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(),
CodegenUtilKt.unwrapFrontendVersion(functionDescriptor)
functionDescriptor.getExtensionReceiverParameter() != null
);
return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);

View File

@@ -17,10 +17,10 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
@@ -37,7 +37,7 @@ fun writeKotlinMetadata(
av.visit(JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME, JvmBytecodeBinaryVersion.INSTANCE.toArray())
av.visit(JvmAnnotationNames.KIND_FIELD_NAME, kind.id)
var flags = extraFlags
if (KotlinCompilerVersion.isPreRelease() && state.languageVersionSettings.languageVersion == LanguageVersion.LATEST) {
if (DeserializedDescriptorResolver.IS_PRE_RELEASE && state.languageVersionSettings.languageVersion == LanguageVersion.LATEST) {
flags = flags or JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG
}
if (flags != 0) {

View File

@@ -63,9 +63,6 @@ public abstract class CommonCompilerArguments implements Serializable {
@ValueDescription("<count>")
public String repeat;
@Argument(value = "Xskip-metadata-version-check", description = "Load classes with bad metadata version anyway (incl. pre-release classes)")
public boolean skipMetadataVersionCheck;
@Argument(value = "Xallow-kotlin-package", description = "Allow compiling code in package 'kotlin'")
public boolean allowKotlinPackage;
@@ -79,6 +76,9 @@ public abstract class CommonCompilerArguments implements Serializable {
@Argument(value = "Xno-check-impl", description = "Do not check presence of 'impl' modifier in multi-platform projects")
public boolean noCheckImpl;
@Argument(value = "Xskip-java-check", description = "Do not warn when running the compiler under Java 6 or 7")
public boolean noJavaVersionWarning;
@Argument(value = "Xcoroutines=warn")
public boolean coroutinesWarn;

View File

@@ -94,6 +94,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
@Argument(value = "Xmultifile-parts-inherit", description = "Compile multifile classes as a hierarchy of parts and facade")
public boolean inheritMultifileParts;
@Argument(value = "Xskip-metadata-version-check", description = "Load classes with bad metadata version anyway (incl. pre-release classes)")
public boolean skipMetadataVersionCheck;
@Argument(value = "Xskip-runtime-version-check", description = "Allow Kotlin runtime libraries of incompatible versions in the classpath")
public boolean skipRuntimeVersionCheck;

View File

@@ -23,8 +23,6 @@ import java.util.EnumSet;
public enum CompilerMessageSeverity {
EXCEPTION,
ERROR,
// Unlike a normal warning, a strong warning is not discarded when there are compilation errors.
// Use it for problems related to configuration, not the diagnostics
STRONG_WARNING,
WARNING,
INFO,

View File

@@ -1,88 +0,0 @@
/*
* Copyright 2010-2017 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.cli.common.repl
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
open class AggregatedReplStateHistory<T1, T2>(val history1: IReplStageHistory<T1>, val history2: IReplStageHistory<T2>, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock())
: IReplStageHistory<Pair<T1, T2>>, AbstractList<ReplHistoryRecord<Pair<T1, T2>>>()
{
override val size: Int
get() = minOf(history1.size, history2.size)
override fun push(id: ILineId, item: Pair<T1, T2>) {
lock.write {
assertSameSize()
history1.push(id, item.first)
history2.push(id, item.second)
}
}
override fun get(index: Int): ReplHistoryRecord<Pair<T1, T2>> = lock.read {
assertSameSize()
val r1 = history1[index]
val r2 = history2[index]
assertSameId(r1, r2)
ReplHistoryRecord(r1.id, r1.item to r2.item)
}
override fun pop(): ReplHistoryRecord<Pair<T1, T2>>? = lock.write {
assertSameSize()
val r1 = history1.pop()
val r2 = history2.pop()
if (r1 == null && r2 == null) return null
if (r1 == null || r2 == null) throw IllegalStateException("Aggregated history mismatch: $r1 vs $r2")
assertSameId(r1, r2)
ReplHistoryRecord(r1.id, r1.item to r2.item)
}
override fun resetTo(id: ILineId): Iterable<ILineId> = lock.write {
assertSameSize()
val i1 = history1.resetTo(id).toList()
val i2 = history2.resetTo(id).toList()
if (i1 != i2) throw IllegalStateException("Aggregated history resetted lines mismatch: $i1 != $i2")
i1
}
private fun assertSameSize() {
if (history1.size != history2.size) throw IllegalStateException("Aggregated history sizes mismatch: ${history1.size} != ${history2.size}")
}
private fun assertSameId(r1: ReplHistoryRecord<T1>, r2: ReplHistoryRecord<T2>) {
if (r1.id != r2.id) throw IllegalStateException("Aggregated history mismatch: ${r1.id} != ${r2.id}")
}
}
open class AggregatedReplStageState<T1, T2>(val state1: IReplStageState<T1>, val state2: IReplStageState<T2>, final override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock())
: IReplStageState<Pair<T1, T2>>
{
override val history: IReplStageHistory<Pair<T1, T2>> = AggregatedReplStateHistory(state1.history, state2.history, lock)
override fun <StateT : IReplStageState<*>> asState(target: Class<out StateT>): StateT =
when {
target.isAssignableFrom(state1::class.java) -> state1 as StateT
target.isAssignableFrom(state2::class.java) -> state2 as StateT
else -> super.asState(target)
}
override fun getNextLineNo() = state1.getNextLineNo()
override val currentGeneration: Int get() = state1.currentGeneration
}

View File

@@ -1,72 +0,0 @@
/*
* Copyright 2010-2017 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.cli.common.repl
import java.io.Serializable
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write
data class LineId(override val no: Int, override val generation: Int, private val codeHash: Int) : ILineId, Serializable {
constructor(codeLine: ReplCodeLine): this(codeLine.no, codeLine.generation, codeLine.code.hashCode())
override fun compareTo(other: ILineId): Int = (other as? LineId)?.let {
no.compareTo(it.no).takeIf { it != 0 }
?: generation.compareTo(it.generation).takeIf { it != 0 }
?: codeHash.compareTo(it.codeHash)
} ?: -1 // TODO: check if it doesn't break something
companion object {
private val serialVersionUID: Long = 8328353000L
}
}
open class BasicReplStageHistory<T>(override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : IReplStageHistory<T>, ArrayList<ReplHistoryRecord<T>>() {
val currentGeneration = AtomicInteger(REPL_CODE_LINE_FIRST_GEN)
override fun push(id: ILineId, item: T) {
lock.write {
add(ReplHistoryRecord(id, item))
}
}
override fun pop(): ReplHistoryRecord<T>? = lock.write { if (isEmpty()) null else removeAt(lastIndex) }
override fun resetTo(id: ILineId): Iterable<ILineId> {
lock.write {
val idx = indexOfFirst { it.id == id }
if (idx < 0) throw java.util.NoSuchElementException("Cannot rest to inexistent line ${id.no}")
if (idx < lastIndex) {
val removed = asSequence().drop(idx + 1).map { it.id }.toList()
removeRange(idx + 1, size)
currentGeneration.incrementAndGet()
return removed
}
else return emptyList()
}
}
}
open class BasicReplStageState<HistoryItemT>(override final val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()): IReplStageState<HistoryItemT> {
override val currentGeneration: Int get() = history.currentGeneration.get()
override val history: BasicReplStageHistory<HistoryItemT> = BasicReplStageHistory(lock)
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2010-2017 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.cli.common.repl
import java.io.File
import java.net.URLClassLoader
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
open class GenericReplEvaluatorState(baseClasspath: Iterable<File>, baseClassloader: ClassLoader?, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock())
: IReplStageState<EvalClassWithInstanceAndLoader>
{
override val history: IReplStageHistory<EvalClassWithInstanceAndLoader> = BasicReplStageHistory(lock)
override val currentGeneration: Int get() = (history as BasicReplStageHistory<*>).currentGeneration.get()
val topClassLoader: ReplClassLoader = makeReplClassLoader(baseClassloader, baseClasspath)
val currentClasspath: List<File> get() = lock.read {
history.peek()?.item?.classLoader?.listAllUrlsAsFiles()
?: topClassLoader.listAllUrlsAsFiles()
}
}
internal fun makeReplClassLoader(baseClassloader: ClassLoader?, baseClasspath: Iterable<File>) =
ReplClassLoader(URLClassLoader(baseClasspath.map { it.toURI().toURL() }.toTypedArray(), baseClassloader))

View File

@@ -22,37 +22,27 @@ import kotlin.concurrent.write
class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
baseClasspath: Iterable<File>,
baseClassloader: ClassLoader? = Thread.currentThread().contextClassLoader,
private val fallbackScriptArgs: ScriptArgsWithTypes? = null,
repeatingMode: ReplRepeatingMode = ReplRepeatingMode.REPEAT_ONLY_MOST_RECENT
baseClassloader: ClassLoader?,
protected val fallbackScriptArgs: ScriptArgsWithTypes? = null,
repeatingMode: ReplRepeatingMode = ReplRepeatingMode.REPEAT_ONLY_MOST_RECENT,
protected val stateLock: ReentrantReadWriteLock = ReentrantReadWriteLock()
) : ReplFullEvaluator {
val evaluator = GenericReplEvaluator(baseClasspath, baseClassloader, fallbackScriptArgs, repeatingMode)
val evaluator = GenericReplEvaluator(baseClasspath, baseClassloader, fallbackScriptArgs, repeatingMode, stateLock)
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = AggregatedReplStageState(compiler.createState(lock), evaluator.createState(lock), lock)
override fun compileAndEval(state: IReplStageState<*>, codeLine: ReplCodeLine, scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult {
return state.lock.write {
val aggregatedState = state.asState(AggregatedReplStageState::class.java)
val compiled = compiler.compile(state, codeLine)
override fun compileAndEval(codeLine: ReplCodeLine, scriptArgs: ScriptArgsWithTypes?, verifyHistory: List<ReplCodeLine>?, invokeWrapper: InvokeWrapper?): ReplEvalResult {
return stateLock.write {
val compiled = compiler.compile(codeLine, verifyHistory)
when (compiled) {
is ReplCompileResult.Error -> ReplEvalResult.Error.CompileTime(compiled.message, compiled.location)
is ReplCompileResult.Incomplete -> ReplEvalResult.Incomplete()
is ReplCompileResult.Error -> ReplEvalResult.Error.CompileTime(compiled.compiledHistory, compiled.message, compiled.location)
is ReplCompileResult.HistoryMismatch -> ReplEvalResult.HistoryMismatch(compiled.compiledHistory, compiled.lineNo)
is ReplCompileResult.Incomplete -> ReplEvalResult.Incomplete(compiled.compiledHistory)
is ReplCompileResult.CompiledClasses -> {
val result = eval(state, compiled, scriptArgs, invokeWrapper)
val result = eval(compiled, scriptArgs, invokeWrapper)
when (result) {
is ReplEvalResult.Error,
is ReplEvalResult.HistoryMismatch,
is ReplEvalResult.Incomplete -> {
aggregatedState.apply {
lock.write {
if (state1.history.size > state2.history.size) {
state2.history.peek()?.let {
state1.history.resetTo(it.id)
}
assert(state1.history.size == state2.history.size)
}
}
}
result.completedEvalHistory.lastOrNull()?.let { compiler.resetToLine(it) }
result
}
is ReplEvalResult.ValueResult,
@@ -66,25 +56,49 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
}
}
override fun eval(state: IReplStageState<*>, compileResult: ReplCompileResult.CompiledClasses, scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult =
evaluator.eval(state, compileResult, scriptArgs, invokeWrapper)
override fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
stateLock.write {
val removedCompiledLines = compiler.resetToLine(lineNumber)
val removedEvaluatorLines = evaluator.resetToLine(lineNumber)
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult = compiler.check(state, codeLine)
removedCompiledLines.zip(removedEvaluatorLines).forEach {
if (it.first != it.second) {
throw IllegalStateException("History mismatch when resetting lines")
}
}
override fun compileToEvaluable(state: IReplStageState<*>, codeLine: ReplCodeLine, defaultScriptArgs: ScriptArgsWithTypes?): Pair<ReplCompileResult, Evaluable?> {
val compiled = compiler.compile(state, codeLine)
return removedCompiledLines
}
}
override fun resetToLine(line: ReplCodeLine): List<ReplCodeLine> = resetToLine(line.no)
override val lastEvaluatedScripts: List<EvalHistoryType> get() = evaluator.lastEvaluatedScripts
override val history: List<ReplCodeLine> get() = evaluator.history
override val currentClasspath: List<File> get() = evaluator.currentClasspath
override val compiledHistory: List<ReplCodeLine> get() = compiler.history
override val evaluatedHistory: List<ReplCodeLine> get() = evaluator.history
override fun eval(compileResult: ReplCompileResult.CompiledClasses, scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult =
evaluator.eval(compileResult, scriptArgs, invokeWrapper)
override fun check(codeLine: ReplCodeLine): ReplCheckResult = compiler.check(codeLine)
override fun compileToEvaluable(codeLine: ReplCodeLine, defaultScriptArgs: ScriptArgsWithTypes?, verifyHistory: List<ReplCodeLine>?): Pair<ReplCompileResult, Evaluable?> {
val compiled = compiler.compile(codeLine, verifyHistory)
return when (compiled) {
// TODO: seems usafe when delayed evaluation may happen after some more compileAndEval calls on the same state; check and fix or protect
is ReplCompileResult.CompiledClasses -> Pair(compiled, DelayedEvaluation(state, compiled, evaluator, defaultScriptArgs ?: fallbackScriptArgs))
is ReplCompileResult.CompiledClasses -> Pair(compiled, DelayedEvaluation(compiled, stateLock, evaluator, defaultScriptArgs ?: fallbackScriptArgs))
else -> Pair(compiled, null)
}
}
class DelayedEvaluation(private val state: IReplStageState<*>,
override val compiledCode: ReplCompileResult.CompiledClasses,
class DelayedEvaluation(override val compiledCode: ReplCompileResult.CompiledClasses,
private val stateLock: ReentrantReadWriteLock,
private val evaluator: ReplEvaluator,
private val defaultScriptArgs: ScriptArgsWithTypes?) : Evaluable {
override fun eval(scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult =
evaluator.eval(state, compiledCode, scriptArgs ?: defaultScriptArgs, invokeWrapper)
override fun eval(scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult {
return stateLock.write { evaluator.eval(compiledCode, scriptArgs ?: defaultScriptArgs, invokeWrapper) }
}
}
}
}

View File

@@ -18,55 +18,144 @@ package org.jetbrains.kotlin.cli.common.repl
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
import java.net.URLClassLoader
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
val baseClassloader: ClassLoader? = Thread.currentThread().contextClassLoader,
open class GenericReplEvaluator(baseClasspath: Iterable<File>,
baseClassloader: ClassLoader?,
protected val fallbackScriptArgs: ScriptArgsWithTypes? = null,
protected val repeatingMode: ReplRepeatingMode = ReplRepeatingMode.REPEAT_ONLY_MOST_RECENT
protected val repeatingMode: ReplRepeatingMode = ReplRepeatingMode.REPEAT_ONLY_MOST_RECENT,
protected val stateLock: ReentrantReadWriteLock = ReentrantReadWriteLock()
) : ReplEvaluator {
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = GenericReplEvaluatorState(baseClasspath, baseClassloader, lock)
private val topClassLoader: ReplClassLoader = makeReplClassLoader(baseClassloader, baseClasspath)
override fun eval(state: IReplStageState<*>,
compileResult: ReplCompileResult.CompiledClasses,
private val evaluatedHistory = ReplHistory<EvalClassWithInstanceAndLoader>()
override fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
return stateLock.write {
evaluatedHistory.resetToLine(lineNumber)
}.map { it.first }
}
override val history: List<ReplCodeLine> get() = stateLock.read { evaluatedHistory.copySources() }
override val currentClasspath: List<File> get() = stateLock.read {
evaluatedHistory.copyValues().lastOrNull()?.classLoader?.listAllUrlsAsFiles()
?: topClassLoader.listAllUrlsAsFiles()
}
private class HistoryActions(val effectiveHistory: List<EvalClassWithInstanceAndLoader>,
val verify: (compareHistory: SourceList?) -> Int?,
val addPlaceholder: (line: CompiledReplCodeLine, value: EvalClassWithInstanceAndLoader) -> Unit,
val removePlaceholder: (line: CompiledReplCodeLine) -> Boolean,
val addFinal: (line: CompiledReplCodeLine, value: EvalClassWithInstanceAndLoader) -> Unit,
val processClasses: (compileResult: ReplCompileResult.CompiledClasses) -> Pair<ClassLoader, Class<out Any>>)
private fun prependClassLoaderWithNewClasses(effectiveHistory: List<EvalClassWithInstanceAndLoader>, compileResult: ReplCompileResult.CompiledClasses): Pair<ClassLoader, Class<out Any>> {
return stateLock.write {
var mainLineClassName: String? = null
val classLoader = makeReplClassLoader(effectiveHistory.lastOrNull()?.classLoader ?: topClassLoader, compileResult.classpathAddendum)
fun classNameFromPath(path: String) = JvmClassName.byInternalName(path.removeSuffix(".class"))
fun compiledClassesNames() = compileResult.classes.map { classNameFromPath(it.path).internalName.replace('/', '.') }
val expectedClassName = compileResult.generatedClassname
compileResult.classes.filter { it.path.endsWith(".class") }
.forEach {
val className = classNameFromPath(it.path)
if (className.internalName == expectedClassName || className.internalName.endsWith("/$expectedClassName")) {
mainLineClassName = className.internalName.replace('/', '.')
}
classLoader.addClass(className, it.bytes)
}
val scriptClass = try {
classLoader.loadClass(mainLineClassName!!)
}
catch (t: Throwable) {
throw Exception("Error loading class $mainLineClassName: known classes: ${compiledClassesNames()}", t)
}
Pair(classLoader, scriptClass)
}
}
override fun eval(compileResult: ReplCompileResult.CompiledClasses,
scriptArgs: ScriptArgsWithTypes?,
invokeWrapper: InvokeWrapper?): ReplEvalResult {
state.lock.write {
val evalState = state.asState(GenericReplEvaluatorState::class.java)
val historyActor = when (repeatingMode) {
ReplRepeatingMode.NONE -> HistoryActionsForNoRepeat(evalState)
stateLock.write {
val verifyHistory = compileResult.compiledHistory.dropLast(1)
val defaultHistoryActor = HistoryActions(
effectiveHistory = evaluatedHistory.copyValues(),
verify = { line -> evaluatedHistory.firstMismatchingHistory(line) },
addPlaceholder = { line, value -> evaluatedHistory.add(line, value) },
removePlaceholder = { line -> evaluatedHistory.removeLast(line) },
addFinal = { line, value -> evaluatedHistory.add(line, value) },
processClasses = { compiled ->
prependClassLoaderWithNewClasses(evaluatedHistory.copyValues(), compiled)
})
val historyActor: HistoryActions = when (repeatingMode) {
ReplRepeatingMode.NONE -> defaultHistoryActor
ReplRepeatingMode.REPEAT_ONLY_MOST_RECENT -> {
val lastItem = evalState.history.peek()
if (lastItem == null || lastItem.id != compileResult.lineId) {
HistoryActionsForNoRepeat(evalState)
val lastItem = evaluatedHistory.lastItem()
if (lastItem == null || lastItem.first.source != compileResult.compiledCodeLine.source) {
defaultHistoryActor
}
else {
HistoryActionsForRepeatRecentOnly(evalState)
val trimmedHistory = ReplHistory(evaluatedHistory.copyAll().dropLast(1))
HistoryActions(
effectiveHistory = trimmedHistory.copyValues(),
verify = { trimmedHistory.firstMismatchingHistory(it) },
addPlaceholder = { _, _ -> NO_ACTION() },
removePlaceholder = { NO_ACTION_THAT_RETURNS(true) },
addFinal = { line, value ->
evaluatedHistory.removeLast(line)
evaluatedHistory.add(line, value)
},
processClasses = { _ ->
Pair(lastItem.second.classLoader, lastItem.second.klass.java)
})
}
}
ReplRepeatingMode.REPEAT_ANY_PREVIOUS -> {
val matchingItem = evalState.history.firstOrNull { it.id == compileResult.lineId }
if (matchingItem == null) {
HistoryActionsForNoRepeat(evalState)
if (evaluatedHistory.isEmpty() || !evaluatedHistory.contains(compileResult.compiledCodeLine.source)) {
defaultHistoryActor
}
else {
HistoryActionsForRepeatAny(evalState, matchingItem)
val historyCopy = evaluatedHistory.copyAll()
val matchingItem = historyCopy.first { it.first.source == compileResult.compiledCodeLine.source }
val trimmedHistory = ReplHistory(evaluatedHistory.copyAll().takeWhile { it != matchingItem })
HistoryActions(
effectiveHistory = trimmedHistory.copyValues(),
verify = { trimmedHistory.firstMismatchingHistory(it) },
addPlaceholder = { _, _ -> NO_ACTION() },
removePlaceholder = { NO_ACTION_THAT_RETURNS(true) },
addFinal = { line, value ->
val extraLines = evaluatedHistory.resetToLine(line)
evaluatedHistory.removeLast(line)
evaluatedHistory.add(line, value)
extraLines.forEach {
evaluatedHistory.add(it.first, it.second)
}
},
processClasses = { _ ->
Pair(matchingItem.second.classLoader, matchingItem.second.klass.java)
})
}
}
}
val firstMismatch = historyActor.firstMismatch(compileResult.previousLines.asSequence())
val firstMismatch = historyActor.verify(verifyHistory)
if (firstMismatch != null) {
return@eval ReplEvalResult.HistoryMismatch(firstMismatch.first?.id?.no ?: firstMismatch.second?.no ?: -1 /* means error? */)
return@eval ReplEvalResult.HistoryMismatch(evaluatedHistory.copySources(), firstMismatch)
}
val (classLoader, scriptClass) = try {
historyActor.processClasses(compileResult)
}
catch (e: Exception) {
return@eval ReplEvalResult.Error.Runtime(e.message ?: "unknown", e)
return@eval ReplEvalResult.Error.Runtime(evaluatedHistory.copySources(), e.message ?: "unknown", e)
}
val currentScriptArgs = scriptArgs ?: fallbackScriptArgs
@@ -81,7 +170,7 @@ open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
// TODO: try/catch ?
val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams)
historyActor.addPlaceholder(compileResult.lineId, EvalClassWithInstanceAndLoader(scriptClass.kotlin, null, classLoader, invokeWrapper))
historyActor.addPlaceholder(compileResult.compiledCodeLine, EvalClassWithInstanceAndLoader(scriptClass.kotlin, null, classLoader, invokeWrapper))
val scriptInstance =
try {
@@ -89,113 +178,33 @@ open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
else scriptInstanceConstructor.newInstance(*constructorArgs)
}
catch (e: Throwable) {
historyActor.removePlaceholder(compileResult.lineId)
historyActor.removePlaceholder(compileResult.compiledCodeLine)
// ignore everything in the stack trace until this constructor call
return@eval ReplEvalResult.Error.Runtime(renderReplStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"), e as? Exception)
return@eval ReplEvalResult.Error.Runtime(evaluatedHistory.copySources(),
renderReplStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"), e as? Exception)
}
historyActor.removePlaceholder(compileResult.lineId)
historyActor.addFinal(compileResult.lineId, EvalClassWithInstanceAndLoader(scriptClass.kotlin, scriptInstance, classLoader, invokeWrapper))
historyActor.removePlaceholder(compileResult.compiledCodeLine)
historyActor.addFinal(compileResult.compiledCodeLine, EvalClassWithInstanceAndLoader(scriptClass.kotlin, scriptInstance, classLoader, invokeWrapper))
val resultField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }
val resultValue: Any? = resultField.get(scriptInstance)
return if (compileResult.hasResult) ReplEvalResult.ValueResult(resultValue)
else ReplEvalResult.UnitResult()
return if (compileResult.hasResult) ReplEvalResult.ValueResult(evaluatedHistory.copySources(), resultValue)
else ReplEvalResult.UnitResult(evaluatedHistory.copySources())
}
}
override val lastEvaluatedScripts: List<EvalHistoryType> get() {
return stateLock.read { evaluatedHistory.copyAll() }
}
companion object {
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
}
private fun makeReplClassLoader(baseClassloader: ClassLoader?, baseClasspath: Iterable<File>) =
ReplClassLoader(URLClassLoader(baseClasspath.map { it.toURI().toURL() }.toTypedArray(), baseClassloader))
}
private open class HistoryActionsForNoRepeat(val state: GenericReplEvaluatorState) {
open val effectiveHistory: List<EvalClassWithInstanceAndLoader> get() = state.history.map { it.item }
open fun firstMismatch(other: Sequence<ILineId>): Pair<ReplHistoryRecord<EvalClassWithInstanceAndLoader>?, ILineId?>? = state.history.firstMismatch(other)
open fun addPlaceholder(lineId: ILineId, value: EvalClassWithInstanceAndLoader) { state.history.push(lineId, value) }
open fun removePlaceholder(lineId: ILineId): Boolean = state.history.verifiedPop(lineId) != null
open fun addFinal(lineId: ILineId, value: EvalClassWithInstanceAndLoader) { state.history.push(lineId, value) }
open fun processClasses(compileResult: ReplCompileResult.CompiledClasses): Pair<ClassLoader, Class<out Any>> = prependClassLoaderWithNewClasses(effectiveHistory, compileResult)
private fun prependClassLoaderWithNewClasses(effectiveHistory: List<EvalClassWithInstanceAndLoader>,
compileResult: ReplCompileResult.CompiledClasses
): Pair<ClassLoader, Class<out Any>> {
var mainLineClassName: String? = null
val classLoader = makeReplClassLoader(effectiveHistory.lastOrNull()?.classLoader ?: state.topClassLoader, compileResult.classpathAddendum)
fun classNameFromPath(path: String) = JvmClassName.byInternalName(path.removeSuffix(".class"))
fun compiledClassesNames() = compileResult.classes.map { classNameFromPath(it.path).internalName.replace('/', '.') }
val expectedClassName = compileResult.mainClassName
compileResult.classes.filter { it.path.endsWith(".class") }
.forEach {
val className = classNameFromPath(it.path)
if (className.internalName == expectedClassName || className.internalName.endsWith("/$expectedClassName")) {
mainLineClassName = className.internalName.replace('/', '.')
}
classLoader.addClass(className, it.bytes)
}
val scriptClass = try {
classLoader.loadClass(mainLineClassName!!)
}
catch (t: Throwable) {
throw Exception("Error loading class $mainLineClassName: known classes: ${compiledClassesNames()}", t)
}
return Pair(classLoader, scriptClass)
}
}
private open class HistoryActionsForRepeatRecentOnly(state: GenericReplEvaluatorState) : HistoryActionsForNoRepeat(state) {
val currentLast = state.history.peek()!!
override val effectiveHistory: List<EvalClassWithInstanceAndLoader> get() = super.effectiveHistory.dropLast(1)
override fun firstMismatch(other: Sequence<ILineId>): Pair<ReplHistoryRecord<EvalClassWithInstanceAndLoader>?, ILineId?>? =
state.history.firstMismatchFiltered(other) { it.id != currentLast.id }
override fun addPlaceholder(lineId: ILineId, value: EvalClassWithInstanceAndLoader) {}
override fun removePlaceholder(lineId: ILineId): Boolean = true
override fun addFinal(lineId: ILineId, value: EvalClassWithInstanceAndLoader) {
state.history.pop()
state.history.push(lineId, value)
}
override fun processClasses(compileResult: ReplCompileResult.CompiledClasses): Pair<ClassLoader, Class<out Any>> =
currentLast.item.classLoader to currentLast.item.klass.java
}
private open class HistoryActionsForRepeatAny(state: GenericReplEvaluatorState, val matchingLine: ReplHistoryRecord<EvalClassWithInstanceAndLoader>): HistoryActionsForNoRepeat(state) {
override val effectiveHistory: List<EvalClassWithInstanceAndLoader> get() = state.history.takeWhile { it.id != matchingLine.id }.map { it.item }
override fun firstMismatch(other: Sequence<ILineId>): Pair<ReplHistoryRecord<EvalClassWithInstanceAndLoader>?, ILineId?>? =
state.history.firstMismatchWhile(other) { it.id != matchingLine.id }
override fun addPlaceholder(lineId: ILineId, value: EvalClassWithInstanceAndLoader) {}
override fun removePlaceholder(lineId: ILineId): Boolean = true
override fun addFinal(lineId: ILineId, value: EvalClassWithInstanceAndLoader) {
val extraLines = state.history.takeLastWhile { it.id == matchingLine.id }
state.history.resetTo(lineId)
state.history.pop()
state.history.push(lineId, value)
extraLines.forEach {
state.history.push(it.id, it.item)
}
}
override fun processClasses(compileResult: ReplCompileResult.CompiledClasses): Pair<ClassLoader, Class<out Any>> =
matchingLine.item.classLoader to matchingLine.item.klass.java
}

View File

@@ -29,11 +29,10 @@ import kotlin.reflect.full.safeCast
@Suppress("unused") // used externally (kotlin.script.utils)
interface KotlinJsr223JvmInvocableScriptEngine : Invocable {
val state: IReplStageState<*> // The Invokable interface do not allow Context/Bindings substitution, so state is supplied via property
val replScriptEvaluator: ReplEvaluatorExposedInternalHistory
private fun prioritizedHistory(receiverClass: KClass<*>?, receiverInstance: Any?): List<EvalClassWithInstanceAndLoader> {
val evalState = state.asState(GenericReplEvaluatorState::class.java)
return evalState.history.map { it.item }.filter { it.instance != null }.reversed().ensureNotEmpty("no script ").let { history ->
return replScriptEvaluator.lastEvaluatedScripts.map { it.second }.filter { it.instance != null }.reversed().ensureNotEmpty("no script ").let { history ->
if (receiverInstance != null) {
val receiverKlass = receiverClass ?: receiverInstance.javaClass.kotlin
val receiverInHistory = history.find { it.instance == receiverInstance } ?:
@@ -60,10 +59,10 @@ interface KotlinJsr223JvmInvocableScriptEngine : Invocable {
private fun invokeImpl(prioritizedCallOrder: List<EvalClassWithInstanceAndLoader>, name: String, args: Array<out Any?>): Any? {
// TODO: cache the method lookups?
val (fn, mapping, invokeWrapper) = prioritizedCallOrder.asSequence().map { (klass, instance, _, invokeWrapper) ->
val candidates = klass.functions.filter { it.name == name }
candidates.findMapping(listOf(instance) + args)?.let {
Triple(it.first, it.second, invokeWrapper)
val (fn, mapping, invokeWrapper) = prioritizedCallOrder.asSequence().map { attempt ->
val candidates = attempt.klass.functions.filter { it.name == name }
candidates.findMapping(listOf<Any?>(attempt.instance) + args)?.let {
Triple(it.first, it.second, attempt.invokeWrapper)
}
}.filterNotNull().firstOrNull() ?: throw NoSuchMethodException("no suitable function '$name' found")
@@ -95,7 +94,7 @@ interface KotlinJsr223JvmInvocableScriptEngine : Invocable {
}
private fun <T : Any> proxyInterface(thiz: Any?, clasz: Class<T>?): T? {
if (state.history.size == 0) throw IllegalStateException("no script")
replScriptEvaluator.lastEvaluatedScripts.ensureNotEmpty("no script")
val priority = prioritizedHistory(thiz?.javaClass?.kotlin, thiz)
if (clasz == null) throw IllegalArgumentException("class object cannot be null")
@@ -110,6 +109,33 @@ interface KotlinJsr223JvmInvocableScriptEngine : Invocable {
}
}
private fun invokeImpl(prioritizedCallOrder: List<EvalClassWithInstanceAndLoader>, name: String, args: Array<out Any?>): Any? {
// TODO: cache the method lookups?
val (fn, mapping, invokeWrapper) = prioritizedCallOrder.asSequence().map { attempt ->
val candidates = attempt.klass.functions.filter { it.name == name }
candidates.findMapping(listOf<Any?>(attempt.instance) + args)?.let {
Triple(it.first, it.second, attempt.invokeWrapper)
}
}.filterNotNull().firstOrNull() ?: throw NoSuchMethodException("no suitable function '$name' found")
val res = try {
if (invokeWrapper != null) {
invokeWrapper.invoke {
fn.callBy(mapping)
}
}
else {
fn.callBy(mapping)
}
}
catch (e: Throwable) {
// ignore everything in the stack trace until this constructor call
throw ScriptException(renderReplStackTrace(e.cause!!, startFromMethodName = fn.name))
}
return if (fn.returnType.classifier == Unit::class) Unit else res
}
private fun Iterable<KFunction<*>>.findMapping(args: List<Any?>): Pair<KFunction<*>, Map<KParameter, Any?>>? {
for (fn in this) {
val mapping = tryCreateCallableMapping(fn, args)

View File

@@ -18,16 +18,26 @@ package org.jetbrains.kotlin.cli.common.repl
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import java.io.Reader
import java.util.concurrent.locks.ReentrantReadWriteLock
import java.util.concurrent.atomic.AtomicInteger
import javax.script.*
const val KOTLIN_SCRIPT_STATE_BINDINGS_KEY = "kotlin.script.state"
const val KOTLIN_SCRIPT_ENGINE_BINDINGS_KEY = "kotlin.script.engine"
val KOTLIN_SCRIPT_HISTORY_BINDINGS_KEY = "kotlin.script.history"
val KOTLIN_SCRIPT_LINE_NUMBER_BINDINGS_KEY = "kotlin.script.line.number"
// TODO consider additional error handling
var Bindings.kotlinScriptHistory: MutableList<ReplCodeLine>
@Suppress("UNCHECKED_CAST")
get() = getOrPut(KOTLIN_SCRIPT_HISTORY_BINDINGS_KEY, { arrayListOf<ReplCodeLine>() }) as MutableList<ReplCodeLine>
set(v) { put(KOTLIN_SCRIPT_HISTORY_BINDINGS_KEY, v) }
val Bindings.kotlinScriptLineNumber: AtomicInteger
@Suppress("UNCHECKED_CAST")
get() = getOrPut(KOTLIN_SCRIPT_LINE_NUMBER_BINDINGS_KEY, { AtomicInteger(0) }) as AtomicInteger
abstract class KotlinJsr223JvmScriptEngineBase(protected val myFactory: ScriptEngineFactory) : AbstractScriptEngine(), ScriptEngine, Compilable {
protected abstract val replCompiler: ReplCompiler
protected abstract val replEvaluator: ReplFullEvaluator
protected abstract val replCompiler: ReplCompileAction
protected abstract val replScriptEvaluator: ReplFullEvaluator
override fun eval(script: String, context: ScriptContext): Any? = compileAndEval(script, context)
@@ -37,29 +47,25 @@ abstract class KotlinJsr223JvmScriptEngineBase(protected val myFactory: ScriptEn
override fun compile(script: Reader): CompiledScript = compile(script.readText(), getContext())
override fun createBindings(): Bindings = SimpleBindings().apply { put(KOTLIN_SCRIPT_ENGINE_BINDINGS_KEY, this) }
override fun createBindings(): Bindings = SimpleBindings()
override fun getFactory(): ScriptEngineFactory = myFactory
// the parameter could be used in the future when we decide to keep state completely in the context and solve appropriate problems (now e.g. replCompiler keeps separate state)
fun nextCodeLine(context: ScriptContext, code: String) = getCurrentState(context).let { ReplCodeLine(it.getNextLineNo(), it.currentGeneration, code) }
fun nextCodeLine(@Suppress("UNUSED_PARAMETER") context: ScriptContext, code: String) = ReplCodeLine(this.context.getBindings(ScriptContext.ENGINE_SCOPE).kotlinScriptLineNumber.incrementAndGet(), code)
protected abstract fun createState(lock: ReentrantReadWriteLock = ReentrantReadWriteLock()): IReplStageState<*>
private fun getCurrentHistory(@Suppress("UNUSED_PARAMETER") context: ScriptContext) = this.context.getBindings(ScriptContext.ENGINE_SCOPE).kotlinScriptHistory
protected fun getCurrentState(context: ScriptContext) =
context.getBindings(ScriptContext.ENGINE_SCOPE)
.getOrPut(KOTLIN_SCRIPT_STATE_BINDINGS_KEY, {
// TODO: check why createBinding is not called on creating default context, so the engine is not set
context.getBindings(ScriptContext.ENGINE_SCOPE).put(KOTLIN_SCRIPT_ENGINE_BINDINGS_KEY, this@KotlinJsr223JvmScriptEngineBase)
createState()
}) as IReplStageState<*>
private fun setContextHistory(@Suppress("UNUSED_PARAMETER") context: ScriptContext, history: ArrayList<ReplCodeLine>) {
this.context.getBindings(ScriptContext.ENGINE_SCOPE).kotlinScriptHistory = history
}
open fun overrideScriptArgs(context: ScriptContext): ScriptArgsWithTypes? = null
open fun compileAndEval(script: String, context: ScriptContext): Any? {
val codeLine = nextCodeLine(context, script)
val state = getCurrentState(context)
val result = replEvaluator.compileAndEval(state, codeLine, scriptArgs = overrideScriptArgs(context))
val history = getCurrentHistory(context)
val result = replScriptEvaluator.compileAndEval(codeLine, scriptArgs = overrideScriptArgs(context), verifyHistory = history)
val ret = when (result) {
is ReplEvalResult.ValueResult -> result.value
is ReplEvalResult.UnitResult -> null
@@ -67,26 +73,29 @@ abstract class KotlinJsr223JvmScriptEngineBase(protected val myFactory: ScriptEn
is ReplEvalResult.Incomplete -> throw ScriptException("error: incomplete code")
is ReplEvalResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${result.lineNo}")
}
setContextHistory(context, ArrayList(result.completedEvalHistory))
return ret
}
open fun compile(script: String, context: ScriptContext): CompiledScript {
val codeLine = nextCodeLine(context, script)
val state = getCurrentState(context)
val history = getCurrentHistory(context)
val result = replCompiler.compile(state, codeLine)
val result = replCompiler.compile(codeLine, history)
val compiled = when (result) {
is ReplCompileResult.Error -> throw ScriptException("Error${result.locationString()}: ${result.message}")
is ReplCompileResult.Incomplete -> throw ScriptException("error: incomplete code")
is ReplCompileResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${result.lineNo}")
is ReplCompileResult.CompiledClasses -> result
}
// TODO: check if it is ok to keep compiled history in the same place as compiledEval one
setContextHistory(context, ArrayList(result.compiledHistory))
return CompiledKotlinScript(this, codeLine, compiled)
}
open fun eval(compiledScript: CompiledKotlinScript, context: ScriptContext): Any? {
val state = getCurrentState(context)
val result = try {
replEvaluator.eval(state, compiledScript.compiledData, scriptArgs = overrideScriptArgs(context))
replScriptEvaluator.eval(compiledScript.compiledData, scriptArgs = overrideScriptArgs(context))
}
catch (e: Exception) {
throw ScriptException(e)
@@ -99,6 +108,7 @@ abstract class KotlinJsr223JvmScriptEngineBase(protected val myFactory: ScriptEn
is ReplEvalResult.Incomplete -> throw ScriptException("error: incomplete code")
is ReplEvalResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${result.lineNo}")
}
setContextHistory(context, ArrayList(result.completedEvalHistory))
return ret
}

View File

@@ -20,13 +20,9 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import java.io.File
import java.io.Serializable
import java.util.*
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.reflect.KClass
const val REPL_CODE_LINE_FIRST_NO = 1
const val REPL_CODE_LINE_FIRST_GEN = 1
data class ReplCodeLine(val no: Int, val generation: Int, val code: String) : Serializable {
data class ReplCodeLine(val no: Int, val code: String) : Serializable {
companion object {
private val serialVersionUID: Long = 8228357578L
}
@@ -47,14 +43,9 @@ data class CompiledClassData(val path: String, val bytes: ByteArray) : Serializa
}
}
interface CreateReplStageStateAction {
fun createState(lock: ReentrantReadWriteLock = ReentrantReadWriteLock()): IReplStageState<*>
}
// --- check
interface ReplCheckAction {
fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult
fun check(codeLine: ReplCodeLine): ReplCheckResult
}
sealed class ReplCheckResult : Serializable {
@@ -72,24 +63,40 @@ sealed class ReplCheckResult : Serializable {
}
}
// --- compile
interface ReplResettableCodeLine {
fun resetToLine(lineNumber: Int): List<ReplCodeLine>
interface ReplCompileAction {
fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult
fun resetToLine(line: ReplCodeLine): List<ReplCodeLine> = resetToLine(line.no)
}
sealed class ReplCompileResult : Serializable {
class CompiledClasses(val lineId: LineId,
val previousLines: List<ILineId>,
val mainClassName: String,
interface ReplCodeLineHistory {
val history: List<ReplCodeLine>
}
interface ReplCombinedHistory {
val compiledHistory: List<ReplCodeLine>
val evaluatedHistory: List<ReplCodeLine>
}
interface ReplCompileAction {
fun compile(codeLine: ReplCodeLine, verifyHistory: List<ReplCodeLine>? = null): ReplCompileResult
}
sealed class ReplCompileResult(val compiledHistory: List<ReplCodeLine>) : Serializable {
class CompiledClasses(compiledHistory: List<ReplCodeLine>,
val compiledCodeLine: CompiledReplCodeLine,
val generatedClassname: String,
val classes: List<CompiledClassData>,
val hasResult: Boolean,
val classpathAddendum: List<File>) : ReplCompileResult()
val classpathAddendum: List<File>) : ReplCompileResult(compiledHistory)
class Incomplete : ReplCompileResult()
class Incomplete(compiledHistory: List<ReplCodeLine>) : ReplCompileResult(compiledHistory)
class Error(val message: String,
val location: CompilerMessageLocation = CompilerMessageLocation.NO_LOCATION) : ReplCompileResult() {
class HistoryMismatch(compiledHistory: List<ReplCodeLine>, val lineNo: Int) : ReplCompileResult(compiledHistory)
class Error(compiledHistory: List<ReplCodeLine>,
val message: String,
val location: CompilerMessageLocation = CompilerMessageLocation.NO_LOCATION) : ReplCompileResult(compiledHistory) {
override fun toString(): String = "Error(message = \"$message\""
}
@@ -98,35 +105,43 @@ sealed class ReplCompileResult : Serializable {
}
}
interface ReplCompiler : ReplCompileAction, ReplCheckAction, CreateReplStageStateAction
interface ReplCompiler : ReplResettableCodeLine, ReplCodeLineHistory, ReplCompileAction, ReplCheckAction
// --- eval
typealias EvalHistoryType = Pair<CompiledReplCodeLine, EvalClassWithInstanceAndLoader>
interface ReplEvaluatorExposedInternalHistory {
val lastEvaluatedScripts: List<EvalHistoryType>
}
interface ReplClasspath {
val currentClasspath: List<File>
}
data class EvalClassWithInstanceAndLoader(val klass: KClass<*>, val instance: Any?, val classLoader: ClassLoader, val invokeWrapper: InvokeWrapper?)
interface ReplEvalAction {
fun eval(state: IReplStageState<*>,
compileResult: ReplCompileResult.CompiledClasses,
fun eval(compileResult: ReplCompileResult.CompiledClasses,
scriptArgs: ScriptArgsWithTypes? = null,
invokeWrapper: InvokeWrapper? = null): ReplEvalResult
}
sealed class ReplEvalResult : Serializable {
class ValueResult(val value: Any?) : ReplEvalResult() {
sealed class ReplEvalResult(val completedEvalHistory: List<ReplCodeLine>) : Serializable {
class ValueResult(completedEvalHistory: List<ReplCodeLine>, val value: Any?) : ReplEvalResult(completedEvalHistory) {
override fun toString(): String = "Result: $value"
}
class UnitResult : ReplEvalResult()
class UnitResult(completedEvalHistory: List<ReplCodeLine>) : ReplEvalResult(completedEvalHistory)
class Incomplete : ReplEvalResult()
class Incomplete(completedEvalHistory: List<ReplCodeLine>) : ReplEvalResult(completedEvalHistory)
class HistoryMismatch(val lineNo: Int) : ReplEvalResult()
class HistoryMismatch(completedEvalHistory: List<ReplCodeLine>, val lineNo: Int) : ReplEvalResult(completedEvalHistory)
sealed class Error(val message: String) : ReplEvalResult() {
class Runtime(message: String, val cause: Exception? = null) : Error(message)
sealed class Error(completedEvalHistory: List<ReplCodeLine>, val message: String) : ReplEvalResult(completedEvalHistory) {
class Runtime(completedEvalHistory: List<ReplCodeLine>, message: String, val cause: Exception? = null) : Error(completedEvalHistory, message)
class CompileTime(message: String,
val location: CompilerMessageLocation = CompilerMessageLocation.NO_LOCATION) : Error(message)
class CompileTime(completedEvalHistory: List<ReplCodeLine>,
message: String,
val location: CompilerMessageLocation = CompilerMessageLocation.NO_LOCATION) : Error(completedEvalHistory, message)
override fun toString(): String = "${this::class.simpleName}Error(message = \"$message\""
}
@@ -136,44 +151,43 @@ sealed class ReplEvalResult : Serializable {
}
}
interface ReplEvaluator : ReplEvalAction, CreateReplStageStateAction
// --- compileAdnEval
interface ReplEvaluator : ReplResettableCodeLine, ReplCodeLineHistory, ReplEvaluatorExposedInternalHistory, ReplEvalAction, ReplClasspath
interface ReplAtomicEvalAction {
fun compileAndEval(state: IReplStageState<*>,
codeLine: ReplCodeLine,
fun compileAndEval(codeLine: ReplCodeLine,
scriptArgs: ScriptArgsWithTypes? = null,
verifyHistory: List<ReplCodeLine>? = null,
invokeWrapper: InvokeWrapper? = null): ReplEvalResult
}
interface ReplAtomicEvaluator : ReplAtomicEvalAction, ReplCheckAction
interface ReplAtomicEvaluator : ReplResettableCodeLine, ReplCombinedHistory, ReplEvaluatorExposedInternalHistory, ReplAtomicEvalAction, ReplCheckAction, ReplClasspath
interface ReplDelayedEvalAction {
fun compileToEvaluable(state: IReplStageState<*>,
codeLine: ReplCodeLine,
defaultScriptArgs: ScriptArgsWithTypes? = null): Pair<ReplCompileResult, Evaluable?>
fun compileToEvaluable(codeLine: ReplCodeLine, defaultScriptArgs: ScriptArgsWithTypes? = null, verifyHistory: List<ReplCodeLine>?): Pair<ReplCompileResult, Evaluable?>
}
// other
interface Evaluable {
val compiledCode: ReplCompileResult.CompiledClasses
fun eval(scriptArgs: ScriptArgsWithTypes? = null, invokeWrapper: InvokeWrapper? = null): ReplEvalResult
}
interface ReplFullEvaluator : ReplEvaluator, ReplAtomicEvaluator, ReplDelayedEvalAction
interface ReplFullEvaluator : ReplEvaluator, ReplAtomicEvaluator, ReplDelayedEvalAction, ReplCombinedHistory
/**
* Keep args and arg types together, so as a whole they are present or absent
*/
class ScriptArgsWithTypes(val scriptArgs: Array<out Any?>, val scriptArgsTypes: Array<out KClass<out Any>>) : Serializable {
init { assert(scriptArgs.size == scriptArgsTypes.size) }
companion object {
private val serialVersionUID: Long = 8529357500L
}
}
interface ScriptTemplateEmptyArgsProvider {
val defaultEmptyArgs: ScriptArgsWithTypes?
}
class SimpleScriptTemplateEmptyArgsProvider(override val defaultEmptyArgs: ScriptArgsWithTypes? = null) : ScriptTemplateEmptyArgsProvider
enum class ReplRepeatingMode {
NONE,
REPEAT_ONLY_MOST_RECENT,

View File

@@ -1,78 +0,0 @@
/*
* Copyright 2010-2017 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.cli.common.repl
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
interface ILineId : Comparable<ILineId> {
val no: Int
val generation: Int
}
data class ReplHistoryRecord<out T> (val id: ILineId, val item: T)
interface IReplStageHistory<T> : List<ReplHistoryRecord<T>> {
fun peek(): ReplHistoryRecord<T>? = lock.read { lastOrNull() }
fun push(id: ILineId, item: T)
fun pop(): ReplHistoryRecord<T>?
fun verifiedPop(id: ILineId): ReplHistoryRecord<T>? = lock.write {
if (lastOrNull()?.id == id) pop()
else null
}
fun resetTo(id: ILineId): Iterable<ILineId>
val lock: ReentrantReadWriteLock
}
interface IReplStageState<T> {
val history: IReplStageHistory<T>
val lock: ReentrantReadWriteLock
val currentGeneration: Int
fun getNextLineNo(): Int = history.peek()?.id?.no?.let { it + 1 } ?: REPL_CODE_LINE_FIRST_NO // TODO: it should be more robust downstream (e.g. use atomic)
fun <StateT : IReplStageState<*>> asState(target: Class<out StateT>): StateT =
if (target.isAssignableFrom(this::class.java)) this as StateT
else throw IllegalArgumentException("$this is not an expected instance of IReplStageState")
}
fun <T> IReplStageHistory<T>.firstMismatch(other: Sequence<ILineId>): Pair<ReplHistoryRecord<T>?, ILineId?>? =
lock.read {
iterator().asSequence().zip(other.asSequence()).firstOrNull { it.first.id != it.second }?.let { it.first to it.second }
}
fun<T> IReplStageHistory<T>.firstMismatchFiltered(other: Sequence<ILineId>, predicate: (ReplHistoryRecord<T>) -> Boolean): Pair<ReplHistoryRecord<T>?, ILineId?>? =
lock.read {
iterator().asSequence().filter(predicate).zip(other.asSequence()).firstOrNull { it.first.id != it.second }?.let { it.first to it.second }
}
fun<T> IReplStageHistory<T>.firstMismatchWhile(other: Sequence<ILineId>, predicate: (ReplHistoryRecord<T>) -> Boolean): Pair<ReplHistoryRecord<T>?, ILineId?>? =
lock.read {
iterator().asSequence().takeWhile(predicate).zip(other.asSequence()).firstOrNull { it.first.id != it.second }?.let { it.first to it.second }
}

View File

@@ -20,13 +20,13 @@ import com.google.common.base.Throwables
import java.io.File
import java.net.URLClassLoader
fun makeScriptBaseName(codeLine: ReplCodeLine) =
"Line_${codeLine.no}${if (codeLine.generation > REPL_CODE_LINE_FIRST_GEN) "_gen_${codeLine.generation}" else ""}"
fun makeScriptBaseName(codeLine: ReplCodeLine, generation: Long) =
"Line_${codeLine.no}${if (generation > 1) "_gen_$generation" else ""}"
fun renderReplStackTrace(cause: Throwable, startFromMethodName: String): String {
val newTrace = arrayListOf<StackTraceElement>()
var skip = true
for ((_, element) in cause.stackTrace.withIndex().reversed()) {
for ((i, element) in cause.stackTrace.withIndex().reversed()) {
if ("${element.className}.${element.methodName}" == startFromMethodName) {
skip = false
}
@@ -43,6 +43,10 @@ fun renderReplStackTrace(cause: Throwable, startFromMethodName: String): String
return Throwables.getStackTraceAsString(cause)
}
fun NO_ACTION(): Unit = Unit
fun <T> NO_ACTION_THAT_RETURNS(v: T): T = v
internal fun ClassLoader.listAllUrlsAsFiles(): List<File> {
val parents = generateSequence(this) { loader -> loader.parent }.filterIsInstance(URLClassLoader::class.java)
return parents.fold(emptyList<File>()) { accum, loader ->

View File

@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.utils.StringsKt;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
@@ -155,6 +156,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
}
reportUnknownExtraFlags(messageCollector, arguments);
reportUnsupportedJavaVersion(messageCollector, arguments);
GroupingMessageCollector groupingCollector = new GroupingMessageCollector(messageCollector);
@@ -232,8 +234,6 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
configuration.put(CLIConfigurationKeys.COMPILER_JAR_LOCATOR, locator);
}
configuration.put(CommonConfigurationKeys.SKIP_METADATA_VERSION_CHECK, arguments.skipMetadataVersionCheck);
setupLanguageVersionSettings(configuration, arguments);
}
@@ -275,8 +275,8 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
extraLanguageFeatures.add(coroutinesApplicabilityLevel);
}
CommonConfigurationKeysKt.setLanguageVersionSettings(
configuration,
configuration.put(
CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
new LanguageVersionSettingsImpl(
languageVersion,
ApiVersion.createByLanguageVersion(apiVersion),
@@ -288,19 +288,19 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
@Nullable
private static LanguageFeature chooseCoroutinesApplicabilityLevel(
@NotNull CompilerConfiguration configuration,
@NotNull CommonCompilerArguments arguments
) {
if (arguments.coroutinesError && !arguments.coroutinesWarn && !arguments.coroutinesEnable) {
@NotNull CompilerConfiguration configuration, @NotNull CommonCompilerArguments arguments) {
if (!arguments.coroutinesEnable && !arguments.coroutinesError && !arguments.coroutinesWarn) {
return LanguageFeature.WarnOnCoroutines;
}
else if (arguments.coroutinesError && !arguments.coroutinesWarn && !arguments.coroutinesEnable) {
return LanguageFeature.ErrorOnCoroutines;
}
else if (arguments.coroutinesWarn && !arguments.coroutinesError && !arguments.coroutinesEnable) {
return LanguageFeature.WarnOnCoroutines;
}
else if (arguments.coroutinesEnable && !arguments.coroutinesWarn && !arguments.coroutinesError) {
return LanguageFeature.DoNotWarnOnCoroutines;
}
else if (!arguments.coroutinesEnable && !arguments.coroutinesError) {
return null;
}
else {
} else {
String message = "The -Xcoroutines can only have one value";
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
CompilerMessageSeverity.ERROR, message, CompilerMessageLocation.NO_LOCATION
@@ -350,6 +350,16 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
}
}
private void reportUnsupportedJavaVersion(MessageCollector collector, A arguments) {
if (!SystemInfo.isJavaVersionAtLeast("1.8") && !arguments.noJavaVersionWarning) {
collector.report(
CompilerMessageSeverity.STRONG_WARNING,
"Running the Kotlin compiler under Java 6 or 7 is unsupported and will no longer be possible in a future update.",
CompilerMessageLocation.NO_LOCATION
);
}
}
@NotNull
protected abstract ExitCode doExecute(
@NotNull A arguments,

View File

@@ -39,8 +39,10 @@ class Usage {
for (Field field : clazz.getDeclaredFields()) {
String usage = fieldUsage(field, extraHelp);
if (usage != null) {
if (usage.contains("Xcoroutines")) {
if (coroutinesUsagePrinted) continue;
boolean coroutinesUsage = usage.contains("Xcoroutines");
if (coroutinesUsage && coroutinesUsagePrinted) {
continue;
} else if (coroutinesUsage) {
coroutinesUsagePrinted = true;
}
target.println(usage);
@@ -87,7 +89,6 @@ class Usage {
if (isXCoroutinesKey) {
sb.append(" ");
sb.append(coroutinesKeyDescription);
return sb.toString();
}
int width = OPTION_NAME_PADDING_WIDTH - 1;

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.jvm
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
@@ -31,16 +32,19 @@ import java.util.jar.Manifest
object JvmRuntimeVersionsConsistencyChecker {
private val LOG = Logger.getInstance(JvmRuntimeVersionsConsistencyChecker::class.java)
private fun <T> T?.assertNotNull(lazyMessage: () -> String): T =
this ?: lazyMessage().let { message ->
LOG.error(message)
throw AssertionError(message)
}
private fun fatal(message: String): Nothing {
LOG.error(message)
throw AssertionError(message)
}
private fun <T> T?.assertNotNull(message: () -> String): T =
if (this == null) fatal(message()) else this
private const val META_INF = "META-INF"
private const val MANIFEST_MF = "$META_INF/MANIFEST.MF"
private const val MANIFEST_KOTLIN_VERSION_ATTRIBUTE = "manifest.impl.attribute.kotlin.version"
private const val MANIFEST_KOTLIN_VERSION_VALUE = "manifest.impl.value.kotlin.version"
private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT = "manifest.impl.attribute.kotlin.runtime.component"
private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE = "manifest.impl.value.kotlin.runtime.component.core"
private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN = "manifest.impl.value.kotlin.runtime.component.main"
@@ -53,6 +57,8 @@ object JvmRuntimeVersionsConsistencyChecker {
)
private val KOTLIN_VERSION_ATTRIBUTE: String
private val CURRENT_COMPILER_VERSION: MavenComparableVersion
private val KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE: String
private val KOTLIN_RUNTIME_COMPONENT_CORE: String
private val KOTLIN_RUNTIME_COMPONENT_MAIN: String
@@ -70,6 +76,18 @@ object JvmRuntimeVersionsConsistencyChecker {
KOTLIN_VERSION_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_VERSION_ATTRIBUTE)
.assertNotNull { "$MANIFEST_KOTLIN_VERSION_ATTRIBUTE not found in kotlinManifest.properties" }
CURRENT_COMPILER_VERSION = run {
val kotlinVersionString = manifestProperties.getProperty(MANIFEST_KOTLIN_VERSION_VALUE)
.assertNotNull { "$MANIFEST_KOTLIN_VERSION_VALUE not found in kotlinManifest.properties" }
MavenComparableVersion(kotlinVersionString)
}
if (CURRENT_COMPILER_VERSION != ApiVersion.LATEST.version) {
fatal("Kotlin compiler version $CURRENT_COMPILER_VERSION in kotlinManifest.properties doesn't match ${ApiVersion.LATEST}")
}
KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT)
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT not found in kotlinManifest.properties" }
KOTLIN_RUNTIME_COMPONENT_CORE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE)
@@ -100,8 +118,8 @@ object JvmRuntimeVersionsConsistencyChecker {
val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots)
if (runtimeJarsInfo.jars.isEmpty()) return
val languageVersionSettings = configuration.languageVersionSettings
val apiVersion = languageVersionSettings.apiVersion.version
val languageVersionSettings = configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)
val apiVersion = languageVersionSettings?.apiVersion?.version ?: CURRENT_COMPILER_VERSION
val consistency = checkCompilerClasspathConsistency(messageCollector, apiVersion, runtimeJarsInfo)
if (consistency is ClasspathConsistency.InconsistentWithApiVersion) {
@@ -119,20 +137,29 @@ object JvmRuntimeVersionsConsistencyChecker {
val actualApi = ApiVersion.parse(actualRuntimeVersion.toString())
if (actualApi != null) {
val inferredApiVersion =
if (@Suppress("DEPRECATION") languageVersionSettings.isApiVersionExplicit)
languageVersionSettings.apiVersion
else
minOf(languageVersionSettings.apiVersion, actualApi)
val newSettings = if (languageVersionSettings == null) {
LanguageVersionSettingsImpl(
LanguageVersionSettingsImpl.DEFAULT.languageVersion,
actualApi,
listOf(LanguageFeature.WarnOnCoroutines)
)
}
else {
val inferredApiVersion =
if (@Suppress("DEPRECATION") languageVersionSettings.isApiVersionExplicit)
languageVersionSettings.apiVersion
else
minOf(languageVersionSettings.apiVersion, actualApi)
// "minOf" is needed in case when API version was inferred from language version and it's older than actualApi.
// For example, in "kotlinc-1.2 -language-version 1.0 -cp kotlin-runtime-1.1.jar" we should still infer API = 1.0
val newSettings = LanguageVersionSettingsImpl(
languageVersionSettings.languageVersion,
inferredApiVersion,
languageVersionSettings.additionalFeatures,
isApiVersionExplicit = false
)
// "minOf" is needed in case when API version was inferred from language version and it's older than actualApi.
// For example, in "kotlinc-1.2 -language-version 1.0 -cp kotlin-runtime-1.1.jar" we should still infer API = 1.0
LanguageVersionSettingsImpl(
languageVersionSettings.languageVersion,
inferredApiVersion,
languageVersionSettings.additionalFeatures,
isApiVersionExplicit = false
)
}
messageCollector.issue(null, "Old runtime has been found in the classpath. " +
"Initial language version settings: $languageVersionSettings. " +
@@ -201,10 +228,10 @@ object JvmRuntimeVersionsConsistencyChecker {
}
private fun checkNotNewerThanCompiler(messageCollector: MessageCollector, jar: KotlinLibraryFile): Boolean {
if (jar.version > ApiVersion.LATEST.version) {
if (jar.version > CURRENT_COMPILER_VERSION) {
messageCollector.issue(
jar.file,
"Runtime JAR file has version ${jar.version} which is newer than compiler version ${ApiVersion.LATEST.version}",
"Runtime JAR file has version ${jar.version} which is newer than compiler version $CURRENT_COMPILER_VERSION",
CompilerMessageSeverity.ERROR
)
return true

View File

@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.compiler.plugin.PluginCliOptionProcessingException
import org.jetbrains.kotlin.compiler.plugin.cliPluginUsageString
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
import org.jetbrains.kotlin.script.StandardScriptDefinition
@@ -113,6 +114,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
return ExitCode.OK
}
if (arguments.skipMetadataVersionCheck) {
JvmMetadataVersion.skipCheck = true
}
if (arguments.includeRuntime) {
configuration.put(JVMConfigurationKeys.INCLUDE_RUNTIME, true)
}

View File

@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
import org.jetbrains.kotlin.load.kotlin.PackageParts
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import java.io.EOFException
class JvmPackagePartProvider(
@@ -33,8 +32,6 @@ class JvmPackagePartProvider(
) : PackagePartProvider {
private data class ModuleMappingInfo(val root: VirtualFile, val mapping: ModuleMapping)
private val deserializationConfiguration = CompilerDeserializationConfiguration(env.configuration)
private val notLoadedRoots by lazy(LazyThreadSafetyMode.NONE) {
env.configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS)
.filterIsInstance<JvmClasspathRoot>()
@@ -99,7 +96,7 @@ class JvmPackagePartProvider(
val moduleFiles = metaInf.children.filter { it.name.endsWith(ModuleMapping.MAPPING_FILE_EXT) }
for (moduleFile in moduleFiles) {
val mapping = try {
ModuleMapping.create(moduleFile.contentsToByteArray(), moduleFile.toString(), deserializationConfiguration)
ModuleMapping.create(moduleFile.contentsToByteArray(), moduleFile.toString())
}
catch (e: EOFException) {
throw RuntimeException("Error on reading package parts for '$packageFqName' package in '$moduleFile', " +

View File

@@ -67,8 +67,7 @@ import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2010-2017 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.cli.jvm.repl
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.KotlinScriptExternalDependencies
import java.util.concurrent.locks.ReentrantReadWriteLock
class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory<ScriptDescriptor>(state.lock) {
override fun resetTo(id: ILineId): Iterable<ILineId> {
val removedCompiledLines = super.resetTo(id)
val removedAnalyzedLines = state.analyzerEngine.resetToLine(id.no)
removedCompiledLines.zip(removedAnalyzedLines).forEach {
if (it.first != LineId(it.second)) {
throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}")
}
}
return removedCompiledLines
}
}
abstract class GenericReplCheckerState: IReplStageState<ScriptDescriptor> {
// "line" - is the unit of evaluation here, could in fact consists of several character lines
class LineState(
val codeLine: ReplCodeLine,
val psiFile: KtFile,
val errorHolder: DiagnosticMessageHolder)
var lastLineState: LineState? = null // for transferring state to the compiler in most typical case
}
class GenericReplCompilerState(environment: KotlinCoreEnvironment, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : IReplStageState<ScriptDescriptor>, GenericReplCheckerState() {
override val history = ReplCompilerStageHistory(this)
override val currentGeneration: Int get() = (history as BasicReplStageHistory<*>).currentGeneration.get()
val analyzerEngine = ReplCodeAnalyzer(environment)
var lastDependencies: KotlinScriptExternalDependencies? = null
}

View File

@@ -22,31 +22,66 @@ import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import java.io.File
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
// TODO: remove if unused after switching old repl to the new infrastruct
open class GenericRepl protected constructor(
disposable: Disposable,
scriptDefinition: KotlinScriptDefinition,
compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector,
baseClassloader: ClassLoader?,
protected val fallbackScriptArgs: ScriptArgsWithTypes? = null,
protected val repeatingMode: ReplRepeatingMode = ReplRepeatingMode.NONE
protected val fallbackScriptArgs: ScriptArgsWithTypes?,
protected val repeatingMode: ReplRepeatingMode = ReplRepeatingMode.NONE,
protected val stateLock: ReentrantReadWriteLock
) : ReplCompiler, ReplEvaluator, ReplAtomicEvaluator {
constructor (
disposable: Disposable,
scriptDefinition: KotlinScriptDefinition,
compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector,
baseClassloader: ClassLoader?,
fallbackScriptArgs: ScriptArgsWithTypes? = null
) : this(disposable, scriptDefinition, compilerConfiguration, messageCollector, baseClassloader, fallbackScriptArgs, stateLock = ReentrantReadWriteLock())
protected val compiler: ReplCompiler by lazy { GenericReplCompiler(disposable, scriptDefinition, compilerConfiguration, messageCollector) }
protected val evaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(compiler, compilerConfiguration.jvmClasspathRoots, baseClassloader, fallbackScriptArgs, repeatingMode) }
protected val compiler: ReplCompiler by lazy { GenericReplCompiler(disposable, scriptDefinition, compilerConfiguration, messageCollector, stateLock) }
protected val evaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(compiler, compilerConfiguration.jvmClasspathRoots, baseClassloader, fallbackScriptArgs, repeatingMode, stateLock) }
protected var codeLineNumber = AtomicInteger(0)
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = AggregatedReplStageState(compiler.createState(lock), evaluator.createState(lock), lock)
override fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
return evaluator.resetToLine(lineNumber)
}
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult = compiler.check(state, codeLine)
override fun resetToLine(line: ReplCodeLine): List<ReplCodeLine> {
return evaluator.resetToLine(line)
}
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult = compiler.compile(state, codeLine)
override val history: List<ReplCodeLine> get() = evaluator.history
override val compiledHistory: List<ReplCodeLine> get() = compiler.history
override val evaluatedHistory: List<ReplCodeLine> get() = evaluator.history
override fun eval(state: IReplStageState<*>, compileResult: ReplCompileResult.CompiledClasses, scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult =
evaluator.eval(state, compileResult, scriptArgs, invokeWrapper)
override val currentClasspath: List<File>
get() = evaluator.currentClasspath
override fun compileAndEval(state: IReplStageState<*>, codeLine: ReplCodeLine, scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult =
evaluator.compileAndEval(state, codeLine, scriptArgs, invokeWrapper)
override val lastEvaluatedScripts: List<EvalHistoryType>
get() = evaluator.lastEvaluatedScripts
override fun check(codeLine: ReplCodeLine): ReplCheckResult {
return compiler.check(codeLine)
}
override fun compile(codeLine: ReplCodeLine, verifyHistory: List<ReplCodeLine>?): ReplCompileResult {
return compiler.compile(codeLine, verifyHistory)
}
override fun eval(compileResult: ReplCompileResult.CompiledClasses, scriptArgs: ScriptArgsWithTypes?, invokeWrapper: InvokeWrapper?): ReplEvalResult {
return evaluator.eval(compileResult, scriptArgs, invokeWrapper)
}
override fun compileAndEval(codeLine: ReplCodeLine, scriptArgs: ScriptArgsWithTypes?, verifyHistory: List<ReplCodeLine>?, invokeWrapper: InvokeWrapper?): ReplEvalResult {
return evaluator.compileAndEval(codeLine, scriptArgs, verifyHistory, invokeWrapper)
}
fun nextCodeLine(code: String) = ReplCodeLine(codeLineNumber.incrementAndGet(), code)
}

View File

@@ -21,6 +21,7 @@ package org.jetbrains.kotlin.cli.jvm.repl
import org.jetbrains.kotlin.cli.common.repl.CompiledReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ReplHistory
import org.jetbrains.kotlin.cli.common.repl.ReplResettableCodeLine
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
@@ -42,18 +43,23 @@ import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
import org.jetbrains.kotlin.resolve.scopes.utils.replaceImportingScopes
import org.jetbrains.kotlin.script.ScriptPriorities
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
class GenericReplAnalyzer(environment: KotlinCoreEnvironment,
protected val stateLock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : ReplResettableCodeLine {
private val topDownAnalysisContext: TopDownAnalysisContext
private val topDownAnalyzer: LazyTopDownAnalyzer
private val resolveSession: ResolveSession
private val scriptDeclarationFactory: ScriptMutableDeclarationProviderFactory
private val replState = ResettableAnalyzerState()
private val replState = ResettableReplState()
val module: ModuleDescriptorImpl
get() = stateLock.read { field }
val trace: BindingTraceContext = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
get() = stateLock.read { field }
init {
// Module source scope is empty because all binary classes are in the dependency module, and all source classes are guaranteed
@@ -88,15 +94,21 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
}
}
fun resetToLine(lineNumber: Int): List<ReplCodeLine> = replState.resetToLine(lineNumber)
override fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
return stateLock.write { replState.resetToLine(lineNumber) }
}
override fun resetToLine(line: ReplCodeLine): List<ReplCodeLine> = resetToLine(line.no)
fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
topDownAnalysisContext.scripts.clear()
trace.clearDiagnostics()
return stateLock.write {
topDownAnalysisContext.scripts.clear()
trace.clearDiagnostics()
psiFile.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, codeLine.no)
psiFile.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, codeLine.no)
return doAnalyze(psiFile, codeLine)
doAnalyze(psiFile, codeLine)
}
}
private fun doAnalyze(linePsi: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
@@ -167,8 +179,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
}
// TODO: merge with org.jetbrains.kotlin.resolve.repl.ReplState when switching to new REPL infrastruct everywhere
// TODO: review it's place in the extracted state infrastruct (now the analyzer itself is a part of the state
class ResettableAnalyzerState {
class ResettableReplState {
private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>()
private val submittedLines = hashMapOf<KtFile, LineInfo>()
@@ -178,6 +189,8 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
return removed.map { it.first }
}
fun resetToLine(line: ReplCodeLine): List<ReplCodeLine> = resetToLine(line.no)
fun submitLine(ktFile: KtFile, codeLine: ReplCodeLine) {
val line = LineInfo.SubmittedLine(ktFile, successfulLines.lastValue())
submittedLines[ktFile] = line

View File

@@ -26,9 +26,12 @@ import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.makeScriptBaseName
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplTerminalDiagnosticMessageHolder
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -37,6 +40,8 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
const val KOTLIN_REPL_JVM_TARGET_PROPERTY = "kotlin.repl.jvm.target"
@@ -45,9 +50,9 @@ open class GenericReplChecker(
disposable: Disposable,
val scriptDefinition: KotlinScriptDefinition,
val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
) : ReplCheckAction {
messageCollector: MessageCollector,
protected val stateLock: ReentrantReadWriteLock = ReentrantReadWriteLock()
) {
internal val environment = run {
compilerConfiguration.apply {
add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition)
@@ -65,12 +70,21 @@ open class GenericReplChecker(
private val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
internal fun createDiagnosticHolder() = ReplTerminalDiagnosticMessageHolder()
// "line" - is the unit of evaluation here, could in fact consists of several character lines
internal class LineState(
val codeLine: ReplCodeLine,
val psiFile: KtFile,
val errorHolder: DiagnosticMessageHolder)
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult {
state.lock.write {
val checkerState = state.asState(GenericReplCheckerState::class.java)
val scriptFileName = makeScriptBaseName(codeLine)
private var _lineState: LineState? = null
internal val lineState: LineState? get() = stateLock.read { _lineState }
fun createDiagnosticHolder() = ReplTerminalDiagnosticMessageHolder()
fun check(codeLine: ReplCodeLine, generation: Long): ReplCheckResult {
stateLock.write {
val scriptFileName = makeScriptBaseName(codeLine, generation)
val virtualFile =
LightVirtualFile("$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, StringUtil.convertLineSeparators(codeLine.code)).apply {
charset = CharsetToolkit.UTF8_CHARSET
@@ -83,7 +97,7 @@ open class GenericReplChecker(
val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorHolder)
if (!syntaxErrorReport.isHasErrors) {
checkerState.lastLineState = GenericReplCheckerState.LineState(codeLine, psiFile, errorHolder)
_lineState = LineState(codeLine, psiFile, errorHolder)
}
return when {

View File

@@ -26,82 +26,115 @@ import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.script.KotlinScriptExternalDependencies
import java.io.File
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
// WARNING: not thread safe, assuming external synchronization
open class GenericReplCompiler(disposable: Disposable,
protected val scriptDefinition: KotlinScriptDefinition,
protected val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
) : ReplCompiler {
messageCollector: MessageCollector,
protected val stateLock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : ReplCompiler {
private val checker = GenericReplChecker(disposable, scriptDefinition, compilerConfiguration, messageCollector, stateLock)
private val checker = GenericReplChecker(disposable, scriptDefinition, compilerConfiguration, messageCollector)
private val analyzerEngine = GenericReplAnalyzer(checker.environment, stateLock)
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = GenericReplCompilerState(checker.environment, lock)
private var lastDependencies: KotlinScriptExternalDependencies? = null
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult = checker.check(state, codeLine)
private val descriptorsHistory = ReplHistory<ScriptDescriptor>()
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
state.lock.write {
val compilerState = state.asState(GenericReplCompilerState::class.java)
private val generation = AtomicLong(1)
override fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
return stateLock.write {
generation.incrementAndGet()
val removedCompiledLines = descriptorsHistory.resetToLine(lineNumber)
val removedAnalyzedLines = analyzerEngine.resetToLine(lineNumber)
removedCompiledLines.zip(removedAnalyzedLines).forEach {
if (it.first.first != it.second) {
throw IllegalStateException("History mismatch when resetting lines")
}
}
removedCompiledLines
}.map { it.first }
}
override val history: List<ReplCodeLine> get() = stateLock.read { descriptorsHistory.copySources() }
override fun check(codeLine: ReplCodeLine): ReplCheckResult = stateLock.read {
return checker.check(codeLine, generation.get())
}
override fun compile(codeLine: ReplCodeLine, verifyHistory: List<ReplCodeLine>?): ReplCompileResult {
stateLock.write {
val firstMismatch = descriptorsHistory.firstMismatchingHistory(verifyHistory)
if (firstMismatch != null) {
return@compile ReplCompileResult.HistoryMismatch(descriptorsHistory.copySources(), firstMismatch)
}
val currentGeneration = generation.get()
val (psiFile, errorHolder) = run {
if (compilerState.lastLineState == null || compilerState.lastLineState!!.codeLine != codeLine) {
val res = checker.check(state, codeLine)
if (checker.lineState == null || checker.lineState!!.codeLine != codeLine) {
val res = checker.check(codeLine, currentGeneration)
when (res) {
is ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete()
is ReplCheckResult.Error -> return@compile ReplCompileResult.Error(res.message, res.location)
is ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete(descriptorsHistory.copySources())
is ReplCheckResult.Error -> return@compile ReplCompileResult.Error(descriptorsHistory.copySources(), res.message, res.location)
is ReplCheckResult.Ok -> {} // continue
}
}
Pair(compilerState.lastLineState!!.psiFile, compilerState.lastLineState!!.errorHolder)
Pair(checker.lineState!!.psiFile, checker.lineState!!.errorHolder)
}
val newDependencies = scriptDefinition.getDependenciesFor(psiFile, checker.environment.project, compilerState.lastDependencies)
val newDependencies = scriptDefinition.getDependenciesFor(psiFile, checker.environment.project, lastDependencies)
var classpathAddendum: List<File>? = null
if (compilerState.lastDependencies != newDependencies) {
compilerState.lastDependencies = newDependencies
if (lastDependencies != newDependencies) {
lastDependencies = newDependencies
classpathAddendum = newDependencies?.let { checker.environment.updateClasspath(it.classpath.map(::JvmClasspathRoot)) }
}
val analysisResult = compilerState.analyzerEngine.analyzeReplLine(psiFile, codeLine)
val analysisResult = analyzerEngine.analyzeReplLine(psiFile, codeLine)
AnalyzerWithCompilerReport.reportDiagnostics(analysisResult.diagnostics, errorHolder)
val scriptDescriptor = when (analysisResult) {
is ReplCodeAnalyzer.ReplLineAnalysisResult.WithErrors -> return ReplCompileResult.Error(errorHolder.renderedDiagnostics)
is ReplCodeAnalyzer.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor
is GenericReplAnalyzer.ReplLineAnalysisResult.WithErrors -> return ReplCompileResult.Error(descriptorsHistory.copySources(), errorHolder.renderedDiagnostics)
is GenericReplAnalyzer.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor
else -> error("Unexpected result ${analysisResult.javaClass}")
}
val generationState = GenerationState(
val state = GenerationState(
psiFile.project,
ClassBuilderFactories.binaries(false),
compilerState.analyzerEngine.module,
compilerState.analyzerEngine.trace.bindingContext,
analyzerEngine.module,
analyzerEngine.trace.bindingContext,
listOf(psiFile),
compilerConfiguration
)
generationState.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
generationState.replSpecific.earlierScriptsForReplInterpreter = compilerState.history.map { it.item }
generationState.beforeCompile()
state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
state.replSpecific.earlierScriptsForReplInterpreter = descriptorsHistory.copyValues()
state.beforeCompile()
KotlinCodegenFacade.generatePackage(
generationState,
psiFile.script!!.containingKtFile.packageFqName,
setOf(psiFile.script!!.containingKtFile),
state,
psiFile.script!!.getContainingKtFile().packageFqName,
setOf(psiFile.script!!.getContainingKtFile()),
org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION)
val generatedClassname = makeScriptBaseName(codeLine)
compilerState.history.push(LineId(codeLine), scriptDescriptor)
val generatedClassname = makeScriptBaseName(codeLine, currentGeneration)
val compiledCodeLine = CompiledReplCodeLine(generatedClassname, codeLine)
descriptorsHistory.add(compiledCodeLine, scriptDescriptor)
return ReplCompileResult.CompiledClasses(LineId(codeLine),
compilerState.history.map { it.id },
return ReplCompileResult.CompiledClasses(descriptorsHistory.copySources(),
compiledCodeLine,
generatedClassname,
generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) },
generationState.replSpecific.hasResult,
classpathAddendum ?: emptyList())
state.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) },
state.replSpecific.hasResult,
classpathAddendum ?: emptyList())
}
}

View File

@@ -64,7 +64,7 @@ class ReplInterpreter(
}
private val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
private val analyzerEngine = ReplCodeAnalyzer(environment)
private val analyzerEngine = GenericReplAnalyzer(environment)
fun eval(line: String): LineResult {
++lineNumber
@@ -98,11 +98,11 @@ class ReplInterpreter(
return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
}
val analysisResult = analyzerEngine.analyzeReplLine(psiFile, ReplCodeLine(lineNumber, 0, "fake line"))
val analysisResult = analyzerEngine.analyzeReplLine(psiFile, ReplCodeLine(lineNumber, "fake line"))
AnalyzerWithCompilerReport.reportDiagnostics(analysisResult.diagnostics, errorHolder)
val scriptDescriptor = when (analysisResult) {
is ReplCodeAnalyzer.ReplLineAnalysisResult.WithErrors -> return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
is ReplCodeAnalyzer.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor
is GenericReplAnalyzer.ReplLineAnalysisResult.WithErrors -> return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
is GenericReplAnalyzer.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor
else -> error("Unexpected result ${analysisResult.javaClass}")
}
@@ -185,7 +185,7 @@ class ReplInterpreter(
private fun renderStackTrace(cause: Throwable, startFromMethodName: String): String {
val newTrace = arrayListOf<StackTraceElement>()
var skip = true
for ((_, element) in cause.stackTrace.withIndex().reversed()) {
for ((i, element) in cause.stackTrace.withIndex().reversed()) {
if ("${element.className}.${element.methodName}" == startFromMethodName) {
skip = false
}
@@ -214,8 +214,8 @@ class ReplInterpreter(
state.beforeCompile()
KotlinCodegenFacade.generatePackage(
state,
script.containingKtFile.packageFqName,
setOf(script.containingKtFile),
script.getContainingKtFile().packageFqName,
setOf(script.getContainingKtFile()),
errorHandler
)
}

View File

@@ -80,10 +80,9 @@ open class CompilerCallbackServicesFacadeServer(
override fun lookupTracker_isDoNothing(): Boolean = lookupTracker_isDoNothing
override fun compilationCanceledStatus_checkCanceled(): Void? {
override fun compilationCanceledStatus_checkCanceled() {
try {
compilationCanceledStatus!!.checkCanceled()
return null
}
catch (e: Exception) {
// avoid passing exceptions that may have different serialVersionUID on across rmi border

View File

@@ -0,0 +1,154 @@
/*
* 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.daemon.client
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.daemon.common.CompileService
import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
import java.io.File
import java.io.InputStream
import java.io.OutputStream
// TODO: reduce number of ports used then SOCKET_ANY_FREE_PORT is passed (same problem with other calls)
open class KotlinRemoteReplClientBase(
protected val compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
templateClasspath: List<File>,
templateClassName: String,
scriptArgs: Array<out Any?>? = null,
scriptArgsTypes: Array<out Class<out Any>>? = null,
compilerMessagesOutputStream: OutputStream = System.err,
evalOutputStream: OutputStream? = null,
evalErrorStream: OutputStream? = null,
evalInputStream: InputStream? = null,
port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null
) {
val sessionId = compileService.leaseReplSession(
clientAliveFlagFile?.absolutePath,
targetPlatform,
CompilerCallbackServicesFacadeServer(port = port),
templateClasspath,
templateClassName,
scriptArgs,
scriptArgsTypes,
RemoteOutputStreamServer(compilerMessagesOutputStream, port),
evalOutputStream?.let { RemoteOutputStreamServer(it, port) },
evalErrorStream?.let { RemoteOutputStreamServer(it, port) },
evalInputStream?.let { RemoteInputStreamServer(it, port) },
operationsTracer
).get()
// dispose should be called at the end of the repl lifetime to free daemon repl session and appropriate resources
open fun dispose() {
try {
compileService.releaseReplSession(sessionId)
}
catch (ex: java.rmi.RemoteException) {
// assuming that communication failed and daemon most likely is already down
}
}
}
class KotlinRemoteReplCompiler(
compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
templateClasspath: List<File>,
templateClassName: String,
compilerMessagesOutputStream: OutputStream,
port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null
) : KotlinRemoteReplClientBase(
compileService = compileService,
clientAliveFlagFile = clientAliveFlagFile,
targetPlatform = targetPlatform,
templateClasspath = templateClasspath,
templateClassName = templateClassName,
compilerMessagesOutputStream = compilerMessagesOutputStream,
evalOutputStream = null,
evalErrorStream = null,
evalInputStream = null,
port = port,
operationsTracer = operationsTracer
), ReplCompiler, ReplCheckAction {
override fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
return emptyList() // TODO: not implemented, no current need
}
override val history: List<ReplCodeLine>
get() = emptyList() // TODO: not implemented, no current need
override fun check(codeLine: ReplCodeLine): ReplCheckResult {
return compileService.remoteReplLineCheck(sessionId, codeLine).get()
}
override fun compile(codeLine: ReplCodeLine, verifyHistory: List<ReplCodeLine>?): ReplCompileResult {
return compileService.remoteReplLineCompile(sessionId, codeLine, verifyHistory).get()
}
}
// TODO: consider removing daemon eval completely - it is not required now and has questionable security. This will simplify daemon interface as well
class KotlinRemoteReplEvaluator(
compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
templateClasspath: List<File>,
templateClassName: String,
scriptArgs: Array<out Any?>? = null,
scriptArgsTypes: Array<out Class<out Any>>? = null,
compilerMessagesOutputStream: OutputStream,
evalOutputStream: OutputStream?,
evalErrorStream: OutputStream?,
evalInputStream: InputStream?,
port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null
) : KotlinRemoteReplClientBase(
compileService = compileService,
clientAliveFlagFile = clientAliveFlagFile,
targetPlatform = targetPlatform,
templateClasspath = templateClasspath,
templateClassName = templateClassName,
scriptArgs = scriptArgs,
scriptArgsTypes = scriptArgsTypes,
compilerMessagesOutputStream = compilerMessagesOutputStream,
evalOutputStream = evalOutputStream,
evalErrorStream = evalErrorStream,
evalInputStream = evalInputStream,
port = port,
operationsTracer = operationsTracer
), ReplAtomicEvalAction, ReplEvaluatorExposedInternalHistory, ReplCheckAction {
override val lastEvaluatedScripts: List<EvalHistoryType> = emptyList() // not implemented, no need so far
// TODO: invokeWrapper is ignored here, and in the daemon the session wrapper is used instead; So consider to make it per call (avoid performance penalties though)
// TODO: scriptArgs are ignored here, they should be passed through
override fun compileAndEval(codeLine: ReplCodeLine,
scriptArgs: ScriptArgsWithTypes?,
verifyHistory: List<ReplCodeLine>?,
invokeWrapper: InvokeWrapper?): ReplEvalResult {
return compileService.remoteReplLineEval(sessionId, codeLine, verifyHistory).get()
}
override fun check(codeLine: ReplCodeLine): ReplCheckResult {
return compileService.remoteReplLineCheck(sessionId, codeLine).get()
}
}

View File

@@ -1,71 +0,0 @@
/*
* 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.daemon.client
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.daemon.common.*
import java.io.File
import java.util.concurrent.locks.ReentrantReadWriteLock
// TODO: reduce number of ports used then SOCKET_ANY_FREE_PORT is passed (same problem with other calls)
open class KotlinRemoteReplCompilerClient(
protected val compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
args: Array<out String>,
messageCollector: MessageCollector,
templateClasspath: List<File>,
templateClassName: String,
port: Int = SOCKET_ANY_FREE_PORT
) : ReplCompiler {
val services = BasicCompilerServicesWithResultsFacadeServer(messageCollector, null, port)
val sessionId = compileService.leaseReplSession(
clientAliveFlagFile?.absolutePath,
args,
CompilationOptions(
CompilerMode.NON_INCREMENTAL_COMPILER,
targetPlatform,
arrayOf(ReportCategory.COMPILER_MESSAGE.code, ReportCategory.DAEMON_MESSAGE.code, ReportCategory.EXCEPTION.code, ReportCategory.OUTPUT_MESSAGE.code),
ReportSeverity.INFO.code,
emptyArray()),
services,
templateClasspath,
templateClassName
).get()
// dispose should be called at the end of the repl lifetime to free daemon repl session and appropriate resources
open fun dispose() {
try {
compileService.releaseReplSession(sessionId)
}
catch (ex: java.rmi.RemoteException) {
// assuming that communication failed and daemon most likely is already down
}
}
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> =
RemoteReplCompilerState(compileService.replCreateState(sessionId).get(), lock)
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult =
compileService.replCheck(sessionId, state.asState(RemoteReplCompilerState::class.java).replStateFacade.getId(), codeLine).get()
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult =
compileService.replCompile(sessionId, state.asState(RemoteReplCompilerState::class.java).replStateFacade.getId(), codeLine).get()
}

View File

@@ -1,56 +0,0 @@
/*
* Copyright 2010-2017 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.daemon.client
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.daemon.common.ReplStateFacade
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
// NOTE: the lock is local
// TODO: verify that locla lock doesn't lead to any synch problems
class RemoteReplCompilerStateHistory(private val state: RemoteReplCompilerState) : IReplStageHistory<Unit>, AbstractList<ReplHistoryRecord<Unit>>() {
override val size: Int
get() = state.replStateFacade.getHistorySize()
override fun get(index: Int): ReplHistoryRecord<Unit> = ReplHistoryRecord(state.replStateFacade.historyGet(index), Unit)
override fun push(id: ILineId, item: Unit) {
throw NotImplementedError("push to remote history is not supported")
}
override fun pop(): ReplHistoryRecord<Unit>? {
throw NotImplementedError("pop from remote history is not supported")
}
override fun resetTo(id: ILineId): Iterable<ILineId> = state.replStateFacade.historyResetTo(id).apply {
if (isNotEmpty()) {
currentGeneration.incrementAndGet()
}
}
val currentGeneration = AtomicInteger(REPL_CODE_LINE_FIRST_GEN)
override val lock: ReentrantReadWriteLock get() = state.lock
}
class RemoteReplCompilerState(internal val replStateFacade: ReplStateFacade, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : IReplStageState<Unit> {
override val currentGeneration: Int get() = (history as RemoteReplCompilerStateHistory).currentGeneration.get()
override val history: IReplStageHistory<Unit> = RemoteReplCompilerStateHistory(this)
}

View File

@@ -16,7 +16,10 @@
package org.jetbrains.kotlin.daemon.common
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
import java.io.File
import java.io.Serializable
import java.rmi.Remote
@@ -35,6 +38,8 @@ interface CompileService : Remote {
METADATA
}
companion object {
val NO_SESSION: Int = 0
}
@@ -102,7 +107,6 @@ interface CompileService : Remote {
// TODO: consider adding async version of shutdown and release
@Deprecated("The usages should be replaced with `compile` method", ReplaceWith("compile"))
@Throws(RemoteException::class)
fun remoteCompile(
sessionId: Int,
@@ -115,7 +119,6 @@ interface CompileService : Remote {
operationsTracer: RemoteOperationsTracer?
): CallResult<Int>
@Deprecated("The usages should be replaced with `compile` method", ReplaceWith("compile"))
@Throws(RemoteException::class)
fun remoteIncrementalCompile(
sessionId: Int,
@@ -140,7 +143,6 @@ interface CompileService : Remote {
@Throws(RemoteException::class)
fun clearJarCache()
@Deprecated("The usages should be replaced with other `leaseReplSession` method", ReplaceWith("leaseReplSession"))
@Throws(RemoteException::class)
fun leaseReplSession(
aliveFlagPath: String?,
@@ -160,14 +162,12 @@ interface CompileService : Remote {
@Throws(RemoteException::class)
fun releaseReplSession(sessionId: Int): CallResult<Nothing>
@Deprecated("The usages should be replaced with `replCheck` method", ReplaceWith("replCheck"))
@Throws(RemoteException::class)
fun remoteReplLineCheck(
sessionId: Int,
codeLine: ReplCodeLine
): CallResult<ReplCheckResult>
@Deprecated("The usages should be replaced with `replCompile` method", ReplaceWith("replCompile"))
@Throws(RemoteException::class)
fun remoteReplLineCompile(
sessionId: Int,
@@ -175,38 +175,10 @@ interface CompileService : Remote {
history: List<ReplCodeLine>?
): CallResult<ReplCompileResult>
@Deprecated("Evaluation on daemon is not supported")
@Throws(RemoteException::class)
fun remoteReplLineEval(
sessionId: Int,
codeLine: ReplCodeLine,
history: List<ReplCodeLine>?
): CallResult<ReplEvalResult>
@Throws(RemoteException::class)
fun leaseReplSession(
aliveFlagPath: String?,
compilerArguments: Array<out String>,
compilationOptions: CompilationOptions,
servicesFacade: CompilerServicesFacadeBase,
templateClasspath: List<File>,
templateClassName: String
): CallResult<Int>
@Throws(RemoteException::class)
fun replCreateState(sessionId: Int): CallResult<ReplStateFacade>
@Throws(RemoteException::class)
fun replCheck(
sessionId: Int,
replStateId: Int,
codeLine: ReplCodeLine
): CallResult<ReplCheckResult>
@Throws(RemoteException::class)
fun replCompile(
sessionId: Int,
replStateId: Int,
codeLine: ReplCodeLine
): CallResult<ReplCompileResult>
}

View File

@@ -29,7 +29,6 @@ import java.rmi.RemoteException
* the reason for having common facade is attempt to reduce number of connections between client and daemon
* Note: non-standard naming convention used to denote combining several entities in one facade - prefix <entityName>_ is used for every function belonging to the entity
*/
@Deprecated("The usages should be replaced with `compile` method and `CompilerServicesFacadeBase` implementations", ReplaceWith("CompilerServicesFacadeBase"))
interface CompilerCallbackServicesFacade : Remote {
@Throws(RemoteException::class)
@@ -81,7 +80,7 @@ interface CompilerCallbackServicesFacade : Remote {
// ----------------------------------------------------
// CompilationCanceledStatus
@Throws(RemoteException::class, RmiFriendlyCompilationCanceledException::class)
fun compilationCanceledStatus_checkCanceled(): Void?
fun compilationCanceledStatus_checkCanceled(): Unit
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2010-2017 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.daemon.common
import org.jetbrains.kotlin.cli.common.repl.ILineId
import java.rmi.Remote
import java.rmi.RemoteException
interface ReplStateFacade : Remote {
@Throws(RemoteException::class)
fun getId(): Int
@Throws(RemoteException::class)
fun getHistorySize(): Int
@Throws(RemoteException::class)
fun historyGet(index: Int): ILineId
@Throws(RemoteException::class)
fun historyResetTo(id: ILineId): List<ILineId>
}

View File

@@ -63,6 +63,7 @@ import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
import java.util.logging.Level
import java.util.logging.Logger
import kotlin.comparisons.compareByDescending
import kotlin.concurrent.read
import kotlin.concurrent.schedule
import kotlin.concurrent.write
@@ -101,7 +102,6 @@ class CompileServiceImpl(
val timer: Timer,
val onShutdown: () -> Unit
) : CompileService {
init {
System.setProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
}
@@ -133,13 +133,24 @@ class CompileServiceImpl(
private val lock = ReentrantReadWriteLock()
private val sessions: MutableMap<Int, ClientOrSessionProxy<Any>> = hashMapOf()
private val sessionsIdCounter = AtomicInteger(0)
private val internalRng = Random()
fun<T: Any> leaseSession(session: ClientOrSessionProxy<T>): Int = lock.write {
val newId = getValidId(sessionsIdCounter) {
it != CompileService.NO_SESSION && !sessions.containsKey(it)
fun<T: Any> leaseSession(session: ClientOrSessionProxy<T>): Int {
// fighting hypothetical integer wrapping
var newId = sessionsIdCounter.incrementAndGet()
for (attempt in 1..100) {
if (newId != CompileService.NO_SESSION) {
lock.write {
if (!sessions.containsKey(newId)) {
sessions.put(newId, session)
return newId
}
}
}
// assuming wrap, jumping to random number to reduce probability of further clashes
newId = sessionsIdCounter.addAndGet(internalRng.nextInt())
}
sessions.put(newId, session)
newId
throw IllegalStateException("Invalid state or algorithm error")
}
fun isEmpty(): Boolean = lock.read { sessions.isEmpty() }
@@ -256,7 +267,7 @@ class CompileServiceImpl(
ifAlive { CompileService.CallResult.Good(usedMemory(withGC = true)) }
override fun shutdown(): CompileService.CallResult<Nothing> = ifAliveExclusive(minAliveness = Aliveness.LastSession, ignoreCompilerChanged = true) {
shutdownWithDelay()
shutdownImpl()
CompileService.CallResult.Ok()
}
@@ -461,10 +472,9 @@ class CompileServiceImpl(
CompileService.CallResult.Error("Sorry, only JVM target platform is supported now")
else {
val disposable = Disposer.newDisposable()
val compilerMessagesStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(compilerMessagesOutputStream, DummyProfiler()), REMOTE_STREAM_BUFFER_SIZE))
val messageCollector = KeepFirstErrorMessageCollector(compilerMessagesStream)
val repl = KotlinJvmReplService(disposable, port, templateClasspath, templateClassName,
messageCollector, operationsTracer)
val repl = KotlinJvmReplService(disposable, templateClasspath, templateClassName,
scriptArgs?.let { ScriptArgsWithTypes(it, scriptArgsTypes?.map { it.kotlin }?.toTypedArray() ?: emptyArray()) },
compilerMessagesOutputStream, operationsTracer)
val sessionId = state.sessions.leaseSession(ClientOrSessionProxy(aliveFlagPath, repl, disposable))
CompileService.CallResult.Good(sessionId)
@@ -477,14 +487,14 @@ class CompileServiceImpl(
override fun remoteReplLineCheck(sessionId: Int, codeLine: ReplCodeLine): CompileService.CallResult<ReplCheckResult> =
ifAlive(minAliveness = Aliveness.Alive) {
withValidRepl(sessionId) {
CompileService.CallResult.Good(check(codeLine))
check(codeLine)
}
}
override fun remoteReplLineCompile(sessionId: Int, codeLine: ReplCodeLine, history: List<ReplCodeLine>?): CompileService.CallResult<ReplCompileResult> =
ifAlive(minAliveness = Aliveness.Alive) {
withValidRepl(sessionId) {
CompileService.CallResult.Good(compile(codeLine, history))
compile(codeLine, history)
}
}
@@ -493,56 +503,12 @@ class CompileServiceImpl(
codeLine: ReplCodeLine,
history: List<ReplCodeLine>?
): CompileService.CallResult<ReplEvalResult> =
ifAlive(minAliveness = Aliveness.Alive) {
CompileService.CallResult.Error("Eval on daemon is not supported")
}
override fun leaseReplSession(aliveFlagPath: String?,
compilerArguments: Array<out String>,
compilationOptions: CompilationOptions,
servicesFacade: CompilerServicesFacadeBase,
templateClasspath: List<File>,
templateClassName: String
): CompileService.CallResult<Int> = ifAlive(minAliveness = Aliveness.Alive) {
if (compilationOptions.targetPlatform != CompileService.TargetPlatform.JVM)
CompileService.CallResult.Error("Sorry, only JVM target platform is supported now")
else {
val disposable = Disposer.newDisposable()
val messageCollector = CompileServicesFacadeMessageCollector(servicesFacade, compilationOptions)
val repl = KotlinJvmReplService(disposable, port, templateClasspath, templateClassName,
messageCollector, null)
val sessionId = state.sessions.leaseSession(ClientOrSessionProxy(aliveFlagPath, repl, disposable))
CompileService.CallResult.Good(sessionId)
}
}
override fun replCreateState(sessionId: Int): CompileService.CallResult<ReplStateFacade> =
ifAlive(minAliveness = Aliveness.Alive) {
withValidRepl(sessionId) {
CompileService.CallResult.Good(createRemoteState(port))
compileAndEval(codeLine, verifyHistory = history)
}
}
override fun replCheck(sessionId: Int, replStateId: Int, codeLine: ReplCodeLine): CompileService.CallResult<ReplCheckResult> =
ifAlive(minAliveness = Aliveness.Alive) {
withValidRepl(sessionId) {
withValidReplState(replStateId) { state ->
check(state, codeLine)
}
}
}
override fun replCompile(sessionId: Int, replStateId: Int, codeLine: ReplCodeLine): CompileService.CallResult<ReplCompileResult> =
ifAlive(minAliveness = Aliveness.Alive) {
withValidRepl(sessionId) {
withValidReplState(replStateId) { state ->
compile(state, codeLine)
}
}
}
// -----------------------------------------------------------------------
// internal implementation stuff
// TODO: consider matching compilerId coming from outside with actual one
@@ -603,7 +569,7 @@ class CompileServiceImpl(
// 3. check if in graceful shutdown state and all sessions are closed
if (shutdownCondition({ state.alive.get() == Aliveness.LastSession.ordinal && state.sessions.isEmpty() }, "All sessions finished, shutting down")) {
shutdownWithDelay()
shutdown()
shuttingDown = true
}
@@ -629,7 +595,7 @@ class CompileServiceImpl(
// TODO: could be too expensive anyway, consider removing this check
shutdownCondition({ classpathWatcher.isChanged }, "Compiler changed"))
{
scheduleShutdown(true)
shutdown()
shuttingDown = true
}
@@ -745,7 +711,7 @@ class CompileServiceImpl(
operationsTracer: RemoteOperationsTracer?,
body: (PrintStream, EventManager, Profiler) -> ExitCode): CompileService.CallResult<Int> =
ifAlive {
withValidClientOrSessionProxy(sessionId) { _ ->
withValidClientOrSessionProxy(sessionId) { session ->
operationsTracer?.before("compile")
val rpcProfiler = if (daemonOptions.reportPerf) WallAndThreadTotalProfiler() else DummyProfiler()
val eventManger = EventManagerImpl()
@@ -775,7 +741,7 @@ class CompileServiceImpl(
tracer: RemoteOperationsTracer?,
body: (EventManager, Profiler) -> ExitCode): CompileService.CallResult<Int> =
ifAlive {
withValidClientOrSessionProxy(sessionId) { _ ->
withValidClientOrSessionProxy(sessionId) { session ->
tracer?.before("compile")
val rpcProfiler = if (daemonOptions.reportPerf) WallAndThreadTotalProfiler() else DummyProfiler()
val eventManger = EventManagerImpl()
@@ -895,6 +861,7 @@ class CompileServiceImpl(
finally {
_lastUsedSeconds = nowSeconds()
}
}
private inline fun<R> withValidRepl(sessionId: Int, body: KotlinJvmReplService.() -> R): CompileService.CallResult<R> =
@@ -903,12 +870,4 @@ class CompileServiceImpl(
CompileService.CallResult.Good(it.body())
} ?: CompileService.CallResult.Error("Not a REPL session $sessionId")
}
@JvmName("withValidRepl1")
private inline fun<R> withValidRepl(sessionId: Int, body: KotlinJvmReplService.() -> CompileService.CallResult<R>): CompileService.CallResult<R> =
withValidClientOrSessionProxy(sessionId) { session ->
(session?.data as? KotlinJvmReplService?)?.let {
it.body()
} ?: CompileService.CallResult.Error("Not a REPL session $sessionId")
}
}

View File

@@ -35,6 +35,7 @@ import kotlin.concurrent.schedule
val DAEMON_PERIODIC_CHECK_INTERVAL_MS = 1000L
class LogStream(name: String) : OutputStream() {
val log by lazy { Logger.getLogger(name) }
@@ -156,6 +157,8 @@ object KotlinCompileDaemon {
println(COMPILE_DAEMON_IS_READY_MESSAGE)
log.info("daemon is listening on port: $port")
log.info("daemon is listening on port: $port")
// this supposed to stop redirected streams reader(s) on the client side and prevent some situations with hanging threads, but doesn't work reliably
// TODO: implement more reliable scheme
System.out.close()

View File

@@ -20,40 +20,58 @@ import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.repl.GenericReplCompiler
import org.jetbrains.kotlin.cli.jvm.repl.GenericReplCompilerState
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.daemon.common.CompileService
import org.jetbrains.kotlin.daemon.common.DummyProfiler
import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer
import org.jetbrains.kotlin.daemon.common.RemoteOutputStream
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
import org.jetbrains.kotlin.utils.PathUtil
import java.io.BufferedOutputStream
import java.io.File
import java.io.PrintStream
import java.net.URLClassLoader
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
open class KotlinJvmReplService(
disposable: Disposable,
val portForServers: Int,
templateClasspath: List<File>,
templateClassName: String,
protected val messageCollector: MessageCollector,
@Deprecated("drop it")
protected val fallbackScriptArgs: ScriptArgsWithTypes?,
compilerOutputStreamProxy: RemoteOutputStream,
protected val operationsTracer: RemoteOperationsTracer?
) : ReplCompileAction, ReplCheckAction, CreateReplStageStateAction {
) : ReplCompileAction, ReplAtomicEvalAction, ReplCheckAction, ReplEvaluatorExposedInternalHistory {
protected val compilerMessagesStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(compilerOutputStreamProxy, DummyProfiler()), REMOTE_STREAM_BUFFER_SIZE))
protected class KeepFirstErrorMessageCollector(compilerMessagesStream: PrintStream) : MessageCollector {
private val innerCollector = PrintingMessageCollector(compilerMessagesStream, MessageRenderer.WITHOUT_PATHS, false)
internal var firstErrorMessage: String? = null
internal var firstErrorLocation: CompilerMessageLocation? = null
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
if (firstErrorMessage == null && severity.isError) {
firstErrorMessage = message
firstErrorLocation = location
}
innerCollector.report(severity, message, location)
}
override fun hasErrors(): Boolean = innerCollector.hasErrors()
override fun clear() {
innerCollector.clear()
}
}
protected val messageCollector = KeepFirstErrorMessageCollector(compilerMessagesStream)
protected val configuration = CompilerConfiguration().apply {
addJvmClasspathRoots(PathUtil.getJdkClassesRoots())
addJvmClasspathRoots(PathUtil.getKotlinPathsForCompiler().let { listOf(it.runtimePath, it.reflectPath, it.scriptRuntimePath) })
addJvmClasspathRoots(templateClasspath)
put(CommonConfigurationKeys.MODULE_NAME, "kotlin-script")
put(CommonConfigurationKeys.SKIP_METADATA_VERSION_CHECK, true)
}
protected fun makeScriptDefinition(templateClasspath: List<File>, templateClassName: String): KotlinScriptDefinition? {
@@ -89,92 +107,49 @@ open class KotlinJvmReplService(
else GenericReplCompiler(disposable, scriptDef, configuration, messageCollector)
}
protected val statesLock = ReentrantReadWriteLock()
// TODO: consider using values here for session cleanup
protected val states = WeakHashMap<RemoteReplStateFacadeServer, Boolean>() // used as (missing) WeakHashSet
protected val stateIdCounter = AtomicInteger()
@Deprecated("remove after removal state-less check/compile/eval methods")
protected val defaultStateFacade: RemoteReplStateFacadeServer by lazy { createRemoteState() }
private val replEvaluator: ReplFullEvaluator? by lazy {
replCompiler?.let { compiler ->
GenericReplCompilingEvaluator(compiler, configuration.jvmClasspathRoots, null, fallbackScriptArgs, ReplRepeatingMode.NONE)
}
}
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> =
replCompiler?.createState(lock) ?: throw IllegalStateException("repl compiler is not initialized properly")
override val lastEvaluatedScripts: List<EvalHistoryType> get() = replEvaluator?.lastEvaluatedScripts ?: emptyList()
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult {
override fun check(codeLine: ReplCodeLine): ReplCheckResult {
operationsTracer?.before("check")
try {
return replCompiler?.check(state, codeLine)
?: ReplCheckResult.Error("Initialization error", CompilerMessageLocation.NO_LOCATION)
return replCompiler?.check(codeLine)
?: ReplCheckResult.Error(messageCollector.firstErrorMessage ?: "Unknown error",
messageCollector.firstErrorLocation ?: CompilerMessageLocation.NO_LOCATION)
}
finally {
operationsTracer?.after("check")
}
}
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
override fun compile(codeLine: ReplCodeLine, verifyHistory: List<ReplCodeLine>?): ReplCompileResult {
operationsTracer?.before("compile")
try {
return replCompiler?.compile(state, codeLine)
?: ReplCompileResult.Error("Initialization error", CompilerMessageLocation.NO_LOCATION)
return replCompiler?.compile(codeLine, verifyHistory)
?: ReplCompileResult.Error(verifyHistory ?: emptyList(),
messageCollector.firstErrorMessage ?: "Unknown error",
messageCollector.firstErrorLocation ?: CompilerMessageLocation.NO_LOCATION)
}
finally {
operationsTracer?.after("compile")
}
}
@Deprecated("Use check(state, line) instead")
fun check(codeLine: ReplCodeLine): ReplCheckResult = check(defaultStateFacade.state, codeLine)
@Deprecated("Use compile(state, line) instead")
fun compile(codeLine: ReplCodeLine, verifyHistory: List<ReplCodeLine>?): ReplCompileResult = compile(defaultStateFacade.state, codeLine)
fun createRemoteState(port: Int = portForServers): RemoteReplStateFacadeServer = statesLock.write {
val id = getValidId(stateIdCounter) { id -> states.none { it.key.getId() == id} }
val stateFacade = RemoteReplStateFacadeServer(id, createState().asState(GenericReplCompilerState::class.java), port)
states.put(stateFacade, true)
stateFacade
}
fun<R> withValidReplState(stateId: Int, body: (IReplStageState<*>) -> R): CompileService.CallResult<R> = statesLock.read {
states.keys.firstOrNull { it.getId() == stateId }?.let {
CompileService.CallResult.Good(body(it.state))
override fun compileAndEval(codeLine: ReplCodeLine, scriptArgs: ScriptArgsWithTypes?, verifyHistory: List<ReplCodeLine>?, invokeWrapper: InvokeWrapper?): ReplEvalResult {
operationsTracer?.before("eval")
try {
return replEvaluator?.compileAndEval(codeLine, scriptArgs ?: fallbackScriptArgs, verifyHistory, invokeWrapper)
?: ReplEvalResult.Error.CompileTime(verifyHistory ?: replEvaluator?.history ?: emptyList(),
messageCollector.firstErrorMessage ?: "Unknown error",
messageCollector.firstErrorLocation ?: CompilerMessageLocation.NO_LOCATION)
}
?: CompileService.CallResult.Error("No REPL state with id $stateId found")
}
}
internal class KeepFirstErrorMessageCollector(compilerMessagesStream: PrintStream) : MessageCollector {
private val innerCollector = PrintingMessageCollector(compilerMessagesStream, MessageRenderer.WITHOUT_PATHS, false)
internal var firstErrorMessage: String? = null
internal var firstErrorLocation: CompilerMessageLocation? = null
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
if (firstErrorMessage == null && severity.isError) {
firstErrorMessage = message
firstErrorLocation = location
finally {
operationsTracer?.after("eval")
}
innerCollector.report(severity, message, location)
}
override fun hasErrors(): Boolean = innerCollector.hasErrors()
override fun clear() {
innerCollector.clear()
}
}
internal val internalRng = Random()
inline internal fun getValidId(counter: AtomicInteger, check: (Int) -> Boolean): Int {
// fighting hypothetical integer wrapping
var newId = counter.incrementAndGet()
var attemptsLeft = 100
while (!check(newId)) {
attemptsLeft -= 1
if (attemptsLeft <= 0)
throw IllegalStateException("Invalid state or algorithm error")
// assuming wrap, jumping to random number to reduce probability of further clashes
newId = counter.addAndGet(internalRng.nextInt())
}
return newId
}

View File

@@ -1,39 +0,0 @@
/*
* Copyright 2010-2017 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.daemon
import org.jetbrains.kotlin.cli.common.repl.ILineId
import org.jetbrains.kotlin.cli.jvm.repl.GenericReplCompilerState
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
import org.jetbrains.kotlin.daemon.common.ReplStateFacade
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
import java.rmi.server.UnicastRemoteObject
class RemoteReplStateFacadeServer(val _id: Int,
val state: GenericReplCompilerState,
port: Int = SOCKET_ANY_FREE_PORT
) : ReplStateFacade,
UnicastRemoteObject(port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
{
override fun getId(): Int = _id
override fun getHistorySize(): Int = state.history.size
override fun historyGet(index: Int): ILineId = state.history[index].id
override fun historyResetTo(id: ILineId): List<ILineId> = state.history.resetTo(id).toList()
}

View File

@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.context.LazyResolveToken
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.frontend.di.configureCommon
import org.jetbrains.kotlin.frontend.di.configureModule
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
@@ -47,10 +46,11 @@ import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
private fun StorageComponentContainer.configureJavaTopDownAnalysis(
fun StorageComponentContainer.configureJavaTopDownAnalysis(
moduleContentScope: GlobalSearchScope,
project: Project,
lookupTracker: LookupTracker
lookupTracker: LookupTracker,
languageVersionSettings: LanguageVersionSettings
) {
useInstance(moduleContentScope)
useInstance(lookupTracker)
@@ -75,6 +75,7 @@ private fun StorageComponentContainer.configureJavaTopDownAnalysis(
useImpl<JavaSourceElementFactoryImpl>()
useInstance(InternalFlexibleTypeTransformer)
useInstance(languageVersionSettings)
useImpl<CompilerDeserializationConfiguration>()
}
@@ -87,19 +88,19 @@ fun createContainerForLazyResolveWithJava(
targetEnvironment: TargetEnvironment,
lookupTracker: LookupTracker,
packagePartProvider: PackagePartProvider,
compilerConfiguration: CompilerConfiguration,
languageVersionSettings: LanguageVersionSettings,
useBuiltInsProvider: Boolean,
useLazyResolve: Boolean
useLazyResolve: Boolean,
compilerConfiguration: CompilerConfiguration
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatform) {
configureModule(moduleContext, JvmPlatform, bindingTrace)
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker)
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker, languageVersionSettings)
useInstance(compilerConfiguration)
useInstance(packagePartProvider)
useInstance(moduleClassResolver)
useInstance(declarationProviderFactory)
configureCommon(compilerConfiguration)
if (useBuiltInsProvider) {
useInstance((moduleContext.module.builtIns as JvmBuiltIns).settings)
useImpl<JvmBuiltInsPackageFragmentProvider>()
@@ -122,17 +123,18 @@ fun createContainerForTopDownAnalyzerForJvm(
moduleContentScope: GlobalSearchScope,
lookupTracker: LookupTracker,
packagePartProvider: PackagePartProvider,
languageVersionSettings: LanguageVersionSettings,
moduleClassResolver: ModuleClassResolver,
compilerConfiguration: CompilerConfiguration
): ComponentProvider = createContainerForLazyResolveWithJava(
moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver,
CompilerEnvironment, lookupTracker, packagePartProvider, compilerConfiguration,
useBuiltInsProvider = true, useLazyResolve = false
CompilerEnvironment, lookupTracker, packagePartProvider, languageVersionSettings,
useBuiltInsProvider = true, useLazyResolve = false, compilerConfiguration = compilerConfiguration
)
fun ComponentProvider.initJvmBuiltInsForTopDownAnalysis() {
get<JvmBuiltIns>().initialize(get<ModuleDescriptor>(), get<LanguageVersionSettings>())
fun ComponentProvider.initJvmBuiltInsForTopDownAnalysis(module: ModuleDescriptor, languageVersionSettings: LanguageVersionSettings) {
get<JvmBuiltIns>().initialize(module, languageVersionSettings)
}
internal fun JvmBuiltIns.initialize(module: ModuleDescriptor, languageVersionSettings: LanguageVersionSettings) {

View File

@@ -143,9 +143,8 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
}
@Override
public void loadClassAnnotations(@NotNull final AnnotationVisitor annotationVisitor, @Nullable byte[] cachedContents) {
byte[] fileContents = cachedContents != null ? cachedContents : getFileContents();
new ClassReader(fileContents).accept(new ClassVisitor(ASM5) {
public void loadClassAnnotations(@NotNull final AnnotationVisitor annotationVisitor) {
new ClassReader(getFileContents()).accept(new ClassVisitor(ASM5) {
@Override
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitAnnotation(@NotNull String desc, boolean visible) {
return convertAnnotationVisitor(annotationVisitor, desc, innerClasses);
@@ -216,9 +215,8 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
}
@Override
public void visitMembers(@NotNull final MemberVisitor memberVisitor, @Nullable byte[] cachedContents) {
byte[] fileContents = cachedContents != null ? cachedContents : getFileContents();
new ClassReader(fileContents).accept(new ClassVisitor(ASM5) {
public void visitMembers(@NotNull final MemberVisitor memberVisitor) {
new ClassReader(getFileContents()).accept(new ClassVisitor(ASM5) {
@Override
public FieldVisitor visitField(int access, @NotNull String name, @NotNull String desc, String signature, Object value) {
final AnnotationVisitor v = memberVisitor.visitField(Name.identifier(name), desc, value);

View File

@@ -19,19 +19,18 @@ package org.jetbrains.kotlin.load.kotlin.incremental
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.storage.StorageManager
internal class IncrementalPackagePartProvider(
internal class IncrementalPackagePartProvider private constructor(
private val parent: PackagePartProvider,
incrementalCaches: List<IncrementalCache>,
storageManager: StorageManager
) : PackagePartProvider {
lateinit var deserializationConfiguration: DeserializationConfiguration
private val moduleMappings = storageManager.createLazyValue {
incrementalCaches.map { cache ->
ModuleMapping.create(cache.getModuleMappingData(), "<incremental>", deserializationConfiguration)
ModuleMapping.create(cache.getModuleMappingData(), "<incremental>")
}
}
@@ -42,4 +41,19 @@ internal class IncrementalPackagePartProvider(
// TODO
override fun findMetadataPackageParts(packageFqName: String): List<String> = TODO()
companion object {
@JvmStatic
fun create(
parent: PackagePartProvider,
targets: List<TargetId>?,
incrementalCompilationComponents: IncrementalCompilationComponents?,
storageManager: StorageManager
): PackagePartProvider {
if (targets == null || incrementalCompilationComponents == null) return parent
val incrementalCaches = targets.map { incrementalCompilationComponents.getIncrementalCache(it) }
return IncrementalPackagePartProvider(parent, incrementalCaches, storageManager)
}
}
}

View File

@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.PackagePartProvider
@@ -82,20 +81,15 @@ object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters>() {
resolverForModule.componentProvider.get<JavaDescriptorResolver>()
}
val configuration = CompilerConfiguration().apply {
val languageSettingsProvider = LanguageSettingsProvider.getInstance(project)
languageVersionSettings = languageSettingsProvider.getLanguageVersionSettings(moduleInfo, project)
val platform = languageSettingsProvider.getTargetPlatform(moduleInfo)
if (platform is JvmTarget) {
put(JVMConfigurationKeys.JVM_TARGET, platform)
}
isReadOnly = true
}
val languageSettingsProvider = LanguageSettingsProvider.getInstance(project)
val trace = CodeAnalyzerInitializer.getInstance(project).createTrace()
//TODO: need to propagate full CompilerConfiguration to frontend
val compilerConfiguration = CompilerConfiguration()
val platform = languageSettingsProvider.getTargetPlatform(moduleInfo)
if (platform is JvmTarget) {
compilerConfiguration.put(JVMConfigurationKeys.JVM_TARGET, platform)
}
compilerConfiguration.isReadOnly = true
val container = createContainerForLazyResolveWithJava(
moduleContext,
trace,
@@ -105,9 +99,10 @@ object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters>() {
targetEnvironment,
LookupTracker.DO_NOTHING,
packagePartProvider,
configuration,
languageSettingsProvider.getLanguageVersionSettings(moduleInfo, project),
useBuiltInsProvider = false, // TODO: load built-ins from module dependencies in IDE
useLazyResolve = true
useLazyResolve = true,
compilerConfiguration = compilerConfiguration
)
StorageComponentContainerContributor.getInstances(project).forEach { it.onContainerComposed(container, moduleInfo) }

View File

@@ -24,9 +24,10 @@ import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.builtins.JvmBuiltInsPackageFragmentProvider
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ContextForNewModule
@@ -62,7 +63,6 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.storage.StorageManager
import java.util.*
@@ -135,10 +135,13 @@ object TopDownAnalyzerFacadeForJVM {
val sourceScope = if (separateModules) sourceModuleSearchScope else GlobalSearchScope.allScope(project)
val moduleClassResolver = SourceOrBinaryModuleClassResolver(sourceScope)
val languageVersionSettings =
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
val optionalBuiltInsModule =
if (configuration.getBoolean(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES)) {
if (createBuiltInsFromModule)
JvmBuiltIns(storageManager).apply { initialize(module, configuration.languageVersionSettings) }.builtInsModule
JvmBuiltIns(storageManager).apply { initialize(module, languageVersionSettings) }.builtInsModule
else module.builtIns.builtInsModule
}
else null
@@ -154,7 +157,7 @@ object TopDownAnalyzerFacadeForJVM {
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker,
packagePartProvider(dependencyScope), moduleClassResolver, configuration
packagePartProvider(dependencyScope), languageVersionSettings, moduleClassResolver, configuration
)
StorageComponentContainerContributor.getInstances(project).forEach { it.onContainerComposed(dependenciesContainer, null) }
@@ -170,22 +173,18 @@ object TopDownAnalyzerFacadeForJVM {
}
else null
val partProvider = packagePartProvider(sourceScope).let { fragment ->
if (targetIds == null || incrementalComponents == null) fragment
else IncrementalPackagePartProvider(fragment, targetIds.map(incrementalComponents::getIncrementalCache), storageManager)
}
// Note that it's necessary to create container for sources _after_ creation of container for dependencies because
// CliLightClassGenerationSupport#initialize is invoked when container is created, so only the last module descriptor is going
// to be stored in CliLightClassGenerationSupport, and it better be the source one (otherwise light classes would not be found)
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
val container = createContainerForTopDownAnalyzerForJvm(
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
partProvider, moduleClassResolver, configuration
IncrementalPackagePartProvider.create(
packagePartProvider(sourceScope), targetIds, incrementalComponents, storageManager
),
languageVersionSettings, moduleClassResolver, configuration
).apply {
initJvmBuiltInsForTopDownAnalysis()
(partProvider as? IncrementalPackagePartProvider)?.deserializationConfiguration = get<DeserializationConfiguration>()
initJvmBuiltInsForTopDownAnalysis(module, languageVersionSettings)
StorageComponentContainerContributor.getInstances(project).forEach { it.onContainerComposed(this, null) }
}
@@ -254,7 +253,7 @@ object TopDownAnalyzerFacadeForJVM {
fun createContextWithSealedModule(project: Project, configuration: CompilerConfiguration): MutableModuleContext =
createModuleContext(project, configuration, false).apply {
setDependencies(module, module.builtIns.builtInsModule)
(module.builtIns as JvmBuiltIns).initialize(module, configuration.languageVersionSettings)
(module.builtIns as JvmBuiltIns).initialize(module, configuration.get(LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT))
}
private fun createModuleContext(

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -49,7 +49,6 @@ object JvmPlatformConfigurator : PlatformConfigurator(
additionalCallCheckers = listOf(
JavaAnnotationCallChecker(),
InterfaceDefaultMethodCallChecker(),
JavaClassOnCompanionChecker(),
ProtectedInSuperClassCompanionCallChecker(),
UnsupportedSyntheticCallableReferenceChecker(),

View File

@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype
import java.util.*
import kotlin.properties.Delegates
@@ -58,10 +59,8 @@ class SamAdapterFunctionsScope(
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
var result: SmartList<FunctionDescriptor>? = null
for (type in receiverTypes) {
val substitutorForType by lazy { buildMemberScopeSubstitutorForType(type) }
for (function in type.memberScope.getContributedFunctions(name, location)) {
val extension = extensionForFunction(function.original)?.substitute(substitutorForType)
val extension = extensionForFunction(function.original)?.substituteForReceiverType(type)
if (extension != null) {
if (result == null) {
result = SmartList()
@@ -77,15 +76,24 @@ class SamAdapterFunctionsScope(
}
}
private fun buildMemberScopeSubstitutorForType(type: KotlinType) =
TypeConstructorSubstitution.create(type).wrapWithCapturingSubstitution(needApproximation = true).buildSubstitutor()
private fun FunctionDescriptor.substituteForReceiverType(receiverType: KotlinType): FunctionDescriptor? {
val containingClass = containingDeclaration as? ClassDescriptor ?: return null
val correspondingSupertype = findCorrespondingSupertype(receiverType, containingClass.defaultType) ?: return null
return substitute(
TypeConstructorSubstitution
.create(correspondingSupertype)
.wrapWithCapturingSubstitution(needApproximation = true)
.buildSubstitutor()
)
}
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
.filterIsInstance<FunctionDescriptor>()
.mapNotNull {
extensionForFunction(it.original)?.substitute(buildMemberScopeSubstitutorForType(type))
extensionForFunction(it.original)?.substituteForReceiverType(type)
}
}
}
@@ -159,10 +167,13 @@ class SamAdapterFunctionsScope(
}
}
override fun newCopyBuilder(substitutor: TypeSubstitutor): CopyConfiguration =
super.newCopyBuilder(substitutor).setOriginal(this.original)
override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? {
val descriptor = super.doSubstitute(configuration) as MyFunctionDescriptor? ?: return null
val original = configuration.original
?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension")
?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension $this")
original as MyFunctionDescriptor
assert(original.original == original) { "original in doSubstitute should have no other original" }

View File

@@ -19,7 +19,10 @@ package org.jetbrains.kotlin.analyzer.common
import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.container.useImpl
@@ -31,7 +34,6 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.di.configureCommon
import org.jetbrains.kotlin.frontend.di.configureModule
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
@@ -49,11 +51,9 @@ import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmen
* See [TargetPlatform.Default]
*/
object DefaultAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
private val compilerConfiguration = CompilerConfiguration().apply {
languageVersionSettings = LanguageVersionSettingsImpl(
LanguageVersion.LATEST, ApiVersion.LATEST, setOf(LanguageFeature.MultiPlatformProjects)
)
}
private val languageVersionSettings = LanguageVersionSettingsImpl(
LanguageVersion.LATEST, ApiVersion.LATEST, setOf(LanguageFeature.MultiPlatformProjects)
)
private class SourceModuleInfo(
override val name: Name,
@@ -135,7 +135,7 @@ object DefaultAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
useImpl<ResolveSession>()
useImpl<LazyTopDownAnalyzer>()
useImpl<FileScopeProviderImpl>()
configureCommon(compilerConfiguration)
useInstance(languageVersionSettings)
useImpl<CompilerDeserializationConfiguration>()
useInstance(packagePartProvider)
useInstance(declarationProviderFactory)

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2010-2015 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.config;
public class CommonConfigurationKeys {
private CommonConfigurationKeys() {
}
public static final CompilerConfigurationKey<LanguageVersionSettings> LANGUAGE_VERSION_SETTINGS =
CompilerConfigurationKey.create("language version settings");
public static final CompilerConfigurationKey<Boolean> DISABLE_INLINE =
CompilerConfigurationKey.create("disable inline");
public static final CompilerConfigurationKey<String> MODULE_NAME =
CompilerConfigurationKey.create("module name");
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2010-2015 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.config
object CommonConfigurationKeys {
@JvmField
val LANGUAGE_VERSION_SETTINGS = CompilerConfigurationKey<LanguageVersionSettings>("language version settings")
@JvmField
val SKIP_METADATA_VERSION_CHECK = CompilerConfigurationKey<Boolean>("skip metadata version check")
@JvmField
val DISABLE_INLINE = CompilerConfigurationKey<Boolean>("disable inline")
@JvmField
val MODULE_NAME = CompilerConfigurationKey<String>("module name")
}
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings
get() = get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
set(value) = put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, value)

View File

@@ -23,11 +23,10 @@ import org.jetbrains.annotations.NotNull;
public class CompilerConfigurationKey<T> {
Key<T> ideaKey;
public CompilerConfigurationKey(@NotNull @NonNls String name) {
private CompilerConfigurationKey(@NotNull @NonNls String name) {
ideaKey = Key.create(name);
}
@NotNull
public static <T> CompilerConfigurationKey<T> create(@NotNull @NonNls String name) {
return new CompilerConfigurationKey<T>(name);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2017 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.
@@ -790,8 +790,6 @@ public interface Errors {
DiagnosticFactory0<KtConstantExpression> WRONG_LONG_SUFFIX = DiagnosticFactory0.create(ERROR, LONG_LITERAL_SUFFIX);
DiagnosticFactory0<KtConstantExpression> INT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstantExpression> FLOAT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstantExpression> FLOAT_LITERAL_CONFORMS_INFINITY = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtConstantExpression> FLOAT_LITERAL_CONFORMS_ZERO = DiagnosticFactory0.create(WARNING);
DiagnosticFactory2<KtConstantExpression, String, KotlinType> CONSTANT_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<KtConstantExpression> INCORRECT_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstantExpression> EMPTY_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR);
@@ -892,7 +890,6 @@ public interface Errors {
DiagnosticFactory1<PsiElement, ClassDescriptor> INACCESSIBLE_OUTER_CLASS_EXPRESSION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<KtClass> NESTED_CLASS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, DECLARATION_NAME);
DiagnosticFactory0<KtObjectDeclaration> NESTED_OBJECT_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, DECLARATION_NAME);
//Inline and inlinable parameters
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> NON_PUBLIC_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2017 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.
@@ -437,7 +437,6 @@ public class DefaultErrorMessages {
MAP.put(INACCESSIBLE_OUTER_CLASS_EXPRESSION, "Expression is inaccessible from a nested class ''{0}'', use ''inner'' keyword to make the class inner", NAME);
MAP.put(NESTED_CLASS_NOT_ALLOWED, "Nested class is not allowed here, use 'inner' keyword to make the class inner");
MAP.put(NESTED_OBJECT_NOT_ALLOWED, "Objects inside inner classes are prohibited");
MAP.put(HAS_NEXT_MISSING, "hasNext() cannot be called on iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "hasNext() is ambiguous for iterator() of type ''{0}''", RENDER_TYPE);
@@ -535,8 +534,6 @@ public class DefaultErrorMessages {
MAP.put(INT_LITERAL_OUT_OF_RANGE, "The value is out of range");
MAP.put(WRONG_LONG_SUFFIX, "Use 'L' instead of 'l'");
MAP.put(FLOAT_LITERAL_OUT_OF_RANGE, "The value is out of range");
MAP.put(FLOAT_LITERAL_CONFORMS_INFINITY, "Floating point number conforms to infinity");
MAP.put(FLOAT_LITERAL_CONFORMS_ZERO, "Floating point number conforms to zero");
MAP.put(INCORRECT_CHARACTER_LITERAL, "Incorrect character literal");
MAP.put(EMPTY_CHARACTER_LITERAL, "Empty character literal");
MAP.put(ILLEGAL_UNDERSCORE, "Illegal underscore");

View File

@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.frontend.di
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.container.useImpl
@@ -26,11 +26,9 @@ import org.jetbrains.kotlin.context.LazyResolveToken
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
@@ -66,17 +64,12 @@ fun StorageComponentContainer.configureModule(
useInstance(trace)
}
fun StorageComponentContainer.configureCommon(configuration: CompilerConfiguration) {
useInstance(configuration)
useInstance(configuration.languageVersionSettings)
}
fun createContainerForBodyResolve(
moduleContext: ModuleContext,
bindingTrace: BindingTrace,
platform: TargetPlatform,
statementFilter: StatementFilter,
compilerConfiguration: CompilerConfiguration
languageVersionSettings: LanguageVersionSettings
): StorageComponentContainer = createContainer("BodyResolve", platform) {
configureModule(moduleContext, platform, bindingTrace)
@@ -84,7 +77,7 @@ fun createContainerForBodyResolve(
useInstance(LookupTracker.DO_NOTHING)
useInstance(BodyResolveCache.ThrowException)
configureCommon(compilerConfiguration)
useInstance(languageVersionSettings)
useImpl<BodyResolver>()
}
@@ -95,7 +88,7 @@ fun createContainerForLazyBodyResolve(
bindingTrace: BindingTrace,
platform: TargetPlatform,
bodyResolveCache: BodyResolveCache,
compilerConfiguration: CompilerConfiguration
languageVersionSettings: LanguageVersionSettings
): StorageComponentContainer = createContainer("LazyBodyResolve", platform) {
configureModule(moduleContext, platform, bindingTrace)
@@ -103,7 +96,7 @@ fun createContainerForLazyBodyResolve(
useInstance(kotlinCodeAnalyzer)
useInstance(kotlinCodeAnalyzer.fileScopeProvider)
useInstance(bodyResolveCache)
configureCommon(compilerConfiguration)
useInstance(languageVersionSettings)
useImpl<LazyTopDownAnalyzer>()
useImpl<BasicAbsentDescriptorHandler>()
}
@@ -113,7 +106,7 @@ fun createContainerForLazyLocalClassifierAnalyzer(
bindingTrace: BindingTrace,
platform: TargetPlatform,
lookupTracker: LookupTracker,
compilerConfiguration: CompilerConfiguration,
languageVersionSettings: LanguageVersionSettings,
statementFilter: StatementFilter,
localClassDescriptorHolder: LocalClassDescriptorHolder
): StorageComponentContainer = createContainer("LocalClassifierAnalyzer", platform) {
@@ -133,7 +126,7 @@ fun createContainerForLazyLocalClassifierAnalyzer(
useImpl<DeclarationScopeProviderForLocalClassifierAnalyzer>()
useImpl<LocalLazyDeclarationResolver>()
configureCommon(compilerConfiguration)
useInstance(languageVersionSettings)
useInstance(statementFilter)
}
@@ -143,14 +136,15 @@ fun createContainerForLazyResolve(
bindingTrace: BindingTrace,
platform: TargetPlatform,
targetEnvironment: TargetEnvironment,
compilerConfiguration: CompilerConfiguration
languageVersionSettings: LanguageVersionSettings
): StorageComponentContainer = createContainer("LazyResolve", platform) {
configureModule(moduleContext, platform, bindingTrace)
useInstance(declarationProviderFactory)
useInstance(LookupTracker.DO_NOTHING)
configureCommon(compilerConfiguration)
useInstance(languageVersionSettings)
//TODO: need to propagate full CompilerConfiguration to frontend
useInstance(CompilerConfiguration.EMPTY)
useImpl<FileScopeProviderImpl>()
useImpl<CompilerDeserializationConfiguration>()
@@ -160,12 +154,14 @@ fun createContainerForLazyResolve(
useImpl<ResolveSession>()
}
fun createLazyResolveSession(moduleContext: ModuleContext, files: Collection<KtFile>): ResolveSession =
createContainerForLazyResolve(
moduleContext,
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
BindingTraceContext(),
TargetPlatform.Default,
CompilerEnvironment,
CompilerConfiguration.EMPTY
).get<ResolveSession>()
@JvmOverloads
fun createLazyResolveSession(
moduleContext: ModuleContext,
declarationProviderFactory: DeclarationProviderFactory,
bindingTrace: BindingTrace,
platform: TargetPlatform,
languageVersionSettings: LanguageVersionSettings,
targetEnvironment: TargetEnvironment = CompilerEnvironment
): ResolveSession = createContainerForLazyResolve(
moduleContext, declarationProviderFactory, bindingTrace, platform, targetEnvironment, languageVersionSettings
).get<ResolveSession>()

View File

@@ -311,12 +311,6 @@ private fun findFirstLeafWhollyInRange(file: PsiFile, range: TextRange): PsiElem
return if (elementRange.endOffset <= range.endOffset) element else null
}
val PsiElement.textRangeWithoutComments: TextRange
get() {
val firstNonCommentChild = children.firstOrNull { it !is PsiWhiteSpace && it !is PsiComment } ?: return textRange
return TextRange(firstNonCommentChild.startOffset, endOffset)
}
// ---------------------------------- Debug/logging ----------------------------------------------------------------------------------------
fun PsiElement.getElementTextWithContext(): String {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
* Copyright 2010-2015 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.
@@ -56,8 +56,7 @@ public class CompileTimeConstantUtils {
"kotlin.charArrayOf",
"kotlin.shortArrayOf",
"kotlin.byteArrayOf",
"kotlin.booleanArrayOf",
"kotlin.emptyArray"
"kotlin.booleanArrayOf"
);
public static void checkConstructorParametersType(@NotNull List<KtParameter> parameters, @NotNull BindingTrace trace) {
@@ -111,7 +110,7 @@ public class CompileTimeConstantUtils {
return false;
}
public static boolean isArrayFunctionCall(@NotNull ResolvedCall<?> resolvedCall) {
public static boolean isArrayMethodCall(@NotNull ResolvedCall<?> resolvedCall) {
return ARRAY_CALL_NAMES.contains(DescriptorUtils.getFqName(resolvedCall.getCandidateDescriptor()).asString());
}

View File

@@ -16,14 +16,11 @@
package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
class CompilerDeserializationConfiguration(configuration: CompilerConfiguration) : DeserializationConfiguration {
override val typeAliasesAllowed = configuration.languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)
override val skipMetadataVersionCheck = configuration.getBoolean(CommonConfigurationKeys.SKIP_METADATA_VERSION_CHECK)
class CompilerDeserializationConfiguration(private val languageVersionSettings: LanguageVersionSettings) : DeserializationConfiguration {
override val typeAliasesAllowed: Boolean
get() = languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)
}

View File

@@ -334,15 +334,15 @@ public class DescriptorResolver {
public List<VariableDescriptor> invoke() {
assert owner.getDispatchReceiverParameter() == null
: "Destructuring declarations are only be parsed for lambdas, and they must not have a dispatch receiver";
LexicalScope scopeForDestructuring =
ScopeUtilsKt.createScopeForDestructuring(scope, owner.getExtensionReceiverParameter());
LexicalScope scopeWithReceiver =
ScopeUtilsKt.addImplicitReceiver(scope, owner.getExtensionReceiverParameter());
List<VariableDescriptor> result =
destructuringDeclarationResolver.resolveLocalVariablesFromDestructuringDeclaration(
scope,
destructuringDeclaration, new TransientReceiver(type), /* initializer = */ null,
ExpressionTypingContext.newContext(
trace, scopeForDestructuring, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE
trace, scopeWithReceiver, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE
)
);

View File

@@ -1,117 +0,0 @@
/*
* Copyright 2010-2017 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.resolve
import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.BaseImportingScope
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.check
class LazyExplicitImportScope(
private val packageOrClassDescriptor: DeclarationDescriptor,
private val packageFragmentForVisibilityCheck: PackageFragmentDescriptor?,
private val declaredName: Name,
private val aliasName: Name,
private val storeReferences: (Collection<DeclarationDescriptor>) -> Unit
): BaseImportingScope(null) {
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
if (name != aliasName) return null
return when (packageOrClassDescriptor) {
is PackageViewDescriptor -> packageOrClassDescriptor.memberScope.getContributedClassifier(declaredName, location)
is ClassDescriptor -> packageOrClassDescriptor.unsubstitutedInnerClassesScope.getContributedClassifier(declaredName, location)
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
}
}
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
if (name != aliasName) return emptyList()
return collectCallableMemberDescriptors(location, MemberScope::getContributedFunctions)
}
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
if (name != aliasName) return emptyList()
return collectCallableMemberDescriptors(location, MemberScope::getContributedVariables)
}
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
val descriptors = SmartList<DeclarationDescriptor>()
descriptors.addIfNotNull(getContributedClassifier(aliasName, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS))
descriptors.addAll(getContributedFunctions(aliasName, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS))
descriptors.addAll(getContributedVariables(aliasName, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS))
return descriptors
}
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName, ": ", aliasName)
}
// should be called only once
internal fun storeReferencesToDescriptors() = getContributedDescriptors().apply(storeReferences)
private fun <D : CallableMemberDescriptor> collectCallableMemberDescriptors(
location: LookupLocation,
getDescriptors: MemberScope.(Name, LookupLocation) -> Collection<D>
): Collection<D> {
val descriptors = SmartList<D>()
when (packageOrClassDescriptor) {
is PackageViewDescriptor -> {
val packageScope = packageOrClassDescriptor.memberScope
descriptors.addAll(packageScope.getDescriptors(declaredName, location))
}
is ClassDescriptor -> {
val staticClassScope = packageOrClassDescriptor.staticScope
descriptors.addAll(staticClassScope.getDescriptors(declaredName, location))
if (packageOrClassDescriptor.kind == ClassKind.OBJECT) {
descriptors.addAll(
packageOrClassDescriptor.unsubstitutedMemberScope.getDescriptors(declaredName, location)
.mapNotNull { it.asImportedFromObjectIfPossible() }
)
}
}
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
}
return descriptors.choseOnlyVisibleOrAll()
}
@Suppress("UNCHECKED_CAST")
private fun <D : CallableMemberDescriptor> D.asImportedFromObjectIfPossible(): D? = when (this) {
is PropertyDescriptor -> asImportedFromObject() as D
is FunctionDescriptor -> asImportedFromObject() as D
else -> null
}
private fun <D : CallableMemberDescriptor> Collection<D>.choseOnlyVisibleOrAll() =
filter { isVisible(it, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT) }.
check { it.isNotEmpty() } ?: this
}

View File

@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker;
import java.util.*;
import static org.jetbrains.kotlin.diagnostics.Errors.NESTED_CLASS_NOT_ALLOWED;
import static org.jetbrains.kotlin.diagnostics.Errors.NESTED_OBJECT_NOT_ALLOWED;
import static org.jetbrains.kotlin.lexer.KtTokens.*;
import static org.jetbrains.kotlin.psi.KtStubbedPsiUtil.getContainingDeclaration;
@@ -220,20 +219,10 @@ public class ModifiersChecker {
public void checkModifiersForDeclaration(@NotNull KtDeclaration modifierListOwner, @NotNull MemberDescriptor descriptor) {
checkNestedClassAllowed(modifierListOwner, descriptor);
checkObjectInsideInnerClass(modifierListOwner, descriptor);
checkTypeParametersModifiers(modifierListOwner);
checkModifierListCommon(modifierListOwner, descriptor);
}
private void checkObjectInsideInnerClass(@NotNull KtDeclaration modifierListOwner, @NotNull MemberDescriptor descriptor) {
if (modifierListOwner instanceof KtObjectDeclaration) {
KtObjectDeclaration ktObject = (KtObjectDeclaration) modifierListOwner;
if (!ktObject.isLocal() && isIllegalNestedClass(descriptor)) {
trace.report(NESTED_OBJECT_NOT_ALLOWED.on(ktObject));
}
}
}
private void checkModifierListCommon(@NotNull KtDeclaration modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
AnnotationUseSiteTargetChecker.INSTANCE.check(modifierListOwner, descriptor, trace);
runDeclarationCheckers(modifierListOwner, descriptor);

View File

@@ -54,22 +54,23 @@ object ModifierCheckerCore {
COMPATIBLE_FOR_CLASSES_ONLY
}
private val defaultVisibilityTargets = EnumSet.of(CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS,
private val defaultVisibilityTargets = EnumSet.of(CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS,
MEMBER_FUNCTION, TOP_LEVEL_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER,
MEMBER_PROPERTY, TOP_LEVEL_PROPERTY, CONSTRUCTOR, TYPEALIAS)
val possibleTargetMap = mapOf<KtModifierKeywordToken, Set<KotlinTarget>>(
ENUM_KEYWORD to EnumSet.of(ENUM_CLASS),
ABSTRACT_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INTERFACE, MEMBER_PROPERTY, MEMBER_FUNCTION),
OPEN_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INTERFACE, MEMBER_PROPERTY, MEMBER_FUNCTION),
FINAL_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS, OBJECT, MEMBER_PROPERTY, MEMBER_FUNCTION),
SEALED_KEYWORD to EnumSet.of(CLASS_ONLY),
INNER_KEYWORD to EnumSet.of(CLASS_ONLY),
ABSTRACT_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INNER_CLASS, INTERFACE, MEMBER_PROPERTY, MEMBER_FUNCTION),
OPEN_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INNER_CLASS, INTERFACE, MEMBER_PROPERTY, MEMBER_FUNCTION),
FINAL_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INNER_CLASS, ENUM_CLASS, OBJECT, MEMBER_PROPERTY, MEMBER_FUNCTION),
SEALED_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS),
// We should have also CLASS_ONLY here because INNER_CLASS is not always perfectly identified
INNER_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS),
OVERRIDE_KEYWORD to EnumSet.of(MEMBER_PROPERTY, MEMBER_FUNCTION),
PRIVATE_KEYWORD to defaultVisibilityTargets,
PUBLIC_KEYWORD to defaultVisibilityTargets,
INTERNAL_KEYWORD to defaultVisibilityTargets,
PROTECTED_KEYWORD to EnumSet.of(CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS,
PROTECTED_KEYWORD to EnumSet.of(CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS,
MEMBER_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, MEMBER_PROPERTY, CONSTRUCTOR, TYPEALIAS),
IN_KEYWORD to EnumSet.of(TYPE_PARAMETER, TYPE_PROJECTION),
OUT_KEYWORD to EnumSet.of(TYPE_PARAMETER, TYPE_PROJECTION),
@@ -77,7 +78,7 @@ object ModifierCheckerCore {
VARARG_KEYWORD to EnumSet.of(VALUE_PARAMETER, PROPERTY_PARAMETER),
COMPANION_KEYWORD to EnumSet.of(OBJECT),
LATEINIT_KEYWORD to EnumSet.of(MEMBER_PROPERTY),
DATA_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS),
DATA_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS),
INLINE_KEYWORD to EnumSet.of(FUNCTION, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER),
NOINLINE_KEYWORD to EnumSet.of(VALUE_PARAMETER),
TAILREC_KEYWORD to EnumSet.of(FUNCTION),
@@ -88,8 +89,8 @@ object ModifierCheckerCore {
CONST_KEYWORD to EnumSet.of(MEMBER_PROPERTY, TOP_LEVEL_PROPERTY),
OPERATOR_KEYWORD to EnumSet.of(FUNCTION),
INFIX_KEYWORD to EnumSet.of(FUNCTION),
HEADER_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS),
IMPL_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, MEMBER_FUNCTION, TOP_LEVEL_PROPERTY, MEMBER_PROPERTY, CONSTRUCTOR, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS, TYPEALIAS)
HEADER_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE, CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS),
IMPL_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, MEMBER_FUNCTION, TOP_LEVEL_PROPERTY, MEMBER_PROPERTY, CONSTRUCTOR, CLASS_ONLY, OBJECT, INTERFACE, INNER_CLASS, ENUM_CLASS, ANNOTATION_CLASS, TYPEALIAS)
)
val featureDependencies = mapOf(
@@ -103,8 +104,8 @@ object ModifierCheckerCore {
LanguageFeature.Coroutines to LanguageFeature.ErrorOnCoroutines
)
val noWarningOnFeature = mapOf(
LanguageFeature.Coroutines to LanguageFeature.DoNotWarnOnCoroutines
val warningOnFeature = mapOf(
LanguageFeature.Coroutines to LanguageFeature.WarnOnCoroutines
)
val featureDependenciesTargets = mapOf(
@@ -120,16 +121,16 @@ object ModifierCheckerCore {
)
val possibleParentTargetMap = mapOf<KtModifierKeywordToken, Set<KotlinTarget>>(
INNER_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS),
OVERRIDE_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
INNER_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, ENUM_CLASS),
OVERRIDE_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
INTERFACE, ENUM_CLASS, ENUM_ENTRY),
PROTECTED_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS, COMPANION_OBJECT),
INTERNAL_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
PROTECTED_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, ENUM_CLASS, COMPANION_OBJECT),
INTERNAL_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
ENUM_CLASS, ENUM_ENTRY, FILE),
PRIVATE_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
PRIVATE_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
INTERFACE, ENUM_CLASS, ENUM_ENTRY, FILE),
COMPANION_KEYWORD to EnumSet.of(CLASS_ONLY, ENUM_CLASS, INTERFACE),
FINAL_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
FINAL_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
ENUM_CLASS, ENUM_ENTRY, ANNOTATION_CLASS, FILE)
)
@@ -168,13 +169,6 @@ object ModifierCheckerCore {
result += compatibilityForClassesRegister(PRIVATE_KEYWORD, ABSTRACT_KEYWORD)
result += incompatibilityRegister(CROSSINLINE_KEYWORD, NOINLINE_KEYWORD)
// 1. subclasses contained inside a sealed class can not be instantiated, because their constructors needs
// an instance of an outer sealed (effectively abstract) class
// 2. subclasses of a non-top-level sealed class must be declared inside the class
// (see the KEEP https://github.com/Kotlin/KEEP/blob/master/proposals/sealed-class-inheritance.md)
result += incompatibilityRegister(SEALED_KEYWORD, INNER_KEYWORD)
return result
}
@@ -299,8 +293,8 @@ object ModifierCheckerCore {
return false
}
val pairedNoWarningFeature = noWarningOnFeature[dependency]
if (pairedNoWarningFeature != null && !languageVersionSettings.supportsFeature(pairedNoWarningFeature)) {
val pairedWarningFeature = warningOnFeature[dependency]
if (pairedWarningFeature != null && languageVersionSettings.supportsFeature(pairedWarningFeature)) {
trace.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(node.psi, diagnosticData))
}

View File

@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.types.expressions.isWithoutValueArguments
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.check
class QualifiedExpressionResolver {
@@ -106,7 +107,7 @@ class QualifiedExpressionResolver {
val lastPart = qualifierPartList.last()
val classifier = when (qualifier) {
is PackageViewDescriptor -> qualifier.memberScope.getContributedClassifier(lastPart.name, lastPart.location)
is ClassDescriptor -> {
is ClassDescriptor -> {
val descriptor = qualifier.unsubstitutedInnerClassesScope.getContributedClassifier(lastPart.name, lastPart.location)
checkNotEnumEntry(descriptor, trace, lastPart.expression)
descriptor
@@ -206,7 +207,7 @@ class QualifiedExpressionResolver {
path: List<QualifierPart>,
lastPart: QualifierPart,
packageFragmentForVisibilityCheck: PackageFragmentDescriptor?
): ImportingScope? {
): SingleImportScope? {
val aliasName = KtPsiUtil.getAliasName(importDirective)
if (aliasName == null) {
// import kotlin.
@@ -214,23 +215,63 @@ class QualifiedExpressionResolver {
return null
}
val resolvedDescriptor = resolveToPackageOrClass(
val packageOrClassDescriptor = resolveToPackageOrClass(
path.subList(0, path.size - 1), moduleDescriptor, trace,
packageFragmentForVisibilityCheck, scopeForFirstPart = null, position = QualifierPosition.IMPORT
) ?: return null
val packageOrClassDescriptor = (resolvedDescriptor as? TypeAliasDescriptor)?.let { it.classDescriptor ?: return null } ?: resolvedDescriptor
return LazyExplicitImportScope(packageOrClassDescriptor, packageFragmentForVisibilityCheck, lastPart.name, aliasName) {
candidates ->
if (candidates.isNotEmpty()) {
storeResult(trace, lastPart.expression, candidates, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT, isQualifier = false)
}
else {
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
}
val candidates = collectCandidateDescriptors(lastPart, packageOrClassDescriptor)
if (candidates.isNotEmpty()) {
storeResult(trace, lastPart.expression, candidates, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT, isQualifier = false)
}
else {
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
return null
}
val importedDescriptors = candidates.filter { isVisible(it, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT) }.
check { it.isNotEmpty() } ?: candidates
return SingleImportScope(aliasName, importedDescriptors)
}
private fun collectCandidateDescriptors(lastPart: QualifierPart, packageOrClassDescriptor: DeclarationDescriptor): SmartList<DeclarationDescriptor> {
val descriptors = SmartList<DeclarationDescriptor>()
val lastName = lastPart.name
val location = lastPart.location
when (packageOrClassDescriptor) {
is PackageViewDescriptor -> {
val packageScope = packageOrClassDescriptor.memberScope
descriptors.addIfNotNull(packageScope.getContributedClassifier(lastName, location))
descriptors.addAll(packageScope.getContributedVariables(lastName, location))
descriptors.addAll(packageScope.getContributedFunctions(lastName, location))
}
is ClassDescriptor -> {
descriptors.addIfNotNull(
packageOrClassDescriptor.unsubstitutedInnerClassesScope.getContributedClassifier(lastName, location)
)
val staticClassScope = packageOrClassDescriptor.staticScope
descriptors.addAll(staticClassScope.getContributedFunctions(lastName, location))
descriptors.addAll(staticClassScope.getContributedVariables(lastName, location))
if (packageOrClassDescriptor.kind == ClassKind.OBJECT) {
descriptors.addAll(
packageOrClassDescriptor.unsubstitutedMemberScope.getContributedFunctions(lastName, location)
.map { it.asImportedFromObject() }
)
descriptors.addAll(
packageOrClassDescriptor.unsubstitutedMemberScope.getContributedVariables(lastName, location)
.filterIsInstance<PropertyDescriptor>()
.map { it.asImportedFromObject() }
)
}
}
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
}
return descriptors
}
private fun tryResolveDescriptorsWhichCannotBeImported(
@@ -303,6 +344,9 @@ class QualifiedExpressionResolver {
val location = KotlinLookupLocation(expression)
}
private enum class QualifierPosition {
PACKAGE_HEADER, IMPORT, TYPE, EXPRESSION
}
private fun resolveToPackageOrClass(
path: List<QualifierPart>,
@@ -359,7 +403,7 @@ class QualifiedExpressionResolver {
moduleDescriptor.quickResolveToPackage(path, trace, position)
var currentDescriptor: DeclarationDescriptor? = prefixDescriptor
for (qualifierPartIndex in nextIndexAfterPrefix..path.size - 1) {
for (qualifierPartIndex in nextIndexAfterPrefix .. path.size - 1) {
val qualifierPart = path[qualifierPartIndex]
val nextPackageOrClassDescriptor =
@@ -455,7 +499,7 @@ class QualifiedExpressionResolver {
)
if (result == null) return QualifiedExpressionResolveResult.UNRESOLVED
return when (index) {
return when(index) {
path.size -> QualifiedExpressionResolveResult(result, null)
path.size - 1 -> QualifiedExpressionResolveResult(result, path[index].name)
else -> QualifiedExpressionResolveResult.UNRESOLVED
@@ -596,12 +640,12 @@ class QualifiedExpressionResolver {
if (descriptor is DeclarationDescriptorWithVisibility) {
val fromToCheck =
if (shouldBeVisibleFrom is PackageFragmentDescriptor && shouldBeVisibleFrom.source == SourceElement.NO_SOURCE && referenceExpression.containingFile !is DummyHolder) {
PackageFragmentWithCustomSource(shouldBeVisibleFrom, KotlinSourceElement(referenceExpression.getContainingKtFile()))
}
else {
shouldBeVisibleFrom
}
if (shouldBeVisibleFrom is PackageFragmentDescriptor && shouldBeVisibleFrom.source == SourceElement.NO_SOURCE && referenceExpression.containingFile !is DummyHolder) {
PackageFragmentWithCustomSource(shouldBeVisibleFrom, KotlinSourceElement(referenceExpression.getContainingKtFile()))
}
else {
shouldBeVisibleFrom
}
if (!isVisible(descriptor, fromToCheck, position)) {
trace.report(Errors.INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.visibility, descriptor))
}
@@ -627,25 +671,21 @@ class QualifiedExpressionResolver {
return qualifier
}
}
internal fun isVisible(
descriptor: DeclarationDescriptor,
shouldBeVisibleFrom: DeclarationDescriptor?,
position: QualifierPosition
): Boolean {
if (descriptor !is DeclarationDescriptorWithVisibility || shouldBeVisibleFrom == null) return true
private fun isVisible(
descriptor: DeclarationDescriptor,
shouldBeVisibleFrom: DeclarationDescriptor?,
position: QualifierPosition
): Boolean {
if (descriptor !is DeclarationDescriptorWithVisibility || shouldBeVisibleFrom == null) return true
val visibility = descriptor.visibility
if (position == QualifierPosition.IMPORT) {
if (Visibilities.isPrivate(visibility)) return false
if (!visibility.mustCheckInImports()) return true
val visibility = descriptor.visibility
if (position == QualifierPosition.IMPORT) {
if (Visibilities.isPrivate(visibility)) return false
if (!visibility.mustCheckInImports()) return true
}
return Visibilities.isVisibleIgnoringReceiver(descriptor, shouldBeVisibleFrom)
}
return Visibilities.isVisibleIgnoringReceiver(descriptor, shouldBeVisibleFrom)
}
internal enum class QualifierPosition {
PACKAGE_HEADER, IMPORT, TYPE, EXPRESSION
}
/*

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2010-2015 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.resolve
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.BaseImportingScope
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.utils.Printer
class SingleImportScope(private val aliasName: Name, private val descriptors: Collection<DeclarationDescriptor>) : BaseImportingScope(null) {
override fun getContributedClassifier(name: Name, location: LookupLocation)
= if (name == aliasName) descriptors.filterIsInstance<ClassifierDescriptor>().singleOrNull() else null
override fun getContributedPackage(name: Name)
= if (name == aliasName) descriptors.filterIsInstance<PackageViewDescriptor>().singleOrNull() else null
override fun getContributedVariables(name: Name, location: LookupLocation)
= if (name == aliasName) descriptors.filterIsInstance<VariableDescriptor>() else emptyList()
override fun getContributedFunctions(name: Name, location: LookupLocation)
= if (name == aliasName) descriptors.filterIsInstance<FunctionDescriptor>() else emptyList()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= descriptors
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName, ": ", aliasName)
}
}

View File

@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
import org.jetbrains.kotlin.types.expressions.FakeCallResolver
import java.util.*
class CallCompleter(
@@ -61,6 +62,7 @@ class CallCompleter(
private val dataFlowAnalyzer: DataFlowAnalyzer,
private val callCheckers: Iterable<CallChecker>,
private val builtIns: KotlinBuiltIns,
private val fakeCallResolver: FakeCallResolver,
private val languageVersionSettings: LanguageVersionSettings,
private val compilerConfiguration: CompilerConfiguration
) {
@@ -84,7 +86,7 @@ class CallCompleter(
temporaryTrace.commit()
}
if (resolvedCall != null && context.trace.wantsDiagnostics()) {
if (resolvedCall != null) {
val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall)
resolvedCall.variableCall.call.calleeExpression
else
@@ -93,12 +95,10 @@ class CallCompleter(
if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression
else resolvedCall.call.callElement
val callCheckerContext = CallCheckerContext(context, languageVersionSettings, compilerConfiguration)
for (callChecker in callCheckers) {
callChecker.check(resolvedCall, reportOn, callCheckerContext)
if (resolvedCall is VariableAsFunctionResolvedCall) {
callChecker.check(resolvedCall.variableCall, reportOn, callCheckerContext)
if (context.trace.wantsDiagnostics()) {
val callCheckerContext = CallCheckerContext(context, languageVersionSettings, compilerConfiguration)
for (callChecker in callCheckers) {
callChecker.check(resolvedCall, reportOn, callCheckerContext)
}
}
}

View File

@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtExpression
@@ -41,8 +42,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object CoroutineSuspendCallChecker : CallChecker {
private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING)
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return
if (!descriptor.isSuspend) return
@@ -50,7 +49,7 @@ object CoroutineSuspendCallChecker : CallChecker {
val enclosingSuspendFunction =
context.scope
.parentsWithSelf.firstOrNull {
it is LexicalScope && it.kind in ALLOWED_SCOPE_KINDS &&
it is LexicalScope && it.kind == LexicalScopeKind.FUNCTION_INNER_SCOPE &&
it.ownerDescriptor.safeAs<FunctionDescriptor>()?.isSuspend == true
}?.cast<LexicalScope>()?.ownerDescriptor?.cast<FunctionDescriptor>()
@@ -96,7 +95,7 @@ fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, dia
else if (languageVersionSettings.supportsFeature(LanguageFeature.ErrorOnCoroutines)) {
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(reportOn, diagnosticData))
}
else if (!languageVersionSettings.supportsFeature(LanguageFeature.DoNotWarnOnCoroutines)) {
else if (languageVersionSettings.supportsFeature(LanguageFeature.WarnOnCoroutines)) {
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(reportOn, diagnosticData))
}
}

View File

@@ -56,15 +56,11 @@ import javax.inject.Inject
class TypeTemplate(
val typeVariable: TypeVariable,
val coroutineInferenceData: CoroutineInferenceData,
nullable: Boolean = true
) : FlexibleType(
typeVariable.originalTypeParameter.builtIns.nothingType,
typeVariable.originalTypeParameter.builtIns.anyType.makeNullableAsSpecified(nullable)
) {
val coroutineInferenceData: CoroutineInferenceData
) : FlexibleType(typeVariable.originalTypeParameter.builtIns.nothingType, typeVariable.originalTypeParameter.builtIns.nullableAnyType) {
override fun replaceAnnotations(newAnnotations: Annotations) = this
override fun makeNullableAsSpecified(newNullability: Boolean) = TypeTemplate(typeVariable, coroutineInferenceData, newNullability)
override fun makeNullableAsSpecified(newNullability: Boolean) = this
override val delegate: SimpleType
get() = upperBound

View File

@@ -17,15 +17,13 @@
package org.jetbrains.kotlin.resolve.calls.resolvedCallUtil
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -76,16 +74,29 @@ fun ResolvedCall<*>.getExplicitReceiverValue(): ReceiverValue? {
}
}
fun ResolvedCall<*>.getImplicitReceiverValue(): ImplicitReceiver? =
getImplicitReceivers().firstOrNull() as? ImplicitReceiver
fun ResolvedCall<*>.getImplicitReceiverValue(): ImplicitReceiver? {
return when (explicitReceiverKind) {
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> extensionReceiver ?: dispatchReceiver
ExplicitReceiverKind.DISPATCH_RECEIVER -> extensionReceiver
ExplicitReceiverKind.EXTENSION_RECEIVER -> dispatchReceiver
else -> null
} as? ImplicitReceiver
}
fun ResolvedCall<*>.getImplicitReceivers(): Collection<ReceiverValue> =
when (explicitReceiverKind) {
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> listOfNotNull(extensionReceiver, dispatchReceiver)
ExplicitReceiverKind.DISPATCH_RECEIVER -> listOfNotNull(extensionReceiver)
ExplicitReceiverKind.EXTENSION_RECEIVER -> listOfNotNull(dispatchReceiver)
ExplicitReceiverKind.BOTH_RECEIVERS -> emptyList()
}
fun ResolvedCall<*>.getImplicitReceivers(): Collection<ReceiverValue> {
if (this is VariableAsFunctionResolvedCall) {
val receivers = variableCall.getImplicitReceivers() + functionCall.getImplicitReceivers()
assert(receivers.size <= 3) { "There are ${receivers.size} for $this call" }
return receivers
}
return when (explicitReceiverKind) {
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> listOfNotNull(dispatchReceiver, extensionReceiver)
ExplicitReceiverKind.DISPATCH_RECEIVER -> listOfNotNull(extensionReceiver)
ExplicitReceiverKind.EXTENSION_RECEIVER -> listOfNotNull(dispatchReceiver)
ExplicitReceiverKind.BOTH_RECEIVERS -> emptyList()
}
}
private fun ResolvedCall<*>.hasSafeNullableReceiver(context: CallResolutionContext<*>): Boolean {
if (!call.isSafeCall()) return false

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