Compare commits

...

248 Commits

Author SHA1 Message Date
Dmitry Jemerov
caa2d7a6ce Add fix to changelog 2017-07-18 18:09:35 +02:00
Dmitry Jemerov
2bd989e563 Don't trigger update check when an in-memory file is modified
#KT-18954 Fixed

(cherry picked from commit 9b37e76)
2017-07-18 16:19:40 +02:00
Mikhael Bogdanov
85fe2ed537 Add 1.1.3-2 changes 2017-07-12 16:34:36 +02:00
Yan Zhulanow
68c3ce990e NoArg: Fix NoArgExpressionCodegenExtension loading in IDE 2017-07-04 17:18:41 +03:00
Yan Zhulanow
d74ffc83cf NoArg: Do not invoke initializers by default. Require "invokeInitializers" option to be set explicitly (KT-18667, KT-18668) 2017-07-03 19:20:34 +03:00
Yan Zhulanow
661fe23479 Kapt: Handle parameter with Java names clashing with Java keywords properly (KT-18377) 2017-07-03 19:20:33 +03:00
Mikhael Bogdanov
ff2a122c42 Delete local variables on default mask expantion
#KT-18792 Fixed

(cherry picked from commit 8666b95)
2017-07-03 17:07:57 +02:00
Mikhael Bogdanov
a362275b9e Preventively allocate slots for additional default parameters
Otherwise they are corrupted by inline

(cherry picked from commit 01e2f8e)
2017-07-03 17:02:57 +02:00
Nikolay Krasko
b6d3a175bf Do not compute class names for inline usages during stepping (KT-18411)
This was lost in "Debugger: Fix AbstractPositionManagerTest"(622430a29)

ExtraSteppingFilter: do not compute classNames for inline (f28f7eaa3b)

 #KT-18411 Fixed

(cherry picked from commit d8d862f)
2017-07-03 16:26:11 +03:00
Dmitry Jemerov
f27415f5e2 Optimize library kind detection and make it interruptible
(cherry picked from commit 8441873)
2017-07-03 12:04:37 +02:00
Dmitry Jemerov
2fb159f1d2 Remove unnecessary saveAll()
(cherry picked from commit 4497874)
2017-06-29 17:58:09 +02:00
Mikhael Bogdanov
852ace7973 Calculate default mask shift properly
#KT-18689 Fixed
2017-06-29 15:11:18 +02:00
Mikhail Glukhikh
44ec94c5f0 Protect getSingleAbstractMethodOrNull from data binding deadlock
Now it cannot cause resolve re-entrance
Probably #KT-18687 Fixed

(cherry picked from commit 6c274ce)
2017-06-28 20:22:09 +03:00
Alexey Andreev
99251b6d19 Fix performance issue in JS inliner
See KT-18679

(cherry picked from commit f6964b1)
2017-06-28 10:04:09 +03:00
Sergey Igushkin
450345b6c1 Add sourcesJar and javadocJar to artifacts of gradle-tools projects. 2017-06-23 15:58:20 +03:00
Alexey Tsvetkov
2fa9c149fc Revert Publish javadoc.jar and sources.jar for libraries projects built with Gradle
This reverts commit 9d2d9686a2
2017-06-23 15:54:53 +03:00
Alexey Tsvetkov
9d2d9686a2 Publish javadoc.jar and sources.jar for libraries projects built with Gradle
Maven central will not publish modules without these artifacts

(cherry picked from commit 72dd2e4)
2017-06-23 15:07:50 +03:00
Dmitry Jemerov
02bb353ed0 Changelog minor update 2017-06-21 14:26:20 +02:00
Dmitry Jemerov
3db81c6252 Fix incorrect merge of changelog 2017-06-21 14:12:39 +02:00
Dmitry Jemerov
af3c0591b7 Regenerate changelog for 1.1.3 2017-06-21 13:52:11 +02:00
Ilya Chernikov
ce79c6c7d9 Fix compatibility with renamed Gradle Kotlin DSL 2017-06-21 11:32:38 +02:00
Alexander Udalov
5c481a0923 Avoid NPE at UtilKt.toJavaClass for unrecognized classes
Sadly, the case where this NPE would reproduce, remains unknown

 #KT-18494 Fixed
2017-06-20 12:43:07 +03:00
Mikhail Glukhikh
61cb5983bb Update changelog (1.1.3-eap-85) 2017-06-16 16:00:36 +03:00
Alexey Sedunov
d06af126d8 Kotlin Facet: Fix detection of source set name by Gradle compile task
#KT-17492 Fixed

(cherry picked from commit 36a4565)
2017-06-14 23:12:13 +03:00
Dmitry Jemerov
ede2acd465 Reset library caches on file types change and dumb mode enter/exit
Ref: 50df476199

(cherry picked from commit a2427c6)
2017-06-14 18:10:49 +02:00
Dmitry Jemerov
f2ecdab6d1 Add actions for toggling type hints to list of irrelevant actions
They are available in many tests and only starting with  the 172 branch,
 so we ignore them to reduce clutter and branch divergence.

(cherry picked from commit 52cfec5)
2017-06-13 20:24:39 +02:00
Alexey Sedunov
ab618418cd Presentation: Fix NPE on star projection rendering
EA-100480 Fixed

(cherry picked from commit 8d08022)
2017-06-13 19:52:34 +03:00
Dmitry Jemerov
ecdba7d0fd Show more correct type hints
- Don't show hints containing error type as type parameter
 - Do not expand type aliases
 - Show base type for types of anonymous objects

 #KT-18369 Fixed
 #KT-18341 Fixed
 #KT-18343 Fixed

(cherry picked from commit 8077a71)
2017-06-13 15:30:55 +02:00
Dmitry Jemerov
4d21631868 typo 2017-06-12 19:19:50 +02:00
Dmitry Jemerov
73673dbc72 Sort plugins before uploading 2017-06-12 19:10:33 +02:00
Alexey Sedunov
96a84900dc Kotlin Facet: Fix facet existence check during Gradle import
EA-101476 Fixed

(cherry picked from commit 07a733c)
2017-06-12 16:35:49 +03:00
Pavel V. Talanov
e2b2d22b49 Use clsDelegate to calculate hasModifierProperty("final") for light psi
AllOpen plugin can make some changes and we don't have the tools to make
    correct decision based on psi

 #KT-17857 Fixed
2017-06-08 16:57:22 +03:00
Pavel V. Talanov
8cafb80291 KtLightMemberModifierList:hasExplicitModifier("default") returns false
#KT-18070 Fixed
2017-06-08 16:57:02 +03:00
Dmitry Neverov
6fde1efb79 Property accessor isn't recursive when called on another object
So #KT-18120 Fixed

(cherry picked from commit e2aa351)
2017-06-08 16:28:55 +03:00
Sergey Igushkin
4490b9b6e3 (minor) Improve exception message in case no Android plugin was found
(cherry picked from commit df3b8e8)
2017-06-06 16:49:44 +03:00
Sergey Igushkin
8da583458f Fix for the Databinding issue where the kapt task started too early, not
letting the Databinding pre-process the project.

(cherry picked from commit efffda2)
2017-06-06 16:49:29 +03:00
Sergey Igushkin
c42fa4b309 Add support for com.android.feature plugin.
(cherry picked from commit 495f4b1)
2017-06-06 16:49:15 +03:00
Alexey Andreev
98441430a8 Update changelog 2017-06-06 11:42:11 +03:00
Yan Zhulanow
d7601eccdf Kapt: Fix output file reporting in IC
Fix REPORT_OUTPUT_FILES option passing to GenerationState created in kapt.

This fixes these tests:
Kapt3Incremental.testChangeAnnotatedPropertyType()
Kapt3Incremental.testRemoveAnnotations()
Kapt3Incremental.testRemoveSourceFile()
2017-05-31 16:15:24 +03:00
Alexey Tsvetkov
c7ce1b6a45 Run Gradle Android tests with other Gradle tests 2017-05-31 16:15:23 +03:00
Alexey Tsvetkov
87f495a9d5 Add tests with new Android Gradle Plugin 2017-05-31 16:14:44 +03:00
Sergey Igushkin
3bae7ec17f Fix UnsupportedOperationException caused by mutation of FileCollection 2017-05-31 16:14:44 +03:00
Sergey Igushkin
281756bd7f Migration to AGP 2.3.0 2017-05-31 16:14:44 +03:00
Sergey Igushkin
71eff5c469 Further fixes for Android tests on TeamCity
Added support repository to download_android_sdk.xml
Changed the build tools version in testProject to 23.0.1

(trial) Remove platform 22
2017-05-31 16:14:44 +03:00
Sergey Igushkin
30962096c9 Got rid of the sdk-manager plugin. 2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
416822c0c4 Fix failing Gradle tests
* Extract ANDROID_HOME_PATH constant
* Set ANDROID_HOME_PATH to dependencies/androidSDK
* Running download_android_sdk.xml is now needed to run Gradle Integration Tests
* Modify download_android_sdk.xml so that tools/android is executable

(cherry picked from commit 75a6e37)
2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
dae98dbc90 Gradle: set default values of languageVersion and apiVersion to null
Before the change, Gradle always explicitly set language and api
version to the latest version, preventing the compiler
from inferencing the arguments.

     #KT-18047 fixed
2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
d9315fef92 Set destination to null when module is set in JPS
This fixes the warning "The '-d' option with a directory destination
is ignored because '-module' is specified", when a project imported
from Gradle is built with JPS.

    #KT-17665 fixed
2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
fd2c36a6de Stabilize test of Gradle's daemon for memory leaks
We need to wait for GC to finish, because GC can be concurrent
2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
704f1dc36f Report memory usage only when system property is set
This improves performance of Gradle builds with debug logging (--debug),
because System.gc is now forced only when the system property
'kotlin.gradle.test.report.memory.usage' is set.

    #KT-17960 fixed
2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
16ac28c92a Improve test error message 2017-05-31 16:14:44 +03:00
Alexey Tsvetkov
91dce10322 Limit max number of active Gradle processes for the test run
This is needed to avoid retaining memory by each Gradle version
which is critical for running tests on CI server.
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
998469f0bf Refactor Gradle ITs so any Gradle wrapper version can be used
This change:
* fixes tests with missing (in branch 1.1.3) GradleWrapper-3.4
* enables using any Gradle version in integration tests
without adding a new GradleWrapper-<version> dir.

The only difference between wrappers is in a version
number in a `gradle-wrapper.properties` file.
I removed all but one wrappers from `test/resources`,
and replaced the version with the template token <GRADLE_WRAPPER_VERSION>
for the remaining wrapper.
During a test run a template wrapper for each required version
is copied to a temporary directory.
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
3bc48d0523 Minor: add .gitignore for gradle-tools 2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
dc3ee96170 Fix tests for coroutines setting in Gradle
ArgumentUtils#convertArgumentsToStringList does not
serialize an argument with default value,
so the string "-Xcoroutines=warn" was no longer present in logs.
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
c37f104e4c Refactor kapt tasks' wiring
* Unify tasks wiring for new and old Android Gradle Plugin
* rename wireKaptTask->registerGeneratedJavaSource
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
4ab8ffd874 Pass task object instead of task name to dependsOn
This simplifies filtering out dependsOn later
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
7bc8458ea4 Remove most of Gradle tests with Jack
Jack is deprecated and Kotlin Gradle plugin throws,
so one test checking that build is failing with the exception
is enough.
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
7852050139 Minor: simplify expression 2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
62b290f96e Simplify friend paths configuration 2017-05-31 16:14:43 +03:00
Sergey Igushkin
b037fca737 Various fixes
* Expose internals as public to use them in the agp25 source set
* Refactor of Android25ProjectHandler.kt
* Fix Kapt3 for non-Android projects
2017-05-31 16:14:43 +03:00
Sergey Igushkin
77f9571dc9 Fix Kapt task depending on compileKotlin because of incorrect filtering
of compileJava dependencies

(cherry picked from commit 9a2c3b0)
2017-05-31 16:14:43 +03:00
Alexey Tsvetkov
6eddf9a36c Update gradle wrapper permissions
It was not executable on linux
2017-05-31 16:14:43 +03:00
Sergey Igushkin
cd6b2e0c28 Use the Google Maven repository instead of local preview.
(cherry picked from commit 4279335)

(cherry picked from commit 0e8b850)
2017-05-31 16:14:43 +03:00
Sergey Igushkin
7f0234f941 (minor) Fix missing dependency on JUnit
(cherry picked from commit 7ad5d04)
2017-05-31 16:14:43 +03:00
Sergey Igushkin
3c42a2db82 Fix friend paths configuration with the new API for compile*Test tasks
Add lazy `friendClasspathEntries` to KotlinCompile
Set `friendClasspathEntries` in the Android25Pro
Change to AGP 3.0.0-alpha1;

(cherry picked from commit 1d6dd5c)

(cherry picked from commit 6cdf501)
2017-05-31 16:14:43 +03:00
Sergey Igushkin
f44b9f0cab Fix registering the non-existent Kapt3 classes directory as bytecode if
Kapt3 is disabled.

(cherry picked from commit 692e23c)

(cherry picked from commit 1cbdb6c)
2017-05-31 16:14:43 +03:00
Sergey Igushkin
aab041b086 Change the legacy API threshold to 2.5.0
(cherry picked from commit fca2e23)

(cherry picked from commit 9394d15)
2017-05-31 16:14:43 +03:00
Sergey Igushkin
310a531f49 Tasks wiring improvements & Kapt3 integration through variant wrapping 2017-05-31 16:14:43 +03:00
Sergey Igushkin
ec01bfe7e2 Task wiring
* Generalized tasks wiring
* Moved the old implementation to LegacyAndroidAndroidProjectHandler.kt
* Added an implementation with the new AGP API

(cherry picked from commit 1b4592d)

(cherry picked from commit 50a75d4)
2017-05-31 16:14:42 +03:00
Sergey Igushkin
5cd9af4860 Add prototype against the new AGP API
* Add a separate Gradle source set, that is compiled against the new
  versions of AGP and Gradle

* Separate the public AGP API usages from the old internal API usages
  in KotlinPlugin.kt -- see AbstractAndroidProjectHandler

* Implement Android25ProjectHandler with the new AGP API, wired it
  to KotlinAndroidPlugin through reflection

(cherry picked from commit e6dbf54)

(cherry picked from commit 88e3d4b)
2017-05-31 16:14:42 +03:00
Alexander Udalov
f6581740d8 Improve modular JDK root module detection
According to the spec, "java.se" and every other non-"java.*" module
that exports at least one package without qualification, is a root.
Currently we only support compilation of a single unnamed module, and
apparently unnamed module should read all root modules.

 #KT-18180 Fixed

(cherry picked from commit 1572d2cf2b)
2017-05-31 12:26:13 +03:00
Alexander Udalov
e820bd1c17 Move JavaModuleInfo and JavaModuleGraph to frontend.java
(cherry picked from commit a583a2f171)
2017-05-31 12:02:34 +03:00
Simon Ogorodnik
16e0f0787e Fix IfThenToSafeAccessIntention broken by refactoring
Broken in 66c5717adc

(cherry picked from commit d617b1d)
2017-05-29 19:15:09 +03:00
Yan Zhulanow
837eee3af1 Kapt: Write @kotlin.Metadata annotation to Java stubs #KT-17937 2017-05-25 21:54:58 +03:00
Yan Zhulanow
a6ddef102c Minor: Commit forgotten kapt test data 2017-05-25 21:54:51 +03:00
Alexander Udalov
90c6536256 Fix compilation against JRE 9 on JPS
Write the modular JDK (9+) path to the module.xml file passed to the
compiler from the JPS plugin. This path is then recorded in the compiler
configuration in KotlinToJVMBytecodeCompiler.configureSourceRoots. This
is needed because in JPS plugin, we pass "-no-jdk" and thus no JDK home
path was recorded in the compiler configuration in
K2JVMCompiler.setupJdkClasspathRoots. Presence of JDK home path in the
configuration is crucial for JDK 9 support (see
KotlinCoreEnvironment.Companion.createApplicationEnvironment), because
classes there can only be loaded with the special "jrt" file system, not
as .class files in .jar files

 #KT-17801 Fixed

(cherry picked from commit 965b4199f4)
2017-05-24 17:00:47 +03:00
Alexander Udalov
420b164488 Use environment variable JDK_19 instead of JDK_9
JDK_19 is set on TeamCity agents, not JDK_9.

Also do not invoke getJreHome() because Java 9 distribution does not
have a "jre" subdirectory

(cherry picked from commit f8dabc79c3)
2017-05-24 17:00:45 +03:00
Dmitry Jemerov
84950435e8 Remove incorrect argument count check from TODO searcher
(cherry picked from commit 4f08d2b)
2017-05-23 18:37:38 +02:00
Ilya Chernikov
7cdc7ce2ce Introduce other JVM options inheritance for daemon 2017-05-23 17:44:26 +02:00
Ilya Chernikov
8eea008a65 Fix daemon selection on the memory settings 2017-05-23 17:44:25 +02:00
Ilya Chernikov
bfa97eef25 minor: log daemon client registration 2017-05-23 17:44:24 +02:00
Ilya Chernikov
c60cf28674 Reuse daemon launching logic for out-of-process compilation in gradle 2017-05-23 17:44:24 +02:00
Ilya Chernikov
4895625e24 Improve daemon client diagnostic and run failure detection
Removing prefiltering of the daemon client reporting - filtering should
be performed on the receiver site. And put daemon process output during
executioninto INFO category. May make daemon usage more talkative,
but will not eat important error messages anymore.
Add test with failure condition.
Also failed daemon start should not cause timeout anymore.
2017-05-23 17:44:23 +02:00
Ilya Chernikov
d5cf6a946f Refactor daemon tests, some minor fixes in the client and daemon
Tests refactored for better readability and code reuse
Some shutdown livelock is fixed
Some logging added
2017-05-23 17:44:22 +02:00
Yan Zhulanow
f303a89aac Kapt: Filter the content root items for the compile classpath properly 2017-05-23 18:35:31 +03:00
Yan Zhulanow
6d951acc68 Kapt: Preserve parameter names for abstract methods (KT-17959) 2017-05-23 18:35:31 +03:00
Yan Zhulanow
83e59c9a7e Android Extensions: Remove obsolete migration warning in Gradle plugin 2017-05-23 18:35:30 +03:00
Yan Zhulanow
d852ca9752 Kapt3: Ignore packages with Java keywords inside (KT-17184) 2017-05-23 18:35:29 +03:00
Yan Zhulanow
900959f359 Kapt3: Fix flaky integration tests on Windows agents 2017-05-23 18:35:28 +03:00
Alexey Sedunov
550c4f9ff9 Kotlin Facet: Do not rewrite v2 configuration to latest version
This causes unwanted changes in configuration files
after plugin update

(cherry picked from commit 151b512)
2017-05-23 13:50:39 +03:00
Alexey Sedunov
3a5d464777 Configuration: Use project-level JVM target when facet is absent
#KT-17722 Fixed

(cherry picked from commit 6049bb8)
2017-05-23 13:50:38 +03:00
Alexey Sedunov
0acf6f90c8 Kotlin Facet: Filter out API versions exceeding library version
Also drop version validator as it's not needed anymore
 #KT-17847 Fixed

(cherry picked from commit 23c0e6f)
2017-05-23 13:50:37 +03:00
Alexey Sedunov
60c5d6ddb3 Kotlin Facet: Configure facet if kotlin-android plugin is present
#KT-17861 Fixed

(cherry picked from commit d288c68)
2017-05-23 13:50:36 +03:00
Alexey Sedunov
f972e1a024 Kotlin Facet: Suppress bogus warning about language/api version
#KT-17848 Fixed

(cherry picked from commit 8f6f69d)
2017-05-23 13:50:35 +03:00
Alexey Sedunov
c9f13ef30e Presentation: Fix NPE on functional type rendering
#KT-17638 Fixed

(cherry picked from commit 0994474)
2017-05-23 13:50:34 +03:00
Pavel V. Talanov
ea7eb50b73 Cache GSScope by dependencies in ScriptDependencyModuleInfo
Removing state in previous commit led to 'toVfsRoots' being called to often
2017-05-22 19:30:23 +03:00
Pavel V. Talanov
c835615111 Avoid caching state in ScriptModuleInfos
This led to caching stale dependencies

 #KT-17770 Fixed
2017-05-22 19:28:03 +03:00
Anton Bannykh
2cd139a80e JS: fix char to string convertion in string templates (#KT-17966 fixed)
(cherry picked from commit 419f12f1b7)
2017-05-22 16:04:16 +03:00
Simon Ogorodnik
732ac1afec Fix CCE in constructNestedClassReferenceIdentifier J2K
#KT-17712 fixed

(cherry picked from commit 6a8bb8b)
2017-05-22 14:03:26 +03:00
fitermay
d284e21fea Fix keyword completion in 'if' blocks
#KT-17914 fixed

(cherry picked from commit d0991ff)
2017-05-22 14:03:09 +03:00
Mikhail Glukhikh
68838b0279 Don't suggest making interface member final
(which was possible in leaking this inspection)
So #KT-14443 Fixed

(cherry picked from commit 17869ab)
2017-05-22 09:58:21 +03:00
Mikhail Glukhikh
53fe147f14 Don't suggest make object container open #KT-11003 Fixed
(cherry picked from commit a73cf0e)
2017-05-22 09:58:08 +03:00
Dmitry Neverov
244c0de760 Detect recursive property accessors #KT-17221 Fixed
(cherry picked from commit 3b4dafe)
2017-05-22 09:57:57 +03:00
Ilya Gorbunov
e59fec0f80 preparePublication task requires project version to be set
(cherry picked from commit fec8f4a)
2017-05-19 23:07:17 +03:00
Ilya Gorbunov
6ae4b885c7 Refactor: use sam-like constructor for comparators
(cherry picked from commit 2500a18)
2017-05-19 22:50:12 +03:00
Ilya Gorbunov
6a15981b3a Do not use spread-operator when it causes excessive array copying
(cherry picked from commit ddf6599)
2017-05-19 22:50:12 +03:00
Gaetan Zoritchak
10c85a6add KT-17853: Kotlin.js switched parameters of Math.atan2
https://youtrack.jetbrains.com/issue/KT-17853
The current exposition of the JavaScript [Math object] switched the parameters names.
The correct version is `atan2(y,x)`.

(cherry picked from commit c00918c)
2017-05-19 22:50:12 +03:00
Ilya Gorbunov
50834f9a45 Clarify ReentrantReadWriteLock.write behavior regarding upgrade from read to write lock
#KT-17704 Fixed

(cherry picked from commit 9953efc)
2017-05-19 22:50:12 +03:00
Ilya Gorbunov
06423ff0f6 Add samples for contentToString and contentDeepToString array operations
(cherry picked from commit ef72371)
2017-05-19 22:50:12 +03:00
Marek Langiewicz
3dd54719d9 Fix List.takeLast for lists without RandomAccess
(cherry picked from commit 934b0b8)
2017-05-19 22:50:12 +03:00
Ilya Gorbunov
8167f6f936 Document IllegalArgumentException thrown from string-number conversion
functions when an invalid radix is specified
#KT-17635 Fixed

(cherry picked from commit 8da4839)
2017-05-19 22:50:12 +03:00
Dmitry Jemerov
64462a17f6 Add module documentation for kotlin.test
(cherry picked from commit 927cd04)
2017-05-19 19:51:59 +02:00
Dmitry Jemerov
fa2b68e928 Show calls of TODO() function in TODO view
#KT-8617 Fixed

(cherry picked from commit ded5bfb)
2017-05-19 18:28:16 +02:00
Simon Ogorodnik
7eaf28bc2a Check for batch PSI children update when invalidating package cache
#KT-17868 fixed

(cherry picked from commit dba9011)
2017-05-19 13:12:02 +03:00
Mikhael Bogdanov
0c2de4865b Wrap captured local delegated property into Delegate
#KT-16864 Fixed
2017-05-19 10:43:19 +02:00
Dmitry Petrov
e37729bf7a Fix incremental compilation problems related to type alias constructors
1. Determine source element for descriptors with NO_SOURCE recursively.

2. Always provide type abbreviation for type alias constructor
return type.

 #KT-15495 Fixed
2017-05-19 11:24:53 +03:00
Dmitry Jemerov
5abfba4593 Show location for local classes in Goto Class
#KT-7954 Fixed

(cherry picked from commit f6574a4)
2017-05-18 21:08:02 +02:00
Dmitry Jemerov
d19cf32392 Cleanup code style option names
#KT-14639 Fixed

(cherry picked from commit 232af8a)
2017-05-18 21:07:55 +02:00
Dmitry Jemerov
0e974cc49f Build stubs for local functions; show them in Goto Symbol
#KT-14161 Fixed

(cherry picked from commit 4dd3f30)
2017-05-18 21:07:38 +02:00
Dmitry Jemerov
820dfd3eaf Use provided file content in KotlinJsMetadataVersionIndex
#KT-17821 Fixed

(cherry picked from commit f72dd75)
2017-05-18 21:07:09 +02:00
Dmitry Jemerov
7f7cf3fb14 Don't show disambiguation for "Show expression type" on "this"
#KT-17840 Fixed

(cherry picked from commit af04384)
2017-05-18 21:06:52 +02:00
Dmitry Jemerov
5345858cbe Find Usages on "override val" in constructor asks about base usages
Also fix long-standing bug with "title" parameter being ignored when
displaying messages

 #KT-17845 Fixed

(cherry picked from commit 2cbb8d0)
2017-05-18 21:06:37 +02:00
Dmitry Jemerov
9266ca260f Indicate vararg parameters in Goto Symbol presentation
#KT-17899 Fixed

(cherry picked from commit 8f38d03)
2017-05-18 21:06:22 +02:00
Dmitry Jemerov
8d4648951a Fix stdlib-jre7/8 configuration in new projects
#KT-17875 Fixed
 #KT-17876 Fixed

(cherry picked from commit f113a5c)
2017-05-18 21:06:13 +02:00
Dmitry Jemerov
a1ea6e026d Don't highlight 'this' references as deprecated
#KT-17613 Fixed

(cherry picked from commit 675305f)
2017-05-18 21:05:54 +02:00
Alexander Udalov
aa79a0a7b1 Support single Java source files in kotlinc arguments
E.g. "kotlinc foo.kt test/Bar.java" will compile foo.kt, and
declarations from Bar.java will be accessible to Kotlin code in foo.kt.

The change in AbstractTopLevelMembersInvocationTest is needed because an
incorrect configuration was created in that test where a library jar was
also a Java source root (the compiler is never configured this way in
production), which led to an exception in
JavaCoreProjectEnvironment#addSourcesToClasspath

 #KT-17697 Fixed

(cherry picked from commit 671aed252d)
2017-05-18 19:24:02 +03:00
Pavel V. Talanov
e0b6180fde IDE Performance: skip resolver construction for non-relevant modules
Querying non-existent packages does not trigger module resolver computation
2017-05-18 18:13:47 +03:00
Pavel V. Talanov
fd715917a5 Test not creating resolvers for modules that have no relevant packages 2017-05-18 18:13:45 +03:00
Pavel V. Talanov
68944aca29 Minor: refactor PerModulePackageCacheService 2017-05-18 18:13:42 +03:00
Pavel V. Talanov
9bace18109 Light classes: test extending Number and CharSequence 2017-05-18 18:13:40 +03:00
Pavel V. Talanov
4f0f5212b6 Make sure java completion doesn't suggest classes from builtIns
Fix an undesirable sideeffect of previous changes
2017-05-18 18:13:37 +03:00
Pavel V. Talanov
fb76e5dacd Use wrappers around java.util.* to emulate kotlin.collection.* behaviour
Backend: If kotlin class extends kotlin.collection.List
    write it as it's super interface (light class mode only)
IDE: Provide wrapper classes to java resolve
    that try to emulate backend behaviour

For example if kotlin class implements kotlin.collections.Map,
    we provide a superinterface that has abstract 'getEntries' method
    and 'entrySet' method that is considered default.
In reality all those methods are generated in the class itself.

In IDE supporting this case without hacks is not feasible performance-wise
    since kotlin.collection.* may not be an immediate supertype and we need
    to compute all supertypes just to calculate own methods of the class
2017-05-18 18:13:35 +03:00
Pavel V. Talanov
a497bc3e78 Do not generate bridge and stub methods in light class mode 2017-05-18 18:13:32 +03:00
Pavel V. Talanov
38fa163ee9 Jvm backend: specify declaration origin of generated methods
Allow to distinguish collection stub methods and augmented kotlin api methods
2017-05-18 18:13:30 +03:00
Pavel V. Talanov
088fef14a1 Refactor constructing KOTLIN_MARKER_INTERFACES map 2017-05-18 18:13:28 +03:00
Pavel V. Talanov
8a615c017b J2K class map: expose classes having mutable/readonly kotlin equivalents
Refactor JavaToKotlinClassMap a little bit
2017-05-18 18:13:25 +03:00
Pavel V. Talanov
e07f7ebd2f J2K JavaToKotlinClassMap 2017-05-18 18:13:23 +03:00
Pavel V. Talanov
08a317ea39 Light classes, minor: introduce cannotModify() utility 2017-05-18 18:13:20 +03:00
Anton Bannykh
839834b6a8 JS: fix char boxing in elvis expressions (#KT-17700 fixed)
(cherry picked from commit e098de5e33)
2017-05-18 16:20:01 +03:00
Anton Bannykh
475ba68e57 JS: unmute box/test/coroutinessuspendFunctionAsCoroutine/inlineTwoReceivers.kt
(cherry picked from commit 7503376731)
2017-05-18 16:13:19 +03:00
Anton Bannykh
26a0a9fee8 Updated some tests to expect the new '-Xfoo=bar' advanced options syntax
(cherry picked from commit 503891846f)
2017-05-18 16:12:51 +03:00
Anton Bannykh
dc1e05c10a Prevent 'obsolete form' warnings by passing advanced (-X) arguments using the '-Xfoo=bar' syntax
(cherry picked from commit 9bd562bf67)
2017-05-18 16:11:37 +03:00
Anton Bannykh
cb9f5653f4 JS: support internal visibility from friend modules
Friend modules should be provided using the -Xfriend-modules flag
in the same format as -libraries. No manual configuration required for
JPS, Gradle and Maven plugins.

Friend modules could be switched off using the -Xfriend-modules-disabled
flag. Doing that will
  * prevent internal declarations from being exported,
  * values provided by -Xfriend-modules ignored,
  * raise a compilation error on attemps to use internal declarations from other modules

Fixes #KT-15135 and #KT-16568.

(cherry picked from commit 2e9a59819a)
2017-05-18 16:10:14 +03:00
Sergey Igushkin
e2f959ca24 Fix main and test compilation tasks having different module name in
free compiler args.

(cherry picked from commit 74288ff)
2017-05-18 15:54:53 +03:00
Sergey Igushkin
55ee07b877 Unify build output with Maven
* Added manifest properties to `gradle-tools` projects.
* Add `-kotlin-module` to free compiler args to make the module names
  match the ones in Maven build
* Fixed path to the Groovy sources in `kotlin-gradle-plugin/pom.xml`

(cherry picked from commit 7097246)
2017-05-18 15:54:53 +03:00
Sergey Igushkin
f10480a028 Fix rootDir mis-use in commonConfiguration.gradle:
replace with `kotlin_root`, that is set in the projects

(cherry picked from commit 7030b89)
2017-05-18 15:54:53 +03:00
Sergey Igushkin
a498c7b7a7 Gradle build fixes & improvements:
* Fix Java not compiled in kotlin-gradle-plugin Kotlin source set
* Fix the integration tests running under Java 6
* Fix kotlin-gradle-subplugin-example not being installed -- needed
  for a test
* Fix Android tests being always excluded
* Move versions out of `build.gradle` (x2) to a common `versions.gradle`
* Move JDK, dist and bootstrap to `commonConfiguration.gradle`
* Build `kotlin-gradle-plugin` with JDK_18

(cherry picked from commit c3ae37c)
2017-05-18 15:54:53 +03:00
Sergey Igushkin
fc56737f43 Gradle plugins migration to Gradle build
* Add gradle-tools subproject
* Add Gradle buildscripts to the related projects
* Remove the projects from the libraries pom.xml
* Move AndroidGradleWrapper.groovy to separate source root
* Changed artifact dependencies to project dependencies where needed
* Extract common configuration into commonConfiguration.gradle
* (convert functions to closures to be able to call them)
* Refactor DSL usage
* Replace `project.properties` with `findProperty`
* Unify Gradle wrapper between `libraries` and `gradle-tools`
(as a temporary solution, just made the wrapper files the same)

(cherry picked from commit 8e65b5f)
2017-05-18 15:54:52 +03:00
Alexander Udalov
ffafe89d8c Do not try to load Java classes from incorrect packages
#KT-11474 Fixed

(cherry picked from commit bfb3b38ebc)
2017-05-18 13:36:33 +03:00
Dmitry Neverov
5e5c280323 Make semicolon in loop with empty body not redundant
So #KT-12805 Fixed

(cherry picked from commit bf4e69e)
2017-05-18 12:57:19 +03:00
Alexey Tsvetkov
ed6cfe3167 Ensure output directory exists when adding it to classpath
Otherwise a warning is reported:
"Сlasspath entry points to a non-existent location".
Currently it only affects Maven + IC.
2017-05-16 20:22:24 +03:00
Alexey Tsvetkov
6697811244 Do not print OUTPUT message as warning in Maven
Before the change Maven + IC had been reporting OUTPUT
messages as warnings since OUTPUT was removed
from CompilerMessageSeverity.VERBOSE
2017-05-16 20:22:24 +03:00
Denis Zharkov
69f99cb733 Revert "Turn off fast class reading to avoid problems with IC"
This reverts commit 8a97a24c9a.
2017-05-16 18:26:52 +03:00
Denis Zharkov
875936eefb Use allScope when resolving classifiers of binary classes 2017-05-16 18:08:02 +03:00
Alexey Tsvetkov
8a97a24c9a Turn off fast class reading to avoid problems with IC
It seems that fast class reading is somehow connected to
problems with incremental compilation when the compiler
reports "unresolved supertypes" (e.g `java.lang.Object` in KT-17897)
on previously compiled code.

Turning off fast class reading seems to "fix" the problem,
so I'm turning it off temporarily until a root cause is discovered.
2017-05-16 16:32:09 +03:00
Dmitry Jemerov
3ae62cb3f7 Fix exception on new file creation when no file template is defined
#KT-17906 Fixed

(cherry picked from commit 63d32a5)
2017-05-16 12:06:09 +02:00
Yan Zhulanow
342cba9ac1 Allopen, Gradle: Fix JPS build on Windows (KT-17830)
Appears that plugin classpath can contain not only `File.separatorChar`, but also '/' on Windows. Without the proper handling of this case, Gradle importer may import the plugin JAR made for Gradle with shaded 'com.intellij' and cause an exception during the JPS build.
2017-05-15 14:42:44 +03:00
Sergey Mashkov
b2becc8b3b KT-10028 Support parallel builds in maven
Mark mojo's as thread safe as users confirmed that all related errors
seem to be fixed
2017-05-15 12:56:34 +03:00
Alexander Udalov
52a71ec0b0 Support .jar archives in friend paths (for internal visibility)
(cherry picked from commit 939f969f12)
2017-05-15 12:21:21 +03:00
Simon Ogorodnik
e1cdfeb533 Use ModalityState.any() for J2K post processing
#KT-17870 fixed

(cherry picked from commit a0a6ef4)
2017-05-12 17:59:31 +03:00
Dmitry Jemerov
979a5b866b Improve diagnostics for EA-100849
KNPE: DeserializerForClassfileDecompilerKt.DeserializerForClassfileDecompiler

(cherry picked from commit f53b9aa)
2017-05-12 12:42:47 +02:00
Dmitry Jemerov
a17fde20e0 EA-100074 - SOE: ExpressionsOfTypeProcessor.containsTypeOrDerivedInside
(cherry picked from commit db1f8c7)
2017-05-12 12:42:47 +02:00
Dmitry Jemerov
60af17dc45 EA-101095 NSEE: KotlinUsageToPsiElementProvider.getAppropriateParentFrom)
(cherry picked from commit ddcde3f)
2017-05-12 12:42:47 +02:00
Dmitry Jemerov
61a2b63046 Revert "Deprecated setting was used for import optimization on the fly. (#1049)"
This reverts commit 75d231cc37.
The added API is available only in IDEA 2017.1.1, not in the original 2017.1 build.

(cherry picked from commit 4e58319)
2017-05-12 12:42:47 +02:00
Mikhail Glukhikh
a96adab791 Don't suggest "if to ?." without else when used in expression position
(cherry picked from commit a1e00ed)
2017-05-12 11:37:49 +03:00
Mikhail Glukhikh
7771e1ed18 Use "if-then to" even for 'if (arg != null) arg' removing 'if'
(cherry picked from commit 326d850)
2017-05-12 11:37:38 +03:00
Mikhail Glukhikh
825de4f4b4 If to safe access: fix message when no dot calls are available
Now "Replace 'if' with safe cast" is suggested

(cherry picked from commit 977d8e1)
2017-05-12 11:37:29 +03:00
Mikhail Glukhikh
e0217e2a7f Change both IfThenTo... inspections highlight level
Retain WEAK WARNING for null checks, one-liners,
and is checks without dot calls in main branch.
Set INFORMATION (no highlighting, just fix) for other cases.

Switch off both bound intentions.
So #KT-15076 Fixed

(cherry picked from commit a77390c)
2017-05-12 11:37:19 +03:00
Mikhail Glukhikh
6733ee9383 Refactoring: convert problemHighlightType to function with parameter
(cherry picked from commit 2d9a5af)
2017-05-12 11:37:05 +03:00
Mikhail Glukhikh
81276653f3 Reduce range of IfThenTo... inspections to just 'if'
(cherry picked from commit d9a33af)
2017-05-12 11:36:54 +03:00
Mikhail Glukhikh
86c0c6131d Minor refactoring: IfThenToSelectData.clausesReplaceableByElvis
(cherry picked from commit 781a45c)
2017-05-12 11:36:44 +03:00
Mikhail Glukhikh
9682aab423 IfThenToDoubleBang: fix AWT from writeAction problem
(cherry picked from commit f3ee5ea)
2017-05-12 11:36:34 +03:00
Mikhail Glukhikh
20dfb3b91d Refactoring of IfThen: ToDoubleBang / ToElvis / ToSafeAccess
Some common actions were extracted to IfThenUtils.kt
Use consistent logic in all three intentions
Also fixes potential PSI consistency problems in conversions dot->safe calls

(cherry picked from commit 66c5717)
2017-05-12 11:36:24 +03:00
Mikhail Glukhikh
be8764a491 Test fix (I hope so) from parameter info group
(cherry picked from commit 6523f23)
2017-05-12 11:36:03 +03:00
Dmitry Neverov
f246098d05 Convert 'if' with 'is' check to 'as?' with safe call #KT-17054 Fixed
(cherry picked from commit fd6d152)
2017-05-12 11:35:45 +03:00
Mikhail Glukhikh
05cd97c7ff Refactoring: SelfTargetingIntention / IntentionBasedInspection
Remove complex logic which disables intention when bound inspection on
Add much simpler logic in SelfTargetingIntention.equals

(cherry picked from commit 0361ed8)
2017-05-12 11:35:27 +03:00
Mikhail Glukhikh
3647252db5 Use InfixCallToOrdinaryIntention directly for INFIX_MODIFIER_REQUIRED
So #KT-10211 Fixed

(cherry picked from commit f054343)
2017-05-11 12:07:06 +03:00
Mikhail Glukhikh
25bf65e38f Override 'equals' in SelfTargetingIntention
This prevents suggestion of duplicating intentions

(cherry picked from commit 967c01f)
2017-05-11 12:06:56 +03:00
Kirill Rakhman
1d125869a0 Add inspection to detect copy() calls in a data class without named arguments
So #KT-17660 Fixed

(cherry picked from commit a8b2d3b)
2017-05-11 12:06:43 +03:00
Mikhail Glukhikh
cf40405258 ConvertReferenceToLambda status refactoring
Intention is not registered now; inspection is enabled by default now,
 but has highlight level of "No highlighting"

(cherry picked from commit 382bf9a)
2017-05-11 12:06:19 +03:00
Mikhail Glukhikh
802ed46be6 ConvertLambdaToReference refactoring
Intention is not registered now; inspection is enabled by default now,
 but has highlight level of "No highlighting"
Inspection does not depend on text length now

So #KT-14335 Fixed

(cherry picked from commit 759e664)
2017-05-11 12:06:06 +03:00
Mikhail Glukhikh
93bf952e8e Get rid of local version of RemoveModifierFix
(cherry picked from commit 1d722e0)
2017-05-11 12:05:55 +03:00
Mikhail Glukhikh
e26ae36186 Get rid of local version of AddModifierFix
(cherry picked from commit 0234567)
2017-05-11 12:05:44 +03:00
Mikhail Glukhikh
cbc717a0af Minor (import removed)
(cherry picked from commit bb76783)
2017-05-11 12:05:34 +03:00
Dmitry Jemerov
16fd2a2580 Index properties defined in primary constructor
#KT-15029 Fixed

(cherry picked from commit 9c4f897)
2017-05-10 14:33:01 +02:00
Dmitry Jemerov
1a6add09ed Return non-default lexer state for unmatched backtick
When a document is changed, the editor highlighter restarts the lexer
at the last point where it was in the default state. Previously, if
a matching backtick was deleted and then reinserted, the lexer was
resumed just before the reinsertion point, and as the result the two
backticks were parsed not as two delimiters of a single token but as
two BAD_CHARACTER tokens. With this change, all tokens after the
unmatched backtick will be in a non-default state, so the lexer will
restart at the first backtick and will correctly see the two backticks
as a single token.

 #KT-9091 Fixed

(cherry picked from commit ec53a6d)
2017-05-10 14:32:51 +02:00
Dmitry Jemerov
2b15f45de7 Correctly handle editor selection in "Show expression type"
To avoid showing a large list, the previous logic returned only the
element directly at caret and other elements with the same start
offset. When selection is present, the platform logic looks only at
elements which have a larger range than the selection, so our elements
could be completely filtered out. Now we look at the selection
ourselves and adjust the returned elements accordingly.

 #KT-16423 Fixed

(cherry picked from commit 66877c1)
2017-05-10 14:32:38 +02:00
Dmitry Jemerov
6528b9c6b6 Better caret position for new Kotlin file/class
#KT-15255 Fixed

(cherry picked from commit c3c0bcb)
2017-05-10 14:32:25 +02:00
Dmitry Jemerov
39c2543b4b Don't highlight entire complex callee expression as call
If an expression returns something that has invoke() defined on it,
this entire expression can act as a callee. If we highlight it, this
will suppress more useful highlighting such as string literals.

 #KT-16159 Fixed

(cherry picked from commit d1893cf)
2017-05-10 14:32:14 +02:00
Dmitry Jemerov
13c560e30a Hide Kotlin live template macros from non-Kotlin contexts
#KT-16635 Fixed

(cherry picked from commit 5d93070)
2017-05-10 14:32:01 +02:00
Dmitry Jemerov
4ac2254900 Show line markers for suspending iteration
#KT-16803 Fixed

(cherry picked from commit c778e04)
2017-05-10 14:31:48 +02:00
Dmitry Jemerov
c877d53d3f Show line markers for sealed classes
#KT-16755 Fixed

(cherry picked from commit baa43a2)
2017-05-10 14:31:30 +02:00
Dmitry Jemerov
35b33e17d9 Allow updating of fold region for imports when it's collapsed
#KT-12856 Fixed

(cherry picked from commit f64aaed)
2017-05-10 14:31:17 +02:00
Dmitry Jemerov
700f0df6e6 Render anonymous objects in Show Expression Type
#KT-17304 Fixed

(cherry picked from commit 66ce2a6)
2017-05-10 14:31:04 +02:00
Dmitry Jemerov
e889fc0495 Pass Editor to StructureViewModel (required for autoscroll from source)
#KT-17439 Fixed

(cherry picked from commit 06a1d36)
2017-05-10 14:30:52 +02:00
Dmitry Jemerov
91345c7e08 Enable rainbow highlighting for destructuring declaration entries
#KT-17652 Fixed

(cherry picked from commit b33c544)
2017-05-10 14:29:40 +02:00
Kirill Rakhman
e250c01465 Add Smart Enter processor for object expessions (#1079)
Fixes #KT-17807

(cherry picked from commit dbcf796)
2017-05-10 10:50:25 +02:00
shiraji
90760f7d29 Introduce quick-fix adding label to 'return' in closures #KT-16851 Fixed
(cherry picked from commit 56d712a)
2017-05-10 10:29:15 +03:00
Dmitry Jemerov
91539caef7 Fix tests
(cherry picked from commit 4b811a3)
2017-05-09 11:51:51 +02:00
nd
7c528e324e Stricter type checks in 'convert to range' intention (#1073)
#KT-17079 #KT-17762 Fixed

(cherry picked from commit e20e097)
2017-05-09 09:32:28 +02:00
Nadia Humbert-Labeaumaz
d1e6054113 Remove "Move to class body" intention for annotation parameters (#1076)
#KT-17708 Fixed

(cherry picked from commit e76f1ac)
2017-05-09 09:29:18 +02:00
Dmitry Jemerov
0fa75b1c59 Don't crash on non-jar files added to classpath
#KT-17698 Fixed

(cherry picked from commit 80e17cb)
2017-05-09 09:19:13 +02:00
Yuli Fiterman
636eb5b14f KT-7848 -- unmerged changes (#1075)
* KT-7848 Initial implementation of literal copy/paste processor for Kotlin

* KT-7848: Tests

* KT-7848: fix issues caught in unit tests with recognizing invalid template entries

* KT-7848: check for KtFile

* KT-7848:  fix capitalization for test data file names

* KT-7848:  Initial changes according as per review

* KT-7848:  TemplateTokenSequence tests

* KT-7848:  fix off by one error caught in test

* KT-7848:  Reformat with keep empty lines in code -> 0

(cherry picked from commit 4393e2d)
2017-05-08 17:51:53 +02:00
Yuli Fiterman
4e2690e0d3 KT-7848: Literal copy/paste processor for Kotlin (#1074)
* KT-7848 Initial implementation of literal copy/paste processor for Kotlin

* KT-7847: Tests

* KT-7847: fix issues caught in unit tests with recognizing invalid template entries

* KT-7847: check for KtFile

* KT-7847:  fix capitalization for test data file names

* KT-7847:  Initial changes according as per review

(cherry picked from commit 99b1bb9)
2017-05-08 16:19:46 +02:00
Kirill Rakhman
c14f7a2063 Add intention to convert top level val with object expression to object declaration (#974)
* Add intention to convert top level val with object expression to object
Fixes #KT-14137

* fix intention description

(cherry picked from commit 8e00af5)
2017-05-08 15:36:03 +02:00
nd
b0906e3a1e Convert to secondary constructor is not applicable to data classes (#1071)
#KT-15942 Fixed

(cherry picked from commit 93b5eec)
2017-05-08 15:25:09 +02:00
nd
5a68027fd4 Detect redundant semicolon before empty import list (#1072)
#KT-16577 Fixed

(cherry picked from commit c9f475b)
2017-05-08 15:17:29 +02:00
Ilya Chernikov
ab52c553e1 Fix script-related tests that aren't ready for roots changed optimizations 2017-05-08 00:19:25 +02:00
Ilya Chernikov
9baf848765 Optimize scripting-related cache creation and update
reduce number of cases when changes are reported from script dependencies
  provider, that causing rootsChanged event, in particular empty dependencies
  are filtered out now

Should reduce IDEA startup delays.
2017-05-07 17:27:38 +02:00
Ilya Chernikov
3edef926ee Add logging with time measurement to script dependencies caching and caches updating 2017-05-07 17:27:36 +02:00
Ilya Chernikov
ad9cd38566 Optimize scripting-related files monitoring
filter vfs changes events to take only non-infrastructure files from actual
project
also drop unnecessary readAction during internal caches update

Should reduce IDEA startup delays.
2017-05-07 17:27:35 +02:00
Dmitry Jemerov
3c33e7699d Fix reporting exception problems on Kotlin UAST fields (KT-17714)
(cherry picked from commit 8337cd4)
2017-05-06 08:20:40 +02:00
Mikhail Zarechenskiy
f26e20dcab Warn about val reassignment via backing field
#KT-16681 In Progress
2017-05-05 21:34:05 +03:00
Mikhail Zarechenskiy
c70e7ad8a7 Fix resolve of last destructuring declaration in block
Last declaration in block is resolved in DEPENDENT mode because it has
 influence on return type and therefore fake call for destructuring declaration
 wasn't completed (see `getBlockReturnedTypeWithWritableScope`)

 Now we resolve fake call for destructuring declaration in INDEPENDENT
 mode as it doesn't have effect on return type

 #KT-15480 Fixed
2017-05-05 21:33:52 +03:00
Alexey Tsvetkov
4a3142b7d0 Merge sequent filter and map calls into one loop
ScopeTowerProcessors.kt contains a few code snippets
that look like `collectCandidates(...).filter { ... }.map { ... }`.
Filter argument is always side-effect free, so it is safe
to merge `filter` and `map` calls into one for-loop.

The change also makes sense, because modified functions are quite hot.
For example `NoExplicitReceiverScopeTowerProcessor.simpleProcess`
produces 11,392,768 ArrayList instances (~1.08% of all objects)
when compiling the compiler according to aprof at the moment of writing.

On my machine the change improves compilation speed of the compiler up to 5%.
2017-05-05 20:38:16 +03:00
Alexey Tsvetkov
70370cb72c Make closing artifact difference registry more robust
KT-16298
2017-05-05 18:40:43 +03:00
Alexey Tsvetkov
4065ffa99d Add test for KT-16298 2017-05-05 15:47:54 +03:00
Jonathan Leitschuh
782f27e765 Avoid flushing cache removed by clean
#KT-16298 fixed
2017-05-05 15:47:54 +03:00
Mikhail Glukhikh
e2726aa95e KT-13997 related: fix of JS relevant test
(cherry picked from commit 7271ca0)
2017-05-05 11:23:51 +03:00
Kirill Rakhman
9e9f16d16e Add quickfix for adding 'lateinit'
Fixes #KT-17650

(cherry picked from commit cd07aea)
2017-05-05 11:23:32 +03:00
Mikhail Glukhikh
a670945b6b KT-13997 related: fix of J2K relevant test
(cherry picked from commit 5de55e8)
2017-05-05 11:23:02 +03:00
Alexey Tsvetkov
b6f3a0d02d Fix exception "Unknown CompilerMessageSeverity: OUTPUT"
`CompilerMessageSeverity.OUTPUT` was removed from the enum set
`CompilerMessageSeverity.VERBOSE` in the commit d8d3bafbe9,
so `GradleMessageCollector` started to throw the exception.

    #KT-17711 fixed
2017-05-04 23:03:39 +03:00
Yan Zhulanow
ed7b517e32 Kapt3: Simplify handling of annotation processing exceptions
The previous handling method was unreliable ("Don't know how to render diagnostic of type KAPT3_PROCESSING_ERROR", exceptions being lost).
2017-05-04 20:24:09 +03:00
Alexey Tsvetkov
cdc25dd67d Test that Kapt3 IC removes stubs for dirty source files 2017-05-04 20:24:02 +03:00
Alexey Tsvetkov
5be0d53cc1 Kapt3: Remove source stubs together with the class files when .kt file is marked dirty (IC) 2017-05-04 20:23:58 +03:00
Yan Zhulanow
d0c9ab8b1c Kapt3: Avoid annotation processing execution when possible (KT-17620)
Do not execute annotation processing if no stubs (and Java files) were changed since the previous execution.
2017-05-04 20:23:52 +03:00
Yan Zhulanow
93acae764d Kapt3: Modify kapt incremental tests in order to support kapt3 2017-05-04 20:23:47 +03:00
Yan Zhulanow
a9e4513fb2 Kapt3: Support incremental compilation of Java stubs (KT-15151) 2017-05-04 20:23:43 +03:00
Yan Zhulanow
b8f423fef5 Kapt3: Support apt modes
Allow to run kapt in "annotation processing only" and "stub generation only" modes in order to support incremental compilation in Gradle.
Unfortunately, annotation processing can't be done incrementally cause it uses all module files, but the stub generation can be done incrementally.
2017-05-04 20:23:38 +03:00
Yan Zhulanow
05c9b12e14 Add kapt3 module to non-compiler-tests 2017-05-04 18:49:21 +03:00
Yan Zhulanow
746fa581b4 Kapt3: Convert reference to KMutableMap.Entry correctly (KT-17567) 2017-05-04 18:49:14 +03:00
Yan Zhulanow
8b3e8f3944 NoArg: Initialize properties in noarg constructor (KT-16692) 2017-05-04 18:49:07 +03:00
Yan Zhulanow
384f51d1e4 Kapt3: Add Maven integration test 2017-05-04 18:49:00 +03:00
Mikhail Glukhikh
9986608a19 Do not report redundant else for enum / sealed from another module
Related to KT-17497

(cherry picked from commit 1273166)
2017-05-04 14:23:57 +03:00
Mikhail Glukhikh
f352da545d KT-17497 related: introduce fix for REDUNDANT_ELSE_IN_WHEN
(cherry picked from commit 35754a9)
2017-05-04 14:23:42 +03:00
Mikhail Glukhikh
a409fe7546 Introduce warning REDUNDANT_ELSE_IN_WHEN #KT-17497 Fixed
(cherry picked from commit 1488682)
2017-05-04 14:23:30 +03:00
Mikhail Glukhikh
d9123562bb Consider property external if all accessors are external #KT-13997 Fixed
(cherry picked from commit e53c548)
2017-05-04 14:23:17 +03:00
Mikhail Glukhikh
44b3092777 J2K: move isEffectivelyExternal to kt-file, parameter -> receiver
(cherry picked from commit b8af0f5)
2017-05-04 14:23:03 +03:00
Ilya Chernikov
650220c8c8 Use invokeLater properly on scripts reconfiguration
Should fix #EA-97987
2017-05-03 18:08:08 +02:00
Ilya Chernikov
d83bd8bf4c Ignore empty lines at the end of the testdata, more tests
should finally fix source-section plugin tests on windows
2017-05-03 18:08:07 +02:00
Ilya Chernikov
766eb43792 Pass earlier scripts as array, removes 255-lines repl limitation
fixes #KT-10060
2017-05-03 18:08:06 +02:00
Ilya Chernikov
60bb823f1f Switch old IDE/CLI repls to the new infrastructure
should also fix #KT-5822
2017-05-03 18:08:05 +02:00
Ilya Chernikov
efdf0744c7 minor: unwrapping InvocationTargetException on repl line evaluation...
To provide better error diagnostics
2017-05-03 18:08:04 +02:00
Ilya Chernikov
345d453908 Add total reset to repl history and state interfaces 2017-05-03 18:08:03 +02:00
Ilya Chernikov
ceb0e8e072 minor: add some generic repl tests...
in particular ignored test256Evals test that fails due to #KT-10060
2017-05-03 18:08:02 +02:00
Ilya Chernikov
404342d80c minor: some repl cleanup 2017-05-03 18:08:01 +02:00
Alexey Andreev
37bdfc4808 Add changelog for 1.1.3 2017-05-03 17:32:27 +03:00
882 changed files with 13507 additions and 8417 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.compilerRunner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cli.common.arguments.Argument;
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt;
import org.jetbrains.kotlin.utils.StringsKt;
import java.lang.reflect.Field;
@@ -74,7 +75,12 @@ public class ArgumentUtils {
if (fieldType == boolean.class || fieldType == Boolean.class) continue;
result.add(value.toString());
if (ParseCommandLineArgumentsKt.isAdvanced(argument)) {
result.set(result.size() - 1, argument.value() + "=" + value.toString());
}
else {
result.add(value.toString());
}
}
Class<?> superClazz = clazz.getSuperclass();

View File

@@ -19,7 +19,6 @@
package org.jetbrains.kotlin.incremental
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.build.GeneratedFile
@@ -54,6 +53,7 @@ fun makeModuleFile(name: String, isTest: Boolean, outputDir: File, sourcesToComp
sourcesToCompile,
javaSourceRoots.map { JvmSourceRoot(it) },
classpath,
null,
"java-production",
isTest,
// this excludes the output directories from the class path, to be removed for true incremental compilation
@@ -168,10 +168,11 @@ fun<Target> OutputItemsCollectorImpl.generatedFiles(
outputItem.sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?:
targets.filter { getOutputDir(it)?.let { outputItem.outputFile.startsWith(it) } ?: false }.singleOrNull() ?:
representativeTarget
if (outputItem.outputFile.name.endsWith(".class"))
GeneratedJvmClass(target, outputItem.sourceFiles, outputItem.outputFile)
else
GeneratedFile(target, outputItem.sourceFiles, outputItem.outputFile)
when (outputItem.outputFile.extension) {
"class" -> GeneratedJvmClass(target, outputItem.sourceFiles, outputItem.outputFile)
else -> GeneratedFile(target, outputItem.sourceFiles, outputItem.outputFile)
}
}
}

View File

@@ -39,6 +39,7 @@ class KotlinModuleXmlBuilder {
sourceFiles: Iterable<File>,
javaSourceRoots: Iterable<JvmSourceRoot>,
classpathRoots: Iterable<File>,
modularJdkRoot: File?,
targetTypeId: String,
isTests: Boolean,
directoriesToFilterOut: Set<File>,
@@ -64,6 +65,10 @@ class KotlinModuleXmlBuilder {
processJavaSourceRoots(javaSourceRoots)
processClasspath(classpathRoots, directoriesToFilterOut)
if (modularJdkRoot != null) {
p.println("<", MODULAR_JDK_ROOT, " ", PATH, "=\"", getEscapedPath(modularJdkRoot), "\"/>")
}
closeTag(p, MODULE)
return this
}

View File

@@ -35,8 +35,13 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> {
@NotNull
public final KtPureClassOrObject myClass;
@NotNull
public final OwnerKind kind;
@NotNull
public final ClassDescriptor descriptor;
protected ClassBodyCodegen(

View File

@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.CollectionStub
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@@ -337,7 +337,7 @@ class CollectionStubMethodGenerator(
val access = ACC_PUBLIC or (if (synthetic) ACC_SYNTHETIC else 0)
val asmMethod = signature.asmMethod
val genericSignature = if (synthetic) null else signature.genericsSignature
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, asmMethod.name, asmMethod.descriptor, genericSignature, null)
val mv = v.newMethod(CollectionStub, access, asmMethod.name, asmMethod.descriptor, genericSignature, null)
mv.visitCode()
AsmUtil.genThrow(
InstructionAdapter(mv),
@@ -351,7 +351,7 @@ private val READ_ONLY_ARE_EQUAL_TO_MUTABLE_TYPE_CHECKER = KotlinTypeCheckerImpl.
val firstClass = x.declarationDescriptor as? ClassDescriptor ?: return@withAxioms x == y
val secondClass = y.declarationDescriptor as? ClassDescriptor ?: return@withAxioms x == y
val j2k = JavaToKotlinClassMap.INSTANCE
val j2k = JavaToKotlinClassMap
val firstReadOnly = if (j2k.isMutable(firstClass)) j2k.convertMutableToReadOnly(firstClass) else firstClass
val secondReadOnly = if (j2k.isMutable(secondClass)) j2k.convertMutableToReadOnly(secondClass) else secondClass
firstReadOnly.typeConstructor == secondReadOnly.typeConstructor

View File

@@ -1748,7 +1748,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor);
// when captured parameter is singleton
// see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A)
if (parameterOffsetInConstructor == -1) return parentResult;
if (parameterOffsetInConstructor == -1) return adjustVariableValue(parentResult , descriptor);
assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar
: "Part of closure should be either Field or FieldForSharedVar";

View File

@@ -792,7 +792,7 @@ public class FunctionCodegen {
if (!isThereOverriddenInKotlinClass(descriptor)) {
Method method = typeMapper.mapAsmMethod(descriptor);
int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor);
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(overridden), flags, method.getName(), method.getDescriptor(), null, null);
v.newMethod(JvmDeclarationOriginKt.AugmentedBuiltInApi(overridden), flags, method.getName(), method.getDescriptor(), null, null);
}
}
}
@@ -938,12 +938,19 @@ public class FunctionCodegen {
capturedArgumentsCount++;
}
int maskIndex = 0;
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
for (int index = 0; index < valueParameters.size(); index++) {
assert valueParameters.size() > 0 : "Expecting value parameters to generate default function " + functionDescriptor;
int firstMaskIndex = frameMap.enterTemp(Type.INT_TYPE);
for (int index = 1; index < valueParameters.size(); index++) {
if (index % Integer.SIZE == 0) {
maskIndex = frameMap.enterTemp(Type.INT_TYPE);
frameMap.enterTemp(Type.INT_TYPE);
}
}
//default handler or constructor marker
frameMap.enterTemp(AsmTypes.OBJECT_TYPE);
for (int index = 0; index < valueParameters.size(); index++) {
int maskIndex = firstMaskIndex + index / Integer.SIZE;
ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();

View File

@@ -41,8 +41,12 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap.PlatformMutabilityMapping;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DelegationResolver;
@@ -70,7 +74,6 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.*;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isGenericToArray;
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray;
@@ -256,24 +259,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private static final Map<FqName, String> KOTLIN_MARKER_INTERFACES = new HashMap<>();
static {
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterator, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterable, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.collection, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.list, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.listIterator, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.set, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.map, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mapEntry, "kotlin/jvm/internal/markers/KMappedMarker");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterator, "kotlin/jvm/internal/markers/KMutableIterator");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterable, "kotlin/jvm/internal/markers/KMutableIterable");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableCollection, "kotlin/jvm/internal/markers/KMutableCollection");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableList, "kotlin/jvm/internal/markers/KMutableList");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableListIterator, "kotlin/jvm/internal/markers/KMutableListIterator");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableSet, "kotlin/jvm/internal/markers/KMutableSet");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMap, "kotlin/jvm/internal/markers/KMutableMap");
KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMapEntry, "kotlin/jvm/internal/markers/KMutableMap$Entry");
static {
for (PlatformMutabilityMapping platformMutabilityMapping : JavaToKotlinClassMap.INSTANCE.getMutabilityMappings()) {
KOTLIN_MARKER_INTERFACES.put(
platformMutabilityMapping.getKotlinReadOnly().asSingleFqName(),
"kotlin/jvm/internal/markers/KMappedMarker");
ClassId mutableClassId = platformMutabilityMapping.getKotlinMutable();
KOTLIN_MARKER_INTERFACES.put(
mutableClassId.asSingleFqName(),
"kotlin/jvm/internal/markers/K" + mutableClassId.getRelativeClassName().asString()
.replace("MutableEntry", "Entry") // kotlin.jvm.internal.markers.KMutableMap.Entry for some reason
.replace(".", "$")
);
}
}
@NotNull
@@ -307,15 +307,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (KotlinType supertype : descriptor.getTypeConstructor().getSupertypes()) {
if (isJvmInterface(supertype.getConstructor().getDeclarationDescriptor())) {
FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
sw.writeInterface();
Type jvmInterfaceType = typeMapper.mapSupertype(supertype, sw);
sw.writeInterfaceEnd();
String jvmInterfaceInternalName = jvmInterfaceType.getInternalName();
superInterfaces.add(jvmInterfaceInternalName);
FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
String kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName);
if (kotlinMarkerInterfaceInternalName != null) {
if (typeMapper.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) {
sw.writeInterface();
Type kotlinCollectionType = typeMapper.mapType(supertype, sw, TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS);
sw.writeInterfaceEnd();
superInterfaces.add(kotlinCollectionType.getInternalName());
}
kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName);
}
}
@@ -358,9 +367,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateFunctionsForDataClasses();
new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
generateToArray();
}
generateToArray();
if (context.closure != null)
genClosureFields(context.closure, v, typeMapper);
@@ -1047,7 +1059,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
private void generateInitializers(@NotNull ExpressionCodegen codegen) {
public void generateInitializers(@NotNull ExpressionCodegen codegen) {
generateInitializers(() -> codegen);
}

View File

@@ -158,7 +158,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
iv.load(0, classType);
int valueParamStart = context.getEarlierScripts().size() + 1;
int valueParamStart = context.getEarlierScripts().isEmpty() ? 1 : 2; // this + array of earlier scripts if not empty
List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
for (ValueParameterDescriptor superclassParam: ctorDesc.getValueParameters()) {
@@ -185,18 +185,20 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
FrameMap frameMap = new FrameMap();
frameMap.enterTemp(OBJECT_TYPE);
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
frameMap.enter(importedScript, OBJECT_TYPE);
}
int offset = 1;
if (!context.getEarlierScripts().isEmpty()) {
int scriptsParamIndex = frameMap.enterTemp(AsmUtil.getArrayType(OBJECT_TYPE));
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
Type earlierClassType = typeMapper.mapClass(earlierScript);
iv.load(0, classType);
iv.load(offset, earlierClassType);
offset += earlierClassType.getSize();
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
int earlierScriptIndex = 0;
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
Type earlierClassType = typeMapper.mapClass(earlierScript);
iv.load(0, classType);
iv.load(scriptsParamIndex, earlierClassType);
iv.aconst(earlierScriptIndex++);
iv.aload(OBJECT_TYPE);
iv.checkcast(earlierClassType);
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
}
}
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this);

View File

@@ -70,7 +70,7 @@ public abstract class TransformationMethodVisitor extends MethodVisitor {
// So we just do it here
if (methodNode.instructions.size() == 0
// MethodNode does not create a list of variables for abstract methods, so we would get NPE in accept() instead
&& (!(delegate instanceof MethodNode) || (methodNode.access & Opcodes.ACC_ABSTRACT) == 0)
&& (!(delegate instanceof MethodNode) || methodNode.localVariables != null)
) {
List<LocalVariableNode> localVariables = methodNode.localVariables;
// visits local variables

View File

@@ -941,7 +941,12 @@ public class InlineCodegen extends CallGenerator {
assert constantValue instanceof Integer : "Mask should be of Integer type, but " + constantValue;
maskValues.add((Integer) constantValue);
if (maskStartIndex == -1) {
maskStartIndex = invocationParamBuilder.getNextParameterOffset();
maskStartIndex = 0;
List<ParameterInfo> infos = invocationParamBuilder.listAllParams();
for (ParameterInfo info : infos) {
if (info instanceof CapturedParamInfo) continue;
maskStartIndex += info.getType().getSize();
}
}
}
else {

View File

@@ -134,7 +134,7 @@ fun expandMaskConditionsAndUpdateVariableNodes(node: MethodNode, maskStartIndex:
}
val indexToVarNode = node.localVariables?.filter { it.index < maskStartIndex }?.associateBy { it.index } ?: emptyMap()
val toDelete = arrayListOf<AbstractInsnNode>()
val toDelete = linkedSetOf<AbstractInsnNode>()
conditions.forEach {
val jumpInstruction = it.jumpInstruction
InsnSequence(it.maskInstruction, (if (it.expandNotDelete) jumpInstruction.next else jumpInstruction.label)).forEach {
@@ -147,6 +147,8 @@ fun expandMaskConditionsAndUpdateVariableNodes(node: MethodNode, maskStartIndex:
}
}
node.localVariables.removeIf { it.start in toDelete && it.end in toDelete }
toDelete.forEach {
node.instructions.remove(it)
}

View File

@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import java.io.File
@@ -215,9 +215,11 @@ class GenerationState @JvmOverloads constructor(
}
private fun shouldOnlyCollectSignatures(origin: JvmDeclarationOrigin)
= classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && origin.originKind == CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL
= classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && origin.originKind in doNotGenerateInLightClassMode
}
private val doNotGenerateInLightClassMode = setOf(CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL, BRIDGE, COLLECTION_STUB, AUGMENTED_BUILTIN_API)
private class LazyJvmDiagnostics(compute: () -> Diagnostics): Diagnostics {
private val delegate by lazy(LazyThreadSafetyMode.SYNCHRONIZED, compute)

View File

@@ -1477,8 +1477,8 @@ public class KotlinTypeMapper {
sw.writeParametersStart();
for (ScriptDescriptor importedScript : importedScripts) {
writeParameter(sw, importedScript.getDefaultType(), /* callableDescriptor = */ null);
if (importedScripts.size() > 0) {
writeParameter(sw, DescriptorUtilsKt.getModule(script).getBuiltIns().getArray().getDefaultType(), null);
}
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {

View File

@@ -29,7 +29,7 @@ open class DefaultValues(val defaultValue: String, val possibleValues: List<Stri
object StringNullDefault : DefaultValues("null")
object LanguageVersions : DefaultValues(
"\"" + LanguageVersion.LATEST_STABLE.versionString + "\"",
"null",
LanguageVersion.values().map { "\"${it.description}\"" }
)

View File

@@ -79,9 +79,20 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
// Advanced options
@GradleOption(DefaultValues.BooleanFalseDefault.class)
@Argument(value = "-Xtypedarrays", description = "Translate primitive arrays to JS typed arrays")
@Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays")
public boolean typedArrays;
@GradleOption(DefaultValues.BooleanFalseDefault.class)
@Argument(value = "-Xfriend-modules-disabled", description = "Disable internal declaration export")
public boolean friendModulesDisabled;
@Argument(
value = "-Xfriend-modules",
valueDescription = "<path>",
description = "Paths to friend modules"
)
public String friendModules;
@NotNull
public static K2JSCompilerArguments createDefaultInstance() {
K2JSCompilerArguments arguments = new K2JSCompilerArguments();

View File

@@ -29,13 +29,14 @@ class ModuleBuilder(
private val classpathRoots = ArrayList<String>()
private val javaSourceRoots = ArrayList<JavaRootPath>()
private val friendDirs = ArrayList<String>()
override var modularJdkRoot: String? = null
fun addSourceFiles(pattern: String) {
sourceFiles.add(pattern)
fun addSourceFiles(path: String) {
sourceFiles.add(path)
}
fun addClasspathEntry(name: String) {
classpathRoots.add(name)
fun addClasspathEntry(path: String) {
classpathRoots.add(path)
}
fun addJavaSourceRoot(rootPath: JavaRootPath) {

View File

@@ -52,6 +52,7 @@ public class ModuleXmlParser {
public static final String JAVA_SOURCE_PACKAGE_PREFIX = "packagePrefix";
public static final String PATH = "path";
public static final String CLASSPATH = "classpath";
public static final String MODULAR_JDK_ROOT = "modularJdkRoot";
@NotNull
public static ModuleScriptData parseModuleScript(
@@ -172,6 +173,10 @@ public class ModuleXmlParser {
String packagePrefix = getNullableAttribute(attributes, JAVA_SOURCE_PACKAGE_PREFIX);
moduleBuilder.addJavaSourceRoot(new JavaRootPath(path, packagePrefix));
}
else if (MODULAR_JDK_ROOT.equalsIgnoreCase(qName)) {
String path = getAttribute(attributes, PATH, qName);
moduleBuilder.setModularJdkRoot(path);
}
else {
throw createError(qName);
}

View File

@@ -52,11 +52,19 @@ open class AggregatedReplStateHistory<T1, T2>(val history1: IReplStageHistory<T1
ReplHistoryRecord(r1.id, r1.item to r2.item)
}
override fun reset(): Iterable<ILineId> = lock.write {
assertSameSize()
val i1 = history1.reset().toList()
val i2 = history2.reset().toList()
if (i1 != i2) throw IllegalStateException("Aggregated history reset lines mismatch: $i1 != $i2")
i1
}
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")
if (i1 != i2) throw IllegalStateException("Aggregated history reset lines mismatch: $i1 != $i2")
i1
}

View File

@@ -49,6 +49,14 @@ open class BasicReplStageHistory<T>(override val lock: ReentrantReadWriteLock =
override fun pop(): ReplHistoryRecord<T>? = lock.write { if (isEmpty()) null else removeAt(lastIndex) }
override fun reset(): Iterable<ILineId> {
lock.write {
val removed = map { it.id }
clear()
return removed
}
}
override fun resetTo(id: ILineId): Iterable<ILineId> {
lock.write {
val idx = indexOfFirst { it.id == id }

View File

@@ -46,8 +46,13 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
aggregatedState.apply {
lock.write {
if (state1.history.size > state2.history.size) {
state2.history.peek()?.let {
state1.history.resetTo(it.id)
if (state2.history.size == 0) {
state1.history.reset()
}
else {
state2.history.peek()?.let {
state1.history.resetTo(it.id)
}
}
assert(state1.history.size == state2.history.size)
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.common.repl
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
import java.lang.reflect.InvocationTargetException
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write
@@ -73,10 +74,14 @@ open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
val useScriptArgs = currentScriptArgs?.scriptArgs
val useScriptArgsTypes = currentScriptArgs?.scriptArgsTypes?.map { it.java }
val constructorParams: Array<Class<*>> = (historyActor.effectiveHistory.map { it.klass.java } +
(useScriptArgs?.mapIndexed { i, it -> useScriptArgsTypes?.getOrNull(i) ?: it?.javaClass ?: Any::class.java } ?: emptyList())
).toTypedArray()
val constructorArgs: Array<Any?> = (historyActor.effectiveHistory.map { it.instance } + useScriptArgs.orEmpty()).toTypedArray()
val hasHistory = historyActor.effectiveHistory.isNotEmpty()
val constructorParams: Array<Class<*>> = (if (hasHistory) arrayOf<Class<*>>(Array<Any>::class.java) else emptyArray<Class<*>>()) +
(useScriptArgs?.mapIndexed { i, it -> useScriptArgsTypes?.getOrNull(i) ?: it?.javaClass ?: Any::class.java } ?: emptyList())
val constructorArgs: Array<out Any?> = if (hasHistory) arrayOf(historyActor.effectiveHistory.map { it.instance }.takeIf { it.isNotEmpty() }?.toTypedArray(),
*(useScriptArgs.orEmpty()))
else useScriptArgs.orEmpty()
// TODO: try/catch ?
val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams)
@@ -88,14 +93,18 @@ open class GenericReplEvaluator(val baseClasspath: Iterable<File>,
if (invokeWrapper != null) invokeWrapper.invoke { scriptInstanceConstructor.newInstance(*constructorArgs) }
else scriptInstanceConstructor.newInstance(*constructorArgs)
}
catch (e: InvocationTargetException) {
// ignore everything in the stack trace until this constructor call
return@eval ReplEvalResult.Error.Runtime(renderReplStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"), e.targetException as? Exception)
}
catch (e: Throwable) {
historyActor.removePlaceholder(compileResult.lineId)
// 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)
}
finally {
historyActor.removePlaceholder(compileResult.lineId)
}
historyActor.removePlaceholder(compileResult.lineId)
historyActor.addFinal(compileResult.lineId, EvalClassWithInstanceAndLoader(scriptClass.kotlin, scriptInstance, classLoader, invokeWrapper))
val resultField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }

View File

@@ -52,6 +52,13 @@ class ReplHistory<T>(startingHistory: CompiledHistoryList<T> = emptyList()) : Se
}
}
/* resets back complete history and returns the lines removed */
fun reset(): SourceHistoryList<T> {
val removed = history.map { Pair(it.first.source, it.second) }
history.clear()
return removed
}
/* resets back to a previous line number and returns the lines removed */
fun resetToLine(lineNumber: Int): SourceHistoryList<T> {
val removed = arrayListOf<SourceHistoryItem<T>>()

View File

@@ -41,6 +41,8 @@ interface IReplStageHistory<T> : List<ReplHistoryRecord<T>> {
else null
}
fun reset(): Iterable<ILineId>
fun resetTo(id: ILineId): Iterable<ILineId>
val lock: ReentrantReadWriteLock

View File

@@ -274,11 +274,19 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
ContainerUtil.addAll(libraries, ArraysKt.filterNot(arguments.libraries.split(File.pathSeparator), String::isEmpty));
}
configuration.put(JSConfigurationKeys.LIBRARIES, libraries);
if (arguments.typedArrays) {
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true);
}
configuration.put(JSConfigurationKeys.LIBRARIES, libraries);
configuration.put(JSConfigurationKeys.FRIEND_PATHS_DISABLED, arguments.friendModulesDisabled);
if (!arguments.friendModulesDisabled && arguments.friendModules != null) {
List<String> friendPaths = ArraysKt.filterNot(arguments.friendModules.split(File.pathSeparator), String::isEmpty);
configuration.put(JSConfigurationKeys.FRIEND_PATHS, friendPaths);
}
String moduleKindName = arguments.moduleKind;
ModuleKind moduleKind = moduleKindName != null ? moduleKindMap.get(moduleKindName) : ModuleKind.PLAIN;

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.cli.jvm
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -93,11 +94,16 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
else if (arguments.module == null) {
for (arg in arguments.freeArgs) {
configuration.addKotlinSourceRoot(arg)
val file = File(arg)
if (file.isDirectory) {
if (file.extension == JavaFileType.DEFAULT_EXTENSION) {
configuration.addJavaSourceRoot(file)
}
else {
configuration.addKotlinSourceRoot(arg)
if (file.isDirectory) {
configuration.addJavaSourceRoot(file)
}
}
}
}

View File

@@ -163,7 +163,7 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup
KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade))
}
override fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
//
return emptyList()
}

View File

@@ -26,6 +26,7 @@ import com.intellij.psi.search.GlobalSearchScope
import gnu.trove.THashMap
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
@@ -36,21 +37,23 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
import kotlin.properties.Delegates
// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices
// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage,
// which is indirectly invoked from PsiPackage.getSubPackages
class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager {
private val perfCounter = PerformanceCounter.create("Find Java class")
private var index: JvmDependenciesIndex by Delegates.notNull()
private lateinit var index: JvmDependenciesIndex
private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex
private val topLevelClassesCache: MutableMap<FqName, VirtualFile?> = THashMap()
private val allScope = GlobalSearchScope.allScope(myPsiManager.project)
private var useFastClassFilesReading = false
fun initialize(packagesCache: JvmDependenciesIndex, useFastClassFilesReading: Boolean) {
this.index = packagesCache
fun initialize(index: JvmDependenciesIndex, singleJavaFileRootsIndex: SingleJavaFileRootsIndex, useFastClassFilesReading: Boolean) {
this.index = index
this.singleJavaFileRootsIndex = singleJavaFileRootsIndex
this.useFastClassFilesReading = useFastClassFilesReading
}
@@ -64,6 +67,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type)
}
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope }
}
@@ -89,7 +93,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return@getOrPut outerClass?.findInnerClass(classId.shortClassName)
}
val resolver = ClassifierResolutionContext { findClass(it, searchScope) }
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass(
virtualFile,
@@ -153,6 +157,13 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
// traverse all
true
}
result.addIfNotNull(
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
)
if (result.isNotEmpty()) {
return@time result.toTypedArray()
}
@@ -169,10 +180,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
//abort on first found
false
}
if (found) {
return PsiPackageImpl(myPsiManager, packageName)
if (!found) {
found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty()
}
return null
return if (found) PsiPackageImpl(myPsiManager, packageName) else null
}
private fun findVirtualFileGivenPackage(
@@ -216,6 +227,11 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
true
})
for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) {
assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" }
result.add(classId.shortClassName.asString())
}
return result
}

View File

@@ -25,6 +25,7 @@ import com.intellij.core.CoreApplicationEnvironment
import com.intellij.core.CoreJavaFileManager
import com.intellij.core.JavaCoreApplicationEnvironment
import com.intellij.core.JavaCoreProjectEnvironment
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.lang.MetaLanguage
import com.intellij.lang.java.JavaParserDefinition
@@ -70,17 +71,10 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
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
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesDynamicCompoundIndex
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.cli.jvm.index.JvmUpdateableDependenciesIndexFactory
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.index.*
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleInfo
import org.jetbrains.kotlin.cli.jvm.modules.ModuleGraph
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
@@ -102,6 +96,8 @@ import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleGraph
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
@@ -147,6 +143,9 @@ class KotlinCoreEnvironment private constructor(
private val sourceFiles = mutableListOf<KtFile>()
private val rootsIndex: JvmDependenciesDynamicCompoundIndex
private val javaModuleFinder: CliJavaModuleFinder
private val javaModuleGraph: JavaModuleGraph
val configuration: CompilerConfiguration = configuration.copy()
init {
@@ -192,6 +191,9 @@ class KotlinCoreEnvironment private constructor(
}
}
javaModuleFinder = CliJavaModuleFinder(VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL))
javaModuleGraph = JavaModuleGraph(javaModuleFinder)
val initialRoots = convertClasspathRoots(configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS))
if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK)) {
@@ -208,11 +210,16 @@ class KotlinCoreEnvironment private constructor(
// REPL and kapt2 update classpath dynamically
val indexFactory = JvmUpdateableDependenciesIndexFactory()
rootsIndex = indexFactory.makeIndexFor(initialRoots)
val (roots, singleJavaFileRoots) =
initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION }
rootsIndex = indexFactory.makeIndexFor(roots)
updateClasspathFromRootsIndex(rootsIndex)
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl)
.initialize(rootsIndex, configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING))
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
rootsIndex,
SingleJavaFileRootsIndex(singleJavaFileRoots),
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING)
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
project.registerService(MetadataFinderFactory::class.java, finderFactory)
@@ -259,28 +266,22 @@ class KotlinCoreEnvironment private constructor(
result.add(JavaRoot(virtualFile, rootType, prefixPackageFqName))
}
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
if (jrtFileSystem != null) {
addModularJdkRoots(jrtFileSystem, result)
}
addModularRoots(result)
return result
}
private fun addModularJdkRoots(fileSystem: VirtualFileSystem, result: MutableList<JavaRoot>) {
val graph = ModuleGraph { moduleName ->
fileSystem.findFileByPath("/modules/$moduleName/module-info.class")?.let((JavaModuleInfo)::read) ?: run {
report(ERROR, "Module $moduleName cannot be found in the Java runtime image")
JavaModuleInfo(moduleName, emptyList(), emptyList())
}
private fun addModularRoots(result: MutableList<JavaRoot>) {
val jrtFileSystem = javaModuleFinder.jrtFileSystem ?: return
val rootModules = computeRootModules(javaModuleFinder)
val allDependencies = javaModuleGraph.getAllDependencies(rootModules).also { modules ->
report(LOGGING, "Loading modules: $modules")
}
val allReachableModules = graph.getAllReachable(listOf("java.base", "java.se")).also { modules ->
report(LOGGING, "Loading modules exported by java.se: $modules")
}
for (moduleName in allReachableModules) {
val root = fileSystem.findFileByPath("/modules/$moduleName")
for (moduleName in allDependencies) {
// TODO: support modules not only from Java runtime image, but from a separate module path
val root = jrtFileSystem.findFileByPath("/modules/$moduleName")
if (root == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph")
}
@@ -290,6 +291,40 @@ class KotlinCoreEnvironment private constructor(
}
}
// See http://openjdk.java.net/jeps/261
private fun computeRootModules(finder: CliJavaModuleFinder): List<String> {
val result = arrayListOf<String>()
val systemModules = finder.computeAllSystemModules()
val javaSeExists = "java.se" in systemModules
if (javaSeExists) {
// The java.se module is a root, if it exists.
result.add("java.se")
}
fun JavaModuleInfo.exportsAtLeastOnePackageUnqualified(): Boolean = exports.any { it.toModules.isEmpty() }
if (!javaSeExists) {
// If it does not exist then every java.* module on the upgrade module path or among the system modules
// that exports at least one package, without qualification, is a root.
for ((name, module) in systemModules) {
if (name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) {
result.add(name)
}
}
}
for ((name, module) in systemModules) {
// Every non-java.* module on the upgrade module path or among the system modules that exports at least one package,
// without qualification, is also a root.
if (!name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) {
result.add(name)
}
}
return result
}
private fun updateClasspathFromRootsIndex(index: JvmDependenciesIndex) {
index.indexedRoots.forEach {
projectEnvironment.addSourcesToClasspath(it.file)
@@ -316,20 +351,18 @@ class KotlinCoreEnvironment private constructor(
fun tryUpdateClasspath(files: Iterable<File>): List<File>? = updateClasspath(files.map(::JvmClasspathRoot))
fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? {
when (root) {
is JvmClasspathRoot -> {
return if (root.file.isFile) findJarRoot(root) else findLocalDirectory(root)
}
is JavaSourceRoot -> {
return if (root.file.isDirectory) findLocalDirectory(root) else null
}
return when (root) {
is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root) else findLocalFile(root)
is JavaSourceRoot -> findLocalFile(root)
else -> throw IllegalStateException("Unexpected root: $root")
}
}
private fun findLocalDirectory(root: JvmContentRoot): VirtualFile? {
fun findLocalFile(path: String) = applicationEnvironment.localFileSystem.findFileByPath(path)
private fun findLocalFile(root: JvmContentRoot): VirtualFile? {
val path = root.file
val localFile = findLocalDirectory(path.absolutePath)
val localFile = findLocalFile(path.absolutePath)
if (localFile == null) {
report(STRONG_WARNING, "Classpath entry points to a non-existent location: $path")
return null
@@ -337,9 +370,6 @@ class KotlinCoreEnvironment private constructor(
return localFile
}
internal fun findLocalDirectory(absolutePath: String): VirtualFile? =
applicationEnvironment.localFileSystem.findFileByPath(absolutePath)
private fun findJarRoot(root: JvmClasspathRoot): VirtualFile? =
applicationEnvironment.jarFileSystem.findFileByPath("${root.file}${URLUtil.JAR_SEPARATOR}")

View File

@@ -188,6 +188,16 @@ object KotlinToJVMBytecodeCompiler {
}
}
for (module in chunk) {
val modularJdkRoot = module.modularJdkRoot
if (modularJdkRoot != null) {
// We use the SDK of the first module in the chunk, which is not always correct because some other module in the chunk
// might depend on a different SDK
configuration.put(JVMConfigurationKeys.JDK_HOME, File(modularJdkRoot))
break
}
}
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
}
@@ -346,7 +356,7 @@ object KotlinToJVMBytecodeCompiler {
override fun analyze(): AnalysisResult {
val project = environment.project
val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNull { module ->
environment.findLocalDirectory(module.getOutputDirectory())
environment.findLocalFile(module.getOutputDirectory())
}.orEmpty()
val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, environment.getSourceFiles())
// To support partial and incremental compilation, we add the scope which contains binaries from output directories

View File

@@ -0,0 +1,115 @@
/*
* 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.index
import com.intellij.lang.java.lexer.JavaLexer
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.impl.source.tree.ElementType
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
init {
for ((file) in roots) {
assert(!file.isDirectory) { "Should not be a directory: $file" }
}
}
private val classIdsInRoots = ArrayList<List<ClassId>>(roots.size)
fun findJavaSourceClass(classId: ClassId): VirtualFile? =
roots.indices
.find { index -> classId in getClassIdsForRootAt(index) }
?.let { index -> roots[index].file }
fun findJavaSourceClasses(packageFqName: FqName): List<ClassId> =
roots.indices.flatMap(this::getClassIdsForRootAt).filter { root -> root.packageFqName == packageFqName }
private fun getClassIdsForRootAt(index: Int): List<ClassId> {
for (i in classIdsInRoots.size..index) {
classIdsInRoots.add(JavaSourceClassIdReader(roots[i].file).readClassIds())
}
return classIdsInRoots[index]
}
/**
* Given a .java file, [readClassIds] uses lexer to determine which classes are declared in that file
*/
private class JavaSourceClassIdReader(file: VirtualFile) {
private val lexer = JavaLexer(LanguageLevel.JDK_1_9).apply {
start(String(file.contentsToByteArray()))
}
private var braceBalance = 0
private fun at(type: IElementType): Boolean = lexer.tokenType == type
private fun end(): Boolean = lexer.tokenType == null
private fun advance() {
when {
at(ElementType.LBRACE) -> braceBalance++
at(ElementType.RBRACE) -> braceBalance--
}
lexer.advance()
}
private fun tokenText(): String = lexer.tokenText
private fun atClass(): Boolean =
braceBalance == 0 && lexer.tokenType in CLASS_KEYWORDS
fun readClassIds(): List<ClassId> {
var packageFqName = FqName.ROOT
while (!end() && !at(ElementType.PACKAGE_KEYWORD) && !atClass()) {
advance()
}
if (at(ElementType.PACKAGE_KEYWORD)) {
val packageName = StringBuilder()
while (!end() && !at(ElementType.SEMICOLON)) {
if (at(ElementType.IDENTIFIER) || at(ElementType.DOT)) {
packageName.append(tokenText())
}
advance()
}
packageFqName = FqName(packageName.toString())
}
val result = ArrayList<ClassId>(1)
while (true) {
while (!end() && !atClass()) {
advance()
}
if (end()) break
while (!end() && !at(ElementType.IDENTIFIER)) {
advance()
}
if (end()) break
result.add(ClassId(packageFqName, Name.identifier(tokenText())))
}
return result
}
companion object {
private val CLASS_KEYWORDS = setOf(ElementType.CLASS_KEYWORD, ElementType.INTERFACE_KEYWORD, ElementType.ENUM_KEYWORD)
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.modules
import com.intellij.openapi.vfs.VirtualFileSystem
import com.intellij.psi.PsiJavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
internal class CliJavaModuleFinder(val jrtFileSystem: VirtualFileSystem?) : JavaModuleFinder {
internal fun computeAllSystemModules(): Map<String, JavaModuleInfo> {
return jrtFileSystem?.findFileByPath("/modules")?.children.orEmpty()
.mapNotNull { root -> root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) }
.mapNotNull((JavaModuleInfo)::read)
.associateBy { moduleInfo -> moduleInfo.moduleName }
}
override fun findModule(name: String): JavaModuleInfo? {
val file = jrtFileSystem?.findFileByPath("/modules/$name/${PsiJavaModule.MODULE_INFO_CLS_FILE}")
if (file != null) {
val moduleInfo = JavaModuleInfo.read(file)
if (moduleInfo != null) {
return moduleInfo
}
}
return null
}
}

View File

@@ -26,16 +26,28 @@ import kotlin.script.dependencies.KotlinScriptExternalDependencies
class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory<ScriptDescriptor>(state.lock) {
override fun reset(): Iterable<ILineId> {
val removedCompiledLines = super.reset()
val removedAnalyzedLines = state.analyzerEngine.reset()
checkConsistent(removedCompiledLines, removedAnalyzedLines)
return removedCompiledLines
}
override fun resetTo(id: ILineId): Iterable<ILineId> {
val removedCompiledLines = super.resetTo(id)
val removedAnalyzedLines = state.analyzerEngine.resetToLine(id.no)
val removedAnalyzedLines = state.analyzerEngine.resetToLine(id)
checkConsistent(removedCompiledLines, removedAnalyzedLines)
return removedCompiledLines
}
private fun checkConsistent(removedCompiledLines: Iterable<ILineId>, removedAnalyzedLines: List<ReplCodeLine>) {
removedCompiledLines.zip(removedAnalyzedLines).forEach {
if (it.first != LineId(it.second)) {
throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}")
}
}
return removedCompiledLines
}
}

View File

@@ -19,6 +19,7 @@
package org.jetbrains.kotlin.cli.jvm.repl
import org.jetbrains.kotlin.cli.common.repl.CompiledReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ILineId
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ReplHistory
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
@@ -88,7 +89,9 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
}
}
fun resetToLine(lineNumber: Int): List<ReplCodeLine> = replState.resetToLine(lineNumber)
fun resetToLine(lineId: ILineId): List<ReplCodeLine> = replState.resetToLine(lineId)
fun reset(): List<ReplCodeLine> = replState.reset()
fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
topDownAnalysisContext.scripts.clear()
@@ -172,12 +175,17 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>()
private val submittedLines = hashMapOf<KtFile, LineInfo>()
fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
val removed = successfulLines.resetToLine(lineNumber)
fun resetToLine(lineId: ILineId): List<ReplCodeLine> {
val removed = successfulLines.resetToLine(lineId.no)
removed.forEach { submittedLines.remove(it.second.linePsi) }
return removed.map { it.first }
}
fun reset(): List<ReplCodeLine> {
submittedLines.clear()
return successfulLines.reset().map { it.first }
}
fun submitLine(ktFile: KtFile, codeLine: ReplCodeLine) {
val line = LineInfo.SubmittedLine(ktFile, successfulLines.lastValue())
submittedLines[ktFile] = line

View File

@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.repl
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.cli.jvm.repl.LineResult.*
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.KotlinCompilerVersion
@@ -86,7 +86,7 @@ class ReplFromTerminal(
}
val lineResult = eval(line)
if (lineResult is LineResult.Incomplete) {
if (lineResult is ReplEvalResult.Incomplete) {
return WhatNextAfterOneLine.INCOMPLETE
}
else {
@@ -94,20 +94,20 @@ class ReplFromTerminal(
}
}
private fun eval(line: String): LineResult {
val lineResult = replInterpreter.eval(line)
when (lineResult) {
is ValueResult, UnitResult -> {
private fun eval(line: String): ReplEvalResult {
val evalResult = replInterpreter.eval(line)
when (evalResult) {
is ReplEvalResult.ValueResult, is ReplEvalResult.UnitResult -> {
writer.notifyCommandSuccess()
if (lineResult is ValueResult) {
writer.outputCommandResult(lineResult.valueAsString)
if (evalResult is ReplEvalResult.ValueResult) {
writer.outputCommandResult(evalResult.value.toString())
}
}
Incomplete -> writer.notifyIncomplete()
is Error.CompileTime -> writer.outputCompileError(lineResult.errorText)
is Error.Runtime -> writer.outputRuntimeError(lineResult.errorText)
is ReplEvalResult.Error.Runtime -> writer.outputRuntimeError(evalResult.message)
is ReplEvalResult.Error.CompileTime -> writer.outputRuntimeError(evalResult.message)
is ReplEvalResult.Incomplete -> writer.notifyIncomplete()
}
return lineResult
return evalResult
}
@Throws(Exception::class)

View File

@@ -16,143 +16,80 @@
package org.jetbrains.kotlin.cli.jvm.repl
import com.google.common.base.Throwables
import com.intellij.openapi.Disposable
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.repl.ReplClassLoader
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import java.io.PrintWriter
import java.net.URLClassLoader
import java.util.concurrent.atomic.AtomicInteger
class ReplInterpreter(
disposable: Disposable,
private val configuration: CompilerConfiguration,
private val replConfiguration: ReplConfiguration
): ReplConfiguration by replConfiguration {
private var lineNumber = 0
private val earlierLines = arrayListOf<EarlierLine>()
private val lineNumber = AtomicInteger()
private val previousIncompleteLines = arrayListOf<String>()
private val classLoader: ReplClassLoader = run {
val classpath = configuration.jvmClasspathRoots.map { it.toURI().toURL() }
ReplClassLoader(URLClassLoader(classpath.toTypedArray(), null))
}
private val environment = run {
configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, REPL_LINE_AS_SCRIPT_DEFINITION)
KotlinCoreEnvironment.createForProduction(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
private val messageCollector = object : MessageCollector {
private var hasErrors = false
private val messageRenderer = MessageRenderer.WITHOUT_PATHS
override fun clear() {
hasErrors = false
}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
val msg = messageRenderer.render(severity, message, location)
with (replConfiguration.writer) {
when (severity) {
CompilerMessageSeverity.EXCEPTION -> sendInternalErrorReport(msg)
CompilerMessageSeverity.ERROR -> outputCompileError(msg)
CompilerMessageSeverity.STRONG_WARNING -> {} // TODO consider reporting this and two below
CompilerMessageSeverity.WARNING -> {}
CompilerMessageSeverity.INFO -> {}
else -> {}
}
}
}
override fun hasErrors(): Boolean = hasErrors
}
private val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
private val analyzerEngine = ReplCodeAnalyzer(environment)
// TODO: add script definition with project-based resolving for IDEA repl
private val scriptCompiler: ReplCompiler by lazy { GenericReplCompiler(disposable, REPL_LINE_AS_SCRIPT_DEFINITION, configuration, messageCollector) }
private val scriptEvaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(scriptCompiler, configuration.jvmClasspathRoots, classLoader, null, ReplRepeatingMode.REPEAT_ANY_PREVIOUS) }
fun eval(line: String): LineResult {
++lineNumber
private val evalState by lazy { scriptEvaluator.createState() }
fun eval(line: String): ReplEvalResult {
val fullText = (previousIncompleteLines + line).joinToString(separator = "\n")
val virtualFile =
LightVirtualFile("line$lineNumber${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, fullText).apply {
charset = CharsetToolkit.UTF8_CHARSET
}
val psiFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
?: error("Script file not analyzed at line $lineNumber: $fullText")
val errorHolder = createDiagnosticHolder()
val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorHolder)
if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) {
return if (allowIncompleteLines) {
previousIncompleteLines.add(line)
LineResult.Incomplete
}
else {
LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
}
}
previousIncompleteLines.clear()
if (syntaxErrorReport.isHasErrors) {
return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
}
val analysisResult = analyzerEngine.analyzeReplLine(psiFile, ReplCodeLine(lineNumber, 0, "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
else -> error("Unexpected result ${analysisResult::class.java}")
}
val state = GenerationState(
psiFile.project,
ClassBuilderFactories.binaries(false),
analyzerEngine.module,
analyzerEngine.trace.bindingContext,
listOf(psiFile),
configuration)
compileScript(psiFile.script!!, earlierLines.map(EarlierLine::getScriptDescriptor), state, CompilationErrorHandler.THROW_EXCEPTION)
for (outputFile in state.factory.asList()) {
if (outputFile.relativePath.endsWith(".class")) {
classLoader.addClass(JvmClassName.byInternalName(outputFile.relativePath.replaceFirst("\\.class$".toRegex(), "")),
outputFile.asByteArray())
}
}
try {
val scriptClass = classLoader.loadClass("Line$lineNumber")
val constructorParams = earlierLines.map(EarlierLine::getScriptClass).toTypedArray()
val constructorArgs = earlierLines.map(EarlierLine::getScriptInstance).toTypedArray()
val evalRes = scriptEvaluator.compileAndEval(evalState, ReplCodeLine(lineNumber.getAndIncrement(), 0, fullText), null, object : InvokeWrapper {
override fun <T> invoke(body: () -> T): T = executeUserCode { body() }
})
val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams)
val scriptInstance = try {
executeUserCode { scriptInstanceConstructor.newInstance(*constructorArgs) }
when {
evalRes !is ReplEvalResult.Incomplete -> previousIncompleteLines.clear()
allowIncompleteLines -> previousIncompleteLines.add(line)
else -> return ReplEvalResult.Error.CompileTime("incomplete code")
}
catch (e: Throwable) {
// ignore everything in the stack trace until this constructor call
return LineResult.Error.Runtime(renderStackTrace(e.cause!!, startFromMethodName = "${scriptClass.name}.<init>"))
}
val rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }
val rv: Any? = rvField.get(scriptInstance)
earlierLines.add(EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance))
if (!state.replSpecific.hasResult) {
return LineResult.UnitResult
}
val valueAsString: String = try {
executeUserCode { rv.toString() }
}
catch (e: Throwable) {
return LineResult.Error.Runtime(renderStackTrace(e, startFromMethodName = "java.lang.String.valueOf"))
}
return LineResult.ValueResult(valueAsString)
return evalRes
}
catch (e: Throwable) {
val writer = PrintWriter(System.err)
@@ -177,59 +114,8 @@ class ReplInterpreter(
}
companion object {
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
private val REPL_LINE_AS_SCRIPT_DEFINITION = object : KotlinScriptDefinition(Any::class) {
override val name = "Kotlin REPL"
}
private fun renderStackTrace(cause: Throwable, startFromMethodName: String): String {
val newTrace = arrayListOf<StackTraceElement>()
var skip = true
for (element in cause.stackTrace.reversed()) {
if ("${element.className}.${element.methodName}" == startFromMethodName) {
skip = false
}
if (!skip) {
newTrace.add(element)
}
}
val resultingTrace = newTrace.reversed().dropLast(1)
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UsePropertyAccessSyntax")
(cause as java.lang.Throwable).setStackTrace(resultingTrace.toTypedArray())
return Throwables.getStackTraceAsString(cause)
}
fun compileScript(
script: KtScript,
earlierScripts: List<ScriptDescriptor>,
state: GenerationState,
errorHandler: CompilationErrorHandler
) {
state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
state.replSpecific.earlierScriptsForReplInterpreter = earlierScripts.toList()
state.beforeCompile()
KotlinCodegenFacade.generatePackage(
state,
script.containingKtFile.packageFqName,
setOf(script.containingKtFile),
errorHandler
)
}
}
}
sealed class LineResult {
class ValueResult(val valueAsString: String): LineResult()
object UnitResult: LineResult()
object Incomplete : LineResult()
sealed class Error(val errorText: String): LineResult() {
class Runtime(errorText: String): Error(errorText)
class CompileTime(errorText: String): Error(errorText)
}
}

View File

@@ -60,7 +60,7 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
environment: Env,
daemonOptions: DaemonOptions = configureDaemonOptions()
): CompileServiceSession? {
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritOtherJvmOptions = false, inheritAdditionalProperties = true)
val daemonReportMessages = ArrayList<DaemonReportMessage>()
val daemonReportingTargets = DaemonReportingTargets(messages = daemonReportMessages)

View File

@@ -102,7 +102,7 @@ object KotlinCompilerClient {
autostart: Boolean,
leaseSession: Boolean,
sessionAliveFlagFile: File? = null
): CompileServiceSession? = connectLoop(reportingTargets) {
): CompileServiceSession? = connectLoop(reportingTargets, autostart) { isLastAttempt ->
ensureServerHostnameIsSetUp()
val (service, newJVMOptions) = tryFindSuitableDaemonOrNewOpts(File(daemonOptions.runFilesPath), compilerId, daemonJVMOptions, { cat, msg -> reportingTargets.report(cat, msg) })
if (service != null) {
@@ -119,7 +119,7 @@ object KotlinCompilerClient {
}
} else {
reportingTargets.report(DaemonReportCategory.DEBUG, "no suitable daemon found")
if (autostart) {
if (!isLastAttempt && autostart) {
startDaemon(compilerId, newJVMOptions, daemonOptions, reportingTargets)
reportingTargets.report(DaemonReportCategory.DEBUG, "new daemon started, trying to find it")
}
@@ -145,6 +145,7 @@ object KotlinCompilerClient {
compilerService.releaseCompileSession(sessionId)
}
@Deprecated("Use other compile method", ReplaceWith("compile"))
fun compile(compilerService: CompileService,
sessionId: Int,
targetPlatform: CompileService.TargetPlatform,
@@ -158,6 +159,7 @@ object KotlinCompilerClient {
}
@Deprecated("Use non-deprecated compile method", ReplaceWith("compile"))
fun incrementalCompile(compileService: CompileService,
sessionId: Int,
targetPlatform: CompileService.TargetPlatform,
@@ -234,7 +236,7 @@ object KotlinCompilerClient {
fun main(vararg args: String) {
val compilerId = CompilerId()
val daemonOptions = configureDaemonOptions()
val daemonLaunchingOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
val daemonLaunchingOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritOtherJvmOptions = false, inheritAdditionalProperties = true)
val clientOptions = configureClientOptions()
val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, daemonLaunchingOptions, clientOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX)
@@ -308,24 +310,27 @@ object KotlinCompilerClient {
// --- Implementation ---------------------------------------
private inline fun <R> connectLoop(reportingTargets: DaemonReportingTargets, body: () -> R?): R? {
@Synchronized
private inline fun <R> connectLoop(reportingTargets: DaemonReportingTargets, autostart: Boolean, body: (Boolean) -> R?): R? {
try {
var attempts = 0
while (attempts < DAEMON_CONNECT_CYCLE_ATTEMPTS) {
attempts += 1
var attempts = 1
while (true) {
val (res, err) = try {
body() to null
body(attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS) to null
}
catch (e: SocketException) { null to e }
catch (e: ConnectException) { null to e }
catch (e: ConnectIOException) { null to e }
catch (e: UnmarshalException) { null to e }
when {
res != null -> return res
err != null && attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS -> throw err
err != null ->
reportingTargets.report(DaemonReportCategory.INFO, "retrying($attempts) on: " + err.toString())
if (res != null) return res
reportingTargets.report(DaemonReportCategory.INFO,
(if (attempts >= DAEMON_CONNECT_CYCLE_ATTEMPTS || !autostart) "no more retries on: " else "retrying($attempts) on: ")
+ err?.toString())
if (attempts++ > DAEMON_CONNECT_CYCLE_ATTEMPTS || !autostart) {
return null
}
}
}
@@ -335,26 +340,6 @@ object KotlinCompilerClient {
return null
}
private fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String = "daemon client") {
if (category == DaemonReportCategory.DEBUG && !verboseReporting) return
out?.println("[$source] ${category.name}: $message")
messages?.add(DaemonReportMessage(category, "[$source] $message"))
messageCollector?.let {
when (category) {
DaemonReportCategory.DEBUG -> it.report(CompilerMessageSeverity.LOGGING, message)
DaemonReportCategory.INFO -> it.report(CompilerMessageSeverity.INFO, message)
DaemonReportCategory.EXCEPTION -> it.report(CompilerMessageSeverity.EXCEPTION, message)
}
}
compilerServices?.let {
when (category) {
DaemonReportCategory.DEBUG -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.DEBUG, message, source)
DaemonReportCategory.INFO -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.INFO, message, source)
DaemonReportCategory.EXCEPTION -> it.report(ReportCategory.EXCEPTION, ReportSeverity.ERROR, message, source)
}
}
}
private fun tryFindSuitableDaemonOrNewOpts(registryDir: File, compilerId: CompilerId, daemonJVMOptions: DaemonJVMOptions, report: (DaemonReportCategory, String) -> Unit): Pair<CompileService?, DaemonJVMOptions> {
registryDir.mkdirs()
val timestampMarker = createTempFile("kotlin-daemon-client-tsmarker", directory = registryDir)
@@ -364,7 +349,7 @@ object KotlinCompilerClient {
finally {
timestampMarker.delete()
}
val comparator = compareByDescending<DaemonWithMetadata, DaemonJVMOptions>(DaemonJVMOptionsMemoryComparator(), { it.jvmOptions })
val comparator = compareBy<DaemonWithMetadata, DaemonJVMOptions>(DaemonJVMOptionsMemoryComparator(), { it.jvmOptions })
.thenBy(FileAgeComparator()) { it.runFile }
val optsCopy = daemonJVMOptions.copy()
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
@@ -395,19 +380,7 @@ object KotlinCompilerClient {
val processBuilder = ProcessBuilder(args)
processBuilder.redirectErrorStream(true)
// assuming daemon process is deaf and (mostly) silent, so do not handle streams
val daemon =
try {
launchWithNativePlatformLauncher(processBuilder)
}
catch (e: IOException) {
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start daemon with native process launcher, falling back to ProcessBuilder#start (${e.cause})")
null
}
catch (e: NoClassDefFoundError) {
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start")
null
}
?: processBuilder.start()
val daemon = launchProcessWithFallback(processBuilder, reportingTargets, "daemon client")
val isEchoRead = Semaphore(1)
isEchoRead.acquire()
@@ -418,19 +391,21 @@ object KotlinCompilerClient {
daemon.inputStream
.reader()
.forEachLine {
reportingTargets.report(DaemonReportCategory.DEBUG, it, "daemon")
if (it == COMPILE_DAEMON_IS_READY_MESSAGE) {
reportingTargets.report(DaemonReportCategory.DEBUG, "Received the message signalling that the daemon is ready")
isEchoRead.release()
return@forEachLine
}
else {
reportingTargets.report(DaemonReportCategory.INFO, it, "daemon")
}
}
}
finally {
daemon.inputStream.close()
daemon.outputStream.close()
daemon.errorStream.close()
isEchoRead.release()
}
}
try {
@@ -474,6 +449,25 @@ class DaemonReportingTargets(val out: PrintStream? = null,
val messageCollector: MessageCollector? = null,
val compilerServices: CompilerServicesFacadeBase? = null)
internal fun DaemonReportingTargets.report(category: DaemonReportCategory, message: String, source: String? = null) {
val sourceMessage: String by lazy { source?.let { "[$it] $message" } ?: message }
out?.println("${category.name}: $sourceMessage")
messages?.add(DaemonReportMessage(category, sourceMessage))
messageCollector?.let {
when (category) {
DaemonReportCategory.DEBUG -> it.report(CompilerMessageSeverity.LOGGING, sourceMessage)
DaemonReportCategory.INFO -> it.report(CompilerMessageSeverity.INFO, sourceMessage)
DaemonReportCategory.EXCEPTION -> it.report(CompilerMessageSeverity.EXCEPTION, sourceMessage)
}
}
compilerServices?.let {
when (category) {
DaemonReportCategory.DEBUG -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.DEBUG, message, source)
DaemonReportCategory.INFO -> it.report(ReportCategory.DAEMON_MESSAGE, ReportSeverity.INFO, message, source)
DaemonReportCategory.EXCEPTION -> it.report(ReportCategory.EXCEPTION, ReportSeverity.ERROR, message, source)
}
}
}
internal fun isProcessAlive(process: Process) =
try {

View File

@@ -16,17 +16,31 @@
package org.jetbrains.kotlin.daemon.client
import net.rubygrapefruit.platform.Native
import net.rubygrapefruit.platform.NativeException
import net.rubygrapefruit.platform.ProcessLauncher
import org.jetbrains.kotlin.daemon.common.DaemonReportCategory
import java.io.IOException
internal fun launchWithNativePlatformLauncher(processBuilder: ProcessBuilder): Process {
return try {
val nativeLauncher = Native.get(ProcessLauncher::class.java)
nativeLauncher.start(processBuilder)
}
catch (e: NativeException) {
throw IOException(e)
}
}
private class NativePlatformLauncherWrapper {
fun launch(processBuilder: ProcessBuilder): Process =
try {
val nativeLauncher = net.rubygrapefruit.platform.Native.get(net.rubygrapefruit.platform.ProcessLauncher::class.java)
nativeLauncher.start(processBuilder)
}
catch (e: net.rubygrapefruit.platform.NativeException) {
throw IOException(e)
}
}
fun launchProcessWithFallback(processBuilder: ProcessBuilder, reportingTargets: DaemonReportingTargets, reportingSource: String = "process launcher"): Process =
try {
NativePlatformLauncherWrapper().launch(processBuilder)
}
catch (e: IOException) {
reportingTargets.report(DaemonReportCategory.DEBUG, "Could not start process with native process launcher, falling back to ProcessBuilder#start (${e.cause})")
null
}
catch (e: NoClassDefFoundError) {
reportingTargets.report(DaemonReportCategory.DEBUG, "net.rubygrapefruit.platform library is not in the classpath, falling back to ProcessBuilder#start")
null
}
?: processBuilder.start()

View File

@@ -37,10 +37,12 @@ class RemoteReplCompilerStateHistory(private val state: RemoteReplCompilerState)
throw NotImplementedError("pop from remote history is not supported")
}
override fun reset(): Iterable<ILineId> = state.replStateFacade.historyReset().apply {
currentGeneration.incrementAndGet()
}
override fun resetTo(id: ILineId): Iterable<ILineId> = state.replStateFacade.historyResetTo(id).apply {
if (isNotEmpty()) {
currentGeneration.incrementAndGet()
}
currentGeneration.incrementAndGet()
}
val currentGeneration = AtomicInteger(REPL_CODE_LINE_FIRST_GEN)

View File

@@ -44,6 +44,10 @@ private const val ORPHANED_RUN_FILE_AGE_THRESHOLD_MS = 1000000L
data class DaemonWithMetadata(val daemon: CompileService, val runFile: File, val jvmOptions: DaemonJVMOptions)
// TODO: write metadata into discovery file to speed up selection
// TODO: consider using compiler jar signature (checksum) as a CompilerID (plus java version, plus ???) instead of classpath checksum
// would allow to use same compiler from taken different locations
// reqs: check that plugins (or anything els) should not be part of the CP
fun walkDaemons(registryDir: File,
compilerId: CompilerId,
fileToCompareTimestamp: File,

View File

@@ -257,15 +257,44 @@ data class CompilerId(
fun isDaemonEnabled(): Boolean = System.getProperty(COMPILE_DAEMON_ENABLED_PROPERTY) != null
fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
vararg additionalParams: String,
inheritMemoryLimits: Boolean,
inheritOtherJvmOptions: Boolean,
inheritAdditionalProperties: Boolean
): DaemonJVMOptions =
configureDaemonJVMOptions(opts, additionalParams.asIterable(), inheritMemoryLimits, inheritOtherJvmOptions, inheritAdditionalProperties)
// TODO: expose sources for testability and test properly
fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
additionalParams: Iterable<String>,
inheritMemoryLimits: Boolean,
inheritOtherJvmOptions: Boolean,
inheritAdditionalProperties: Boolean
): DaemonJVMOptions {
// note: sequence matters, explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
if (inheritMemoryLimits) {
ManagementFactory.getRuntimeMXBean().inputArguments.filterExtractProps(opts.mappers, "-")
// note: sequence matters, e.g. explicit override in COMPILE_DAEMON_JVM_OPTIONS_PROPERTY should be done after inputArguments processing
if (inheritMemoryLimits || inheritOtherJvmOptions) {
val jvmArguments = ManagementFactory.getRuntimeMXBean().inputArguments
val targetOptions = if (inheritMemoryLimits) opts else DaemonJVMOptions()
val otherArgs = jvmArguments.filterExtractProps(targetOptions.mappers, prefix = "-")
if (inheritMemoryLimits && opts.maxMemory.isBlank()) {
val maxMemBytes = Runtime.getRuntime().maxMemory()
// rounding up
val maxMemMegabytes = maxMemBytes / (1024 * 1024) + if (maxMemBytes % (1024 * 1024) == 0L) 0 else 1
opts.maxMemory = "${maxMemMegabytes}m"
}
if (inheritOtherJvmOptions) {
opts.jvmParams.addAll(
otherArgs.filterNot {
it.startsWith("agentlib") ||
it.startsWith("D" + COMPILE_DAEMON_LOG_PATH_PROPERTY) ||
it.startsWith("D" + KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY) ||
it.startsWith("D" + COMPILE_DAEMON_JVM_OPTIONS_PROPERTY) ||
it.startsWith("D" + COMPILE_DAEMON_OPTIONS_PROPERTY)
})
}
}
System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let {
opts.jvmParams.addAll(
@@ -275,7 +304,10 @@ fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
.filterExtractProps(opts.mappers, "-", opts.restMapper))
}
// assuming that from the conflicting options the last one is taken
// TODO: compare and override
opts.jvmParams.addAll(additionalParams)
if (inheritAdditionalProperties) {
System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.let { opts.jvmParams.add("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"$it\"") }
System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { opts.jvmParams.add("D$KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY") }
@@ -285,12 +317,14 @@ fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
fun configureDaemonJVMOptions(vararg additionalParams: String,
inheritMemoryLimits: Boolean,
inheritAdditionalProperties: Boolean
inheritMemoryLimits: Boolean,
inheritOtherJvmOptions: Boolean,
inheritAdditionalProperties: Boolean
): DaemonJVMOptions =
configureDaemonJVMOptions(DaemonJVMOptions(),
additionalParams = *additionalParams,
inheritMemoryLimits = inheritMemoryLimits,
inheritOtherJvmOptions = inheritOtherJvmOptions,
inheritAdditionalProperties = inheritAdditionalProperties)

View File

@@ -31,6 +31,9 @@ interface ReplStateFacade : Remote {
@Throws(RemoteException::class)
fun historyGet(index: Int): ILineId
@Throws(RemoteException::class)
fun historyReset(): List<ILineId>
@Throws(RemoteException::class)
fun historyResetTo(id: ILineId): List<ILineId>
}

View File

@@ -107,6 +107,8 @@ class CompileServiceImpl(
val onShutdown: () -> Unit
) : CompileService {
private val log by lazy { Logger.getLogger("compiler") }
init {
System.setProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
}
@@ -184,8 +186,6 @@ class CompileServiceImpl(
@Volatile private var _lastUsedSeconds = nowSeconds()
val lastUsedSeconds: Long get() = if (rwlock.isWriteLocked || rwlock.readLockCount - rwlock.readHoldCount > 0) nowSeconds() else _lastUsedSeconds
private val log by lazy { Logger.getLogger("compiler") }
private val rwlock = ReentrantReadWriteLock()
private var runFile: File
@@ -212,12 +212,15 @@ class CompileServiceImpl(
}
override fun getDaemonJVMOptions(): CompileService.CallResult<DaemonJVMOptions> = ifAlive {
log.info("getDaemonJVMOptions: $daemonJVMOptions")// + daemonJVMOptions.mappers.flatMap { it.toArgs("-") })
CompileService.CallResult.Good(daemonJVMOptions)
}
override fun registerClient(aliveFlagPath: String?): CompileService.CallResult<Nothing> = ifAlive {
synchronized(state.clientProxies) {
state.clientProxies.add(ClientOrSessionProxy(aliveFlagPath))
log.info("Registered a client alive file: $aliveFlagPath")
}
CompileService.CallResult.Ok()
}
@@ -232,7 +235,7 @@ class CompileServiceImpl(
override fun leaseCompileSession(aliveFlagPath: String?): CompileService.CallResult<Int> = ifAlive(minAliveness = Aliveness.Alive) {
CompileService.CallResult.Good(
state.sessions.leaseSession(ClientOrSessionProxy<Any>(aliveFlagPath)).apply {
log.info("leased a new session $this, client alive file: $aliveFlagPath")
log.info("leased a new session $this, session alive file: $aliveFlagPath")
})
}
@@ -335,6 +338,7 @@ class CompileServiceImpl(
val daemonReporter = DaemonMessageReporter(servicesFacade, compilationOptions)
val compilerMode = compilationOptions.compilerMode
val targetPlatform = compilationOptions.targetPlatform
log.info("Starting compilation with args: " + compilerArguments.joinToString(" "))
val k2PlatformArgs = try {
when (targetPlatform) {
CompileService.TargetPlatform.JVM -> K2JVMCompilerArguments().apply { K2JVMCompiler().parseArguments(compilerArguments, this) }
@@ -709,6 +713,10 @@ class CompileServiceImpl(
private fun shutdownImpl() {
log.info("Shutdown started")
fun Long.mb() = this / (1024 * 1024)
with (Runtime.getRuntime()) {
log.info("Memory stats: total: ${totalMemory().mb()}mb, free: ${freeMemory().mb()}mb, max: ${maxMemory().mb()}mb")
}
state.alive.set(Aliveness.Dying.ordinal)
UnicastRemoteObject.unexportObject(this, true)
@@ -869,9 +877,18 @@ class CompileServiceImpl(
ifAliveChecksImpl(minAliveness, ignoreCompilerChanged, body)
}
inline private fun<R> ifAliveChecksImpl(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> CompileService.CallResult<R>): CompileService.CallResult<R> =
when {
state.alive.get() < minAliveness.ordinal -> CompileService.CallResult.Dying()
inline private fun<R> ifAliveChecksImpl(minAliveness: Aliveness = Aliveness.Alive, ignoreCompilerChanged: Boolean = false, body: () -> CompileService.CallResult<R>): CompileService.CallResult<R> {
val curState = state.alive.get()
return when {
curState < minAliveness.ordinal -> {
log.info("Cannot perform operation, requested state: ${minAliveness.name} > actual: ${try {
Aliveness.values()[curState].name
}
catch (_: Throwable) {
"invalid($curState)"
}}")
CompileService.CallResult.Dying()
}
!ignoreCompilerChanged && classpathWatcher.isChanged -> {
log.info("Compiler changed, scheduling shutdown")
shutdownWithDelay()
@@ -887,6 +904,7 @@ class CompileServiceImpl(
}
}
}
}
private inline fun<R> withValidClientOrSessionProxy(sessionId: Int,
body: (ClientOrSessionProxy<Any>?) -> CompileService.CallResult<R>

View File

@@ -91,8 +91,10 @@ object KotlinCompileDaemon {
fun main(args: Array<String>) {
ensureServerHostnameIsSetUp()
val jvmArguments = ManagementFactory.getRuntimeMXBean().inputArguments
log.info("Kotlin compiler daemon version " + (loadVersionFromResource() ?: "<unknown>"))
log.info("daemon JVM args: " + ManagementFactory.getRuntimeMXBean().inputArguments.joinToString(" "))
log.info("daemon JVM args: " + jvmArguments.joinToString(" "))
log.info("daemon args: " + args.joinToString(" "))
setIdeaIoUseFallback()
@@ -101,7 +103,9 @@ object KotlinCompileDaemon {
val daemonOptions = DaemonOptions()
try {
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true,
inheritOtherJvmOptions = true,
inheritAdditionalProperties = true)
val filteredArgs = args.asIterable().filterExtractProps(compilerId, daemonOptions, prefix = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX)

View File

@@ -35,5 +35,7 @@ class RemoteReplStateFacadeServer(val _id: Int,
override fun historyGet(index: Int): ILineId = state.history[index].id
override fun historyReset(): List<ILineId> = state.history.reset().toList()
override fun historyResetTo(id: ILineId): List<ILineId> = state.history.resetTo(id).toList()
}

View File

@@ -129,12 +129,16 @@ public class SingleAbstractMethodUtils {
@Nullable
public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull JavaClassDescriptor klass) {
if (klass.isDefinitelyNotSamInterface()) return null;
// NB: this check MUST BE at start. Please do not touch until following to-do is resolved
// Otherwise android data binding can cause resolve re-entrance
// For details see KT-18687, KT-16149
// TODO: prevent resolve re-entrance on architecture level, or (alternatively) ask data binding owners not to do it
if (DescriptorUtilsKt.getFqNameSafe(klass).asString().equals("android.databinding.DataBindingComponent")) {
return null;
}
if (klass.isDefinitelyNotSamInterface()) return null;
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
if (abstractMembers.size() == 1) {
CallableMemberDescriptor member = abstractMembers.get(0);

View File

@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedTypeAliasDescriptor
import java.io.File
import java.nio.file.Paths
interface ModuleVisibilityManager {
val chunk: Collection<Module>
@@ -66,24 +67,25 @@ fun isContainedByCompiledPartOfOurModule(descriptor: DeclarationDescriptor, outD
if (binaryClass is VirtualFileKotlinClass) {
val file = binaryClass.file
if (file.fileSystem.protocol == StandardFileSystems.FILE_PROTOCOL) {
val ioFile = VfsUtilCore.virtualToIoFile(file)
return ioFile.absolutePath.startsWith(outDirectory.absolutePath + File.separator)
val ioFile = when (file.fileSystem.protocol) {
StandardFileSystems.FILE_PROTOCOL -> VfsUtilCore.virtualToIoFile(file)
StandardFileSystems.JAR_PROTOCOL -> VfsUtilCore.getVirtualFileForJar(file)?.let(VfsUtilCore::virtualToIoFile)
else -> null
}
return ioFile != null && Paths.get(ioFile.toURI()).startsWith(Paths.get(outDirectory.toURI()))
}
return false
}
fun getSourceElement(descriptor: DeclarationDescriptor): SourceElement =
if (descriptor is CallableMemberDescriptor && descriptor.source === SourceElement.NO_SOURCE) {
descriptor.containingDeclaration.toSourceElement
}
else if (descriptor is DeserializedTypeAliasDescriptor) {
descriptor.containingDeclaration.toSourceElement
}
else {
descriptor.toSourceElement
when {
descriptor is CallableMemberDescriptor && descriptor.source === SourceElement.NO_SOURCE ->
getSourceElement(descriptor.containingDeclaration)
descriptor is DeserializedTypeAliasDescriptor ->
getSourceElement(descriptor.containingDeclaration)
else ->
descriptor.toSourceElement
}
private val DeclarationDescriptor.toSourceElement: SourceElement

View File

@@ -55,7 +55,7 @@ object JvmOverridesBackwardCompatibilityHelper : OverridesBackwardCompatibilityH
val containingClass = DescriptorUtils.getContainingClass(overriddenDescriptor)
?: return false
if (JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(containingClass.fqNameUnsafe) != null) return true
if (JavaToKotlinClassMap.mapKotlinToJava(containingClass.fqNameUnsafe) != null) return true
if (overriddenDescriptor.overriddenDescriptors.isEmpty()) return false
return isOverridingOnlyDescriptorsThatCanBeImplicitlyOverridden(overriddenDescriptor, visitedDescriptors)

View File

@@ -39,7 +39,9 @@ enum class JvmDeclarationOriginKind {
BRIDGE,
MULTIFILE_CLASS,
MULTIFILE_CLASS_PART,
SYNTHETIC // this means that there's no proper descriptor for this jvm declaration
SYNTHETIC, // this means that there's no proper descriptor for this jvm declaration,
COLLECTION_STUB,
AUGMENTED_BUILTIN_API
}
class JvmDeclarationOrigin(
@@ -91,3 +93,7 @@ fun Delegation(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclara
fun SamDelegation(descriptor: FunctionDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SAM_DELEGATION, null, descriptor)
fun Synthetic(element: PsiElement?, descriptor: CallableMemberDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SYNTHETIC, element, descriptor)
val CollectionStub = JvmDeclarationOrigin(COLLECTION_STUB, null, null)
fun AugmentedBuiltInApi(descriptor: CallableDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(AUGMENTED_BUILTIN_API, null, descriptor)

View File

@@ -0,0 +1,21 @@
/*
* 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.jvm.modules
interface JavaModuleFinder {
fun findModule(name: String): JavaModuleInfo?
}

View File

@@ -14,26 +14,29 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.jvm.modules
package org.jetbrains.kotlin.resolve.jvm.modules
import org.jetbrains.kotlin.storage.LockBasedStorageManager
class ModuleGraph(getModuleInfo: (String) -> JavaModuleInfo) {
private val moduleInfo: (String) -> JavaModuleInfo = LockBasedStorageManager.NO_LOCKS.createMemoizedFunction(getModuleInfo)
class JavaModuleGraph(finder: JavaModuleFinder) {
private val moduleInfo: (String) -> JavaModuleInfo? =
LockBasedStorageManager.NO_LOCKS.createMemoizedFunctionWithNullableValues(finder::findModule)
fun getAllReachable(rootModules: List<String>): List<String> {
val visited = linkedSetOf<String>()
fun getAllDependencies(moduleNames: List<String>): List<String> {
// Every module implicitly depends on java.base
val visited = linkedSetOf("java.base")
fun dfs(module: String) {
if (!visited.add(module)) return
for (dependency in moduleInfo(module).requires) {
val moduleInfo = moduleInfo(module) ?: return
for (dependency in moduleInfo.requires) {
if (dependency.isTransitive) {
dfs(dependency.moduleName)
}
}
}
rootModules.forEach(::dfs)
moduleNames.forEach(::dfs)
return visited.toList()
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.jvm.modules
package org.jetbrains.kotlin.resolve.jvm.modules
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.name.FqName

View File

@@ -75,7 +75,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
overloadFilter = JvmOverloadFilter,
platformToKotlinClassMap = JavaToKotlinClassMap.INSTANCE,
platformToKotlinClassMap = JavaToKotlinClassMap,
delegationFilter = JvmDelegationFilter,

View File

@@ -20,6 +20,8 @@ import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import java.io.File
import java.lang.management.ManagementFactory
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
@@ -63,69 +65,85 @@ class KotlinScriptExternalImportsProviderImpl(
// optimized for initial caching, additional handling of possible duplicates to save a call to distinct
// returns list of cached files
override fun <TF: Any> cacheExternalImports(files: Iterable<TF>): Iterable<TF> = cacheLock.write {
val uncached = hashSetOf<String>()
files.mapNotNull { file ->
val path = getFilePath(file)
if (isValidFile(file) && !cache.containsKey(path) && !uncached.contains(path)) {
var filesCount = 0
var additionsCount = 0
val (res, time) = measureThreadTimeMillis {
files.mapNotNull { file ->
filesCount += 1
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
if (scriptDef != null) {
val deps = scriptDef.getDependenciesFor(file, project, null)
if (deps != null) {
log.info("[kts] cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
val path = getFilePath(file)
if (isValidFile(file) && !cache.containsKey(path)) {
val deps = scriptDef.getDependenciesFor(file, project, null)
cache.put(path, deps)
if (deps != null) {
log.info("[kts] cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
additionsCount += 1
file
}
else null
}
cache.put(path, deps)
file
}
else {
uncached.add(path)
null
else null
}
else null
}
else null
}
log.info("[kts] cache creation: $filesCount checked, $additionsCount added (in ${time}ms)")
res
}
// optimized for update, no special duplicates handling
// returns files with valid script definition (or deleted from cache - which in fact should have script def too)
// TODO: this is the badly designed contract, since it mixes the entities, but these files are needed on the calling site now. Find out other solution
override fun <TF: Any> updateExternalImportsCache(files: Iterable<TF>): Iterable<TF> = cacheLock.write {
files.mapNotNull { file ->
val path = getFilePath(file)
if (!isValidFile(file)) {
if (cache.remove(path) != null) {
log.debug("[kts] removed deps for file $path")
file
} // cleared
else {
null // unknown
}
}
else {
var filesCount = 0
var updatesCount = 0
val (res, time) = measureThreadTimeMillis {
files.mapNotNull { file ->
filesCount += 1
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
if (scriptDef != null) {
val oldDeps = cache[path]
val deps = scriptDef.getDependenciesFor(file, project, oldDeps)
when {
deps != null && (oldDeps == null ||
!deps.classpath.isSamePathListAs(oldDeps.classpath) || !deps.sources.isSamePathListAs(oldDeps.sources)) -> {
// changed or new
log.info("[kts] updated/new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
cache.put(path, deps)
}
deps != null -> {
// same as before
}
else -> {
if (cache.remove(path) != null) {
val path = getFilePath(file)
if (!isValidFile(file)) {
if (cache.remove(path) != null) {
log.debug("[kts] removed deps for file $path")
updatesCount += 1
file
} // cleared
else null // unknown
}
else {
val oldDeps = cache[path]
val deps = scriptDef.getDependenciesFor(file, project, oldDeps)
when {
deps != null && (oldDeps == null ||
!deps.classpath.isSamePathListAs(oldDeps.classpath) || !deps.sources.isSamePathListAs(oldDeps.sources)) -> {
// changed or new
log.info("[kts] updated/new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
cache.put(path, deps)
updatesCount += 1
file
}
deps != null -> {
// same as before
null
}
cache.remove(path) != null -> {
log.debug("[kts] removed deps for $path")
} // cleared
updatesCount += 1
file
}
else -> null // unknown
}
}
file
}
else null // not a script
}
}
if (updatesCount > 0) {
log.info("[kts] cache update check: $filesCount checked, $updatesCount updated (in ${time}ms)")
}
res
}
override fun invalidateCaches() {
@@ -160,3 +178,10 @@ private fun Iterable<File>.isSamePathListAs(other: Iterable<File>): Boolean =
}
!(first.hasNext() || second.hasNext())
}
private inline fun<T> measureThreadTimeMillis(body: () -> T): Pair<T, Long> {
val mxBeans = ManagementFactory.getThreadMXBean()
val startTime = mxBeans.currentThreadCpuTime
val res = body()
return res to TimeUnit.NANOSECONDS.toMillis(mxBeans.currentThreadCpuTime - startTime)
}

View File

@@ -41,13 +41,14 @@ import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.utils.keysToMap
import java.util.*
import kotlin.coroutines.experimental.buildSequence
class ResolverForModule(
val packageFragmentProvider: PackageFragmentProvider,
val componentProvider: ComponentProvider
val packageFragmentProvider: PackageFragmentProvider,
val componentProvider: ComponentProvider
)
abstract class ResolverForProject<M : ModuleInfo> {
@@ -84,7 +85,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
return resolverForModuleDescriptor(doGetDescriptorForModule(moduleInfo))
}
internal val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> ResolverForModule> = HashMap()
internal val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, NotNullLazyValue<ResolverForModule>> = HashMap()
override val allModules: Collection<M> by lazy {
(descriptorByModule.keys + delegateResolver.allModules).toSet()
@@ -168,7 +169,8 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
firstDependency: M? = null,
modulePlatforms: (M) -> MultiTargetPlatform?
modulePlatforms: (M) -> MultiTargetPlatform?,
packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
): ResolverForProject<M> {
val storageManager = projectContext.storageManager
@@ -212,8 +214,10 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
for (module in modules) {
val descriptor = resolverForProject.descriptorForModule(module)
val content = modulesContent(module)
val computeResolverForModule = storageManager.createLazyValue {
val content = modulesContent(module)
ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
analyzerFacade(module).createResolverForModule(
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
platformParameters, targetEnvironment, resolverForProject,
@@ -221,7 +225,9 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
)
}
descriptor.initialize(DelegatingPackageFragmentProvider { computeResolverForModule().packageFragmentProvider })
DelegatingPackageFragmentProvider(content, packageOracleFactory.createOracle(module), computeResolverForModule)
.let { descriptor.initialize(it) }
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
}
@@ -243,17 +249,45 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
abstract val targetPlatform: TargetPlatform
}
//NOTE: relies on delegate to be lazily computed and cached
private class DelegatingPackageFragmentProvider(
private val delegate: () -> PackageFragmentProvider
moduleContent: ModuleContent,
private val packageOracle: PackageOracle,
private val resolverForModule: NotNullLazyValue<ResolverForModule>
) : PackageFragmentProvider {
private val syntheticFilePackages = moduleContent.syntheticFiles.map { it.packageFqName }.toSet()
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
return delegate().getPackageFragments(fqName)
if (certainlyDoesNotExist(fqName)) return emptyList()
return resolverForModule().packageFragmentProvider.getPackageFragments(fqName)
}
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
return delegate().getSubPackagesOf(fqName, nameFilter)
if (certainlyDoesNotExist(fqName)) return emptyList()
return resolverForModule().packageFragmentProvider.getSubPackagesOf(fqName, nameFilter)
}
private fun certainlyDoesNotExist(fqName: FqName): Boolean {
if (resolverForModule.isComputed()) return false // let this request get cached inside delegate
return !packageOracle.packageExists(fqName) && fqName !in syntheticFilePackages
}
}
interface PackageOracle {
fun packageExists(fqName: FqName): Boolean
object Optimistic : PackageOracle {
override fun packageExists(fqName: FqName): Boolean = true
}
}
interface PackageOracleFactory {
fun createOracle(moduleInfo: ModuleInfo): PackageOracle
object OptimisticFactory : PackageOracleFactory {
override fun createOracle(moduleInfo: ModuleInfo) = PackageOracle.Optimistic
}
}
@@ -271,4 +305,13 @@ interface LanguageSettingsProvider {
companion object {
fun getInstance(project: Project) = ServiceManager.getService(project, LanguageSettingsProvider::class.java) ?: Default
}
}
interface ResolverForModuleComputationTracker {
fun onResolverComputed(moduleInfo: ModuleInfo)
companion object {
fun getInstance(project: Project): ResolverForModuleComputationTracker? = ServiceManager.getService(project, ResolverForModuleComputationTracker::class.java) ?: null
}
}

View File

@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.cfg.pseudocodeTraverser.*
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.referencedProperty
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors
@@ -53,9 +52,12 @@ import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWi
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.hasThisOrNoDispatchReceiver
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils.*
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.*
@@ -398,18 +400,6 @@ class ControlFlowInformationProvider private constructor(
varWithValReassignErrorGenerated: MutableCollection<VariableDescriptor>
): Boolean {
val variableDescriptor = ctxt.variableDescriptor
val propertyDescriptor = variableDescriptor?.referencedProperty
if (KtPsiUtil.isBackingFieldReference(variableDescriptor) && propertyDescriptor != null) {
val accessor = getParentOfType(expression, KtPropertyAccessor::class.java)
if (accessor != null) {
val accessorDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, accessor)
if (propertyDescriptor.getter === accessorDescriptor) {
//val can be reassigned through backing field inside its own getter
return false
}
}
}
val mayBeInitializedNotHere = ctxt.enterInitState?.mayBeInitialized() ?: false
val hasBackingField = (variableDescriptor as? PropertyDescriptor)?.let {
trace.get(BindingContext.BACKING_FIELD_REQUIRED, it)
@@ -467,7 +457,12 @@ class ControlFlowInformationProvider private constructor(
}
}
else {
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
if (KtPsiUtil.isBackingFieldReference(variableDescriptor)) {
report(Errors.VAL_REASSIGNMENT_VIA_BACKING_FIELD.on(expression, variableDescriptor), ctxt)
}
else {
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
}
}
}
if (isThisOrNoDispatchReceiver) {
@@ -642,7 +637,7 @@ class ControlFlowInformationProvider private constructor(
val containingClass = owner.getContainingClassOrObject()
val containingClassDescriptor = trace.get(DECLARATION_TO_DESCRIPTOR, containingClass) as? ClassDescriptor
if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor) && containingClassDescriptor?.isHeader == false &&
!DescriptorUtils.isEffectivelyExternal(containingClassDescriptor)
!containingClassDescriptor.isEffectivelyExternal()
) {
report(UNUSED_PARAMETER.on(element, variableDescriptor), ctxt)
}
@@ -662,7 +657,7 @@ class ControlFlowInformationProvider private constructor(
|| functionDescriptor.isOverridableOrOverrides
|| owner.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|| functionDescriptor.isHeader || functionDescriptor.isImpl
|| DescriptorUtils.isEffectivelyExternal(functionDescriptor)
|| functionDescriptor.isEffectivelyExternal()
|| OperatorNameConventions.GET_VALUE == functionName
|| OperatorNameConventions.SET_VALUE == functionName
|| OperatorNameConventions.PROVIDE_DELEGATE == functionName) {
@@ -777,25 +772,41 @@ class ControlFlowInformationProvider private constructor(
for (element in instruction.owner.getValueElements(value)) {
if (element !is KtWhenExpression) continue
if (element.isUsedAsExpression(trace.bindingContext)) {
val usedAsExpression = element.isUsedAsExpression(trace.bindingContext)
if (usedAsExpression) {
checkImplicitCastOnConditionalExpression(element)
}
if (element.elseExpression != null) continue
val context = trace.bindingContext
val necessaryCases = WhenChecker.getNecessaryCases(element, context)
if (!necessaryCases.isEmpty()) {
trace.report(NO_ELSE_IN_WHEN.on(element, necessaryCases))
val missingCases = WhenChecker.getMissingCases(element, context)
val elseEntry = element.entries.find { it.isElse }
val subjectExpression = element.subjectExpression
if (usedAsExpression && missingCases.isNotEmpty()) {
if (elseEntry != null) continue
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
}
else {
val subjectExpression = element.subjectExpression
if (subjectExpression != null) {
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(trace.getType(subjectExpression))
else if (subjectExpression != null) {
val subjectType = trace.getType(subjectExpression)
if (elseEntry != null) {
if (missingCases.isEmpty() && subjectType != null && !subjectType.isFlexible()) {
val subjectClass = subjectType.constructor.declarationDescriptor as? ClassDescriptor
val pseudocodeElement = instruction.owner.correspondingElement
val pseudocodeDescriptor = trace[DECLARATION_TO_DESCRIPTOR, pseudocodeElement]
if (subjectClass == null ||
KotlinBuiltIns.isBooleanOrNullableBoolean(subjectType) ||
subjectClass.module == pseudocodeDescriptor?.module) {
trace.report(REDUNDANT_ELSE_IN_WHEN.on(elseEntry))
}
}
continue
}
if (!usedAsExpression) {
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType)
if (enumClassDescriptor != null) {
val missingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
if (!missingCases.isEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN.on(element, missingCases))
val enumMissingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
if (!enumMissingCases.isEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN.on(element, enumMissingCases))
}
}
}

View File

@@ -262,11 +262,6 @@ object WhenChecker {
WhenOnEnumExhaustivenessChecker,
WhenOnSealedExhaustivenessChecker)
@JvmStatic
fun getNecessaryCases(expression: KtWhenExpression, context: BindingContext) =
if (expression.isUsedAsExpression(context)) getMissingCases(expression, context)
else listOf()
@JvmStatic
fun isWhenByEnum(expression: KtWhenExpression, context: BindingContext) =
getClassDescriptorOfTypeIfEnum(whenSubjectType(expression, context)) != null

View File

@@ -761,6 +761,7 @@ public interface Errors {
DiagnosticFactory0<KtLambdaExpression> UNUSED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<KtExpression, DeclarationDescriptor> VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtExpression, DeclarationDescriptor> VAL_REASSIGNMENT_VIA_BACKING_FIELD = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<KtExpression, DeclarationDescriptor> CAPTURED_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtExpression, DeclarationDescriptor> CAPTURED_MEMBER_VAL_INITIALIZATION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtExpression, DeclarationDescriptor> SETTER_PROJECTED_OUT = DiagnosticFactory1.create(ERROR);
@@ -843,6 +844,7 @@ public interface Errors {
DiagnosticFactory0<KtWhenCondition> EXPECTED_CONDITION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtWhenEntry> ELSE_MISPLACED_IN_WHEN = DiagnosticFactory0.create(ERROR, ELSE_ENTRY);
DiagnosticFactory0<KtWhenEntry> REDUNDANT_ELSE_IN_WHEN = DiagnosticFactory0.create(WARNING, ELSE_ENTRY);
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NO_ELSE_IN_WHEN = DiagnosticFactory1.create(ERROR, WHEN_EXPRESSION);
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NON_EXHAUSTIVE_WHEN = DiagnosticFactory1.create(WARNING, WHEN_EXPRESSION);
DiagnosticFactory0<PsiElement> COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT = DiagnosticFactory0.create(ERROR);
@@ -932,7 +934,7 @@ public interface Errors {
INVISIBLE_MEMBER, NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
ImmutableSet<? extends DiagnosticFactory<?>> UNUSED_ELEMENT_DIAGNOSTICS = ImmutableSet.of(
UNUSED_VARIABLE, UNUSED_PARAMETER, ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, VARIABLE_WITH_REDUNDANT_INITIALIZER,
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT);
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT, REDUNDANT_ELSE_IN_WHEN);
ImmutableSet<? extends DiagnosticFactory<?>> TYPE_INFERENCE_ERRORS = ImmutableSet.of(
TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS,
TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR,

View File

@@ -299,6 +299,7 @@ public class DefaultErrorMessages {
MAP.put(UNUSED_LAMBDA_EXPRESSION, "The lambda expression is unused. If you mean a block, you can use 'run { ... }'");
MAP.put(VAL_REASSIGNMENT, "Val cannot be reassigned", NAME);
MAP.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Val cannot be reassigned via backing field", NAME);
MAP.put(CAPTURED_VAL_INITIALIZATION, "Captured values initialization is forbidden due to possible reassignment", NAME);
MAP.put(CAPTURED_MEMBER_VAL_INITIALIZATION, "Captured member values initialization is forbidden due to possible reassignment", NAME);
MAP.put(SETTER_PROJECTED_OUT, "Setter for ''{0}'' is removed by type projection", NAME);
@@ -512,6 +513,7 @@ public class DefaultErrorMessages {
MAP.put(NULL_FOR_NONNULL_TYPE, "Null can not be a value of a non-null type {0}", RENDER_TYPE);
MAP.put(ELSE_MISPLACED_IN_WHEN, "'else' entry must be the last one in a when-expression");
MAP.put(REDUNDANT_ELSE_IN_WHEN, "'when' is exhaustive so 'else' is redundant here");
MAP.put(COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT, "Deprecated syntax. Use '||' instead of commas in when-condition for 'when' without argument");
MAP.put(DUPLICATE_LABEL_IN_WHEN, "Duplicate label in when");

View File

@@ -69,7 +69,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
%eof}
%xstate STRING RAW_STRING SHORT_TEMPLATE_ENTRY BLOCK_COMMENT DOC_COMMENT
%state LONG_TEMPLATE_ENTRY
%state LONG_TEMPLATE_ENTRY UNMATCHED_BACKTICK
DIGIT=[0-9]
DIGIT_OR_UNDERSCORE = [_0-9]
@@ -119,6 +119,7 @@ REGULAR_STRING_PART=[^\\\"\n\$]+
SHORT_TEMPLATE_ENTRY=\${IDENTIFIER}
LONELY_DOLLAR=\$
LONG_TEMPLATE_ENTRY_START=\$\{
LONELY_BACKTICK=`
%%
@@ -318,6 +319,8 @@ LONG_TEMPLATE_ENTRY_START=\$\{
"#" { return KtTokens.HASH ; }
"@" { return KtTokens.AT ; }
{LONELY_BACKTICK} { pushState(UNMATCHED_BACKTICK); return TokenType.BAD_CHARACTER; }
// error fallback
. { return TokenType.BAD_CHARACTER; }
// error fallback for exclusive states

View File

@@ -27,7 +27,7 @@ import com.intellij.util.containers.Stack;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.7.0-SNAPSHOT
* from the specification file <tt>/Users/endermz/projects/kotlin/compiler/frontend/src/org/jetbrains/kotlin/lexer/Kotlin.flex</tt>
* from the specification file <tt>/Users/yole/jetbrains/kotlin/compiler/frontend/src/org/jetbrains/kotlin/lexer/Kotlin.flex</tt>
*/
class _JetLexer implements FlexLexer {
@@ -45,6 +45,7 @@ class _JetLexer implements FlexLexer {
public static final int BLOCK_COMMENT = 8;
public static final int DOC_COMMENT = 10;
public static final int LONG_TEMPLATE_ENTRY = 12;
public static final int UNMATCHED_BACKTICK = 14;
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
@@ -53,7 +54,7 @@ class _JetLexer implements FlexLexer {
* l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 0, 0
};
/**
@@ -183,26 +184,26 @@ class _JetLexer implements FlexLexer {
private static final int [] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\6\0\1\1\1\2\1\3\1\4\2\1\1\5\1\6"+
"\1\7\1\2\1\10\1\11\1\12\1\13\1\14\3\3"+
"\1\15\1\16\14\3\1\17\1\20\1\21\1\22\1\23"+
"\2\1\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+
"\1\33\1\34\1\35\1\36\1\35\1\1\1\37\2\35"+
"\1\40\1\1\1\40\3\41\1\42\1\43\1\2\1\0"+
"\2\44\1\0\1\45\1\0\1\46\1\47\1\50\1\51"+
"\1\0\1\52\1\0\2\2\1\44\1\53\1\54\1\55"+
"\1\56\2\12\1\0\3\3\1\57\1\60\1\61\1\3"+
"\1\62\2\3\1\63\13\3\1\64\1\65\1\66\1\67"+
"\6\0\1\1\1\2\1\3\1\4\1\5\1\1\1\6"+
"\1\7\1\10\1\2\1\11\1\12\1\13\1\14\1\15"+
"\3\3\1\16\1\17\14\3\1\20\1\21\1\22\1\23"+
"\1\24\2\1\1\25\1\26\1\27\1\30\1\31\1\32"+
"\1\33\1\34\1\35\1\36\1\37\1\36\1\1\1\40"+
"\2\36\1\41\1\1\1\41\3\42\1\43\1\44\1\2"+
"\1\0\2\45\1\0\1\46\1\0\1\47\1\50\1\51"+
"\1\52\1\0\1\53\1\0\2\2\1\45\1\54\1\55"+
"\1\56\1\57\2\13\1\0\3\3\1\60\1\61\1\62"+
"\1\3\1\63\2\3\1\64\13\3\1\65\1\66\1\67"+
"\1\70\1\71\1\72\1\73\1\74\1\75\1\76\1\77"+
"\1\100\1\0\1\101\2\102\2\0\1\40\1\103\1\104"+
"\1\0\1\105\1\44\1\3\1\0\1\106\1\107\1\110"+
"\1\111\1\0\1\112\1\113\4\3\1\114\4\3\1\115"+
"\2\3\1\116\1\3\1\117\6\3\1\120\1\121\1\122"+
"\2\0\1\123\2\40\1\45\1\124\1\125\1\126\2\3"+
"\1\127\3\3\1\130\1\131\7\3\1\132\1\100\1\0"+
"\1\133\1\134\3\3\1\135\2\3\1\136\1\137\2\3"+
"\1\140\1\141\1\0\1\3\1\142\2\3\1\143\1\3"+
"\1\144\2\3\1\145\3\3\1\146\1\147\1\150";
"\1\100\1\101\1\0\1\102\2\103\2\0\1\41\1\104"+
"\1\105\1\0\1\106\1\45\1\3\1\0\1\107\1\110"+
"\1\111\1\112\1\0\1\113\1\114\4\3\1\115\4\3"+
"\1\116\2\3\1\117\1\3\1\120\6\3\1\121\1\122"+
"\1\123\2\0\1\124\2\41\1\46\1\125\1\126\1\127"+
"\2\3\1\130\3\3\1\131\1\132\7\3\1\133\1\101"+
"\1\0\1\134\1\135\3\3\1\136\2\3\1\137\1\140"+
"\2\3\1\141\1\142\1\0\1\3\1\143\2\3\1\144"+
"\1\3\1\145\2\3\1\146\3\3\1\147\1\150\1\151";
private static int [] zzUnpackAction() {
int [] result = new int[231];
@@ -646,7 +647,7 @@ class _JetLexer implements FlexLexer {
}
}
private final Stack<State> states = new Stack<>();
private final Stack<State> states = new Stack<State>();
private int lBraceCount;
private int commentStart;
@@ -954,140 +955,144 @@ class _JetLexer implements FlexLexer {
case 1:
{ return TokenType.BAD_CHARACTER;
}
case 105: break;
case 106: break;
case 2:
{ return KtTokens.INTEGER_LITERAL;
}
case 106: break;
case 107: break;
case 3:
{ return KtTokens.IDENTIFIER;
}
case 107: break;
case 108: break;
case 4:
{ return KtTokens.WHITE_SPACE;
}
case 108: break;
case 5:
{ return KtTokens.DIV ;
}
case 109: break;
case 6:
{ return KtTokens.HASH ;
case 5:
{ pushState(UNMATCHED_BACKTICK); return TokenType.BAD_CHARACTER;
}
case 110: break;
case 7:
{ return KtTokens.EXCL ;
case 6:
{ return KtTokens.DIV ;
}
case 111: break;
case 8:
{ return KtTokens.DOT ;
case 7:
{ return KtTokens.HASH ;
}
case 112: break;
case 9:
{ return KtTokens.MINUS ;
case 8:
{ return KtTokens.EXCL ;
}
case 113: break;
case 10:
{ return KtTokens.CHARACTER_LITERAL;
case 9:
{ return KtTokens.DOT ;
}
case 114: break;
case 11:
{ pushState(STRING); return KtTokens.OPEN_QUOTE;
case 10:
{ return KtTokens.MINUS ;
}
case 115: break;
case 12:
{ return KtTokens.LBRACE ;
case 11:
{ return KtTokens.CHARACTER_LITERAL;
}
case 116: break;
case 13:
{ return KtTokens.RBRACE ;
case 12:
{ pushState(STRING); return KtTokens.OPEN_QUOTE;
}
case 117: break;
case 14:
{ return KtTokens.MUL ;
case 13:
{ return KtTokens.LBRACE ;
}
case 118: break;
case 15:
{ return KtTokens.EQ ;
case 14:
{ return KtTokens.RBRACE ;
}
case 119: break;
case 16:
{ return KtTokens.QUEST ;
case 15:
{ return KtTokens.MUL ;
}
case 120: break;
case 17:
{ return KtTokens.PLUS ;
case 16:
{ return KtTokens.EQ ;
}
case 121: break;
case 18:
{ return KtTokens.LT ;
case 17:
{ return KtTokens.QUEST ;
}
case 122: break;
case 19:
{ return KtTokens.GT ;
case 18:
{ return KtTokens.PLUS ;
}
case 123: break;
case 20:
{ return KtTokens.PERC ;
case 19:
{ return KtTokens.LT ;
}
case 124: break;
case 21:
{ return KtTokens.COLON ;
case 20:
{ return KtTokens.GT ;
}
case 125: break;
case 22:
{ return KtTokens.LBRACKET ;
case 21:
{ return KtTokens.PERC ;
}
case 126: break;
case 23:
{ return KtTokens.RBRACKET ;
case 22:
{ return KtTokens.COLON ;
}
case 127: break;
case 24:
{ return KtTokens.LPAR ;
case 23:
{ return KtTokens.LBRACKET ;
}
case 128: break;
case 25:
{ return KtTokens.RPAR ;
case 24:
{ return KtTokens.RBRACKET ;
}
case 129: break;
case 26:
{ return KtTokens.SEMICOLON ;
case 25:
{ return KtTokens.LPAR ;
}
case 130: break;
case 27:
{ return KtTokens.COMMA ;
case 26:
{ return KtTokens.RPAR ;
}
case 131: break;
case 28:
{ return KtTokens.AT ;
case 27:
{ return KtTokens.SEMICOLON ;
}
case 132: break;
case 29:
{ return KtTokens.REGULAR_STRING_PART;
case 28:
{ return KtTokens.COMMA ;
}
case 133: break;
case 30:
{ popState(); yypushback(1); return KtTokens.DANGLING_NEWLINE;
case 29:
{ return KtTokens.AT ;
}
case 134: break;
case 31:
{ popState(); return KtTokens.CLOSING_QUOTE;
case 30:
{ return KtTokens.REGULAR_STRING_PART;
}
case 135: break;
case 32:
{ popState(); return KtTokens.IDENTIFIER;
case 31:
{ popState(); yypushback(1); return KtTokens.DANGLING_NEWLINE;
}
case 136: break;
case 33:
{
case 32:
{ popState(); return KtTokens.CLOSING_QUOTE;
}
case 137: break;
case 34:
{ lBraceCount++; return KtTokens.LBRACE;
case 33:
{ popState(); return KtTokens.IDENTIFIER;
}
case 138: break;
case 34:
{
}
case 139: break;
case 35:
{ lBraceCount++; return KtTokens.LBRACE;
}
case 140: break;
case 36:
{ if (lBraceCount == 0) {
popState();
return KtTokens.LONG_TEMPLATE_ENTRY_END;
@@ -1095,30 +1100,30 @@ class _JetLexer implements FlexLexer {
lBraceCount--;
return KtTokens.RBRACE;
}
case 139: break;
case 36:
case 141: break;
case 37:
{ return KtTokens.FLOAT_LITERAL;
}
case 140: break;
case 37:
case 142: break;
case 38:
{ return KtTokens.FIELD_IDENTIFIER;
}
case 141: break;
case 38:
case 143: break;
case 39:
{ return KtTokens.EOL_COMMENT;
}
case 142: break;
case 39:
case 144: break;
case 40:
{ pushState(BLOCK_COMMENT);
commentDepth = 0;
commentStart = getTokenStart();
}
case 143: break;
case 40:
case 145: break;
case 41:
{ return KtTokens.DIVEQ ;
}
case 144: break;
case 41:
case 146: break;
case 42:
{ if (zzCurrentPos == 0) {
return KtTokens.SHEBANG_COMMENT;
}
@@ -1127,114 +1132,114 @@ class _JetLexer implements FlexLexer {
return KtTokens.HASH;
}
}
case 145: break;
case 42:
case 147: break;
case 43:
{ return KtTokens.EXCLEQ ;
}
case 146: break;
case 43:
case 148: break;
case 44:
{ return KtTokens.RANGE ;
}
case 147: break;
case 44:
case 149: break;
case 45:
{ return KtTokens.MINUSMINUS;
}
case 148: break;
case 45:
case 150: break;
case 46:
{ return KtTokens.MINUSEQ ;
}
case 149: break;
case 46:
case 151: break;
case 47:
{ return KtTokens.ARROW ;
}
case 150: break;
case 47:
case 152: break;
case 48:
{ return KtTokens.IS_KEYWORD ;
}
case 151: break;
case 48:
case 153: break;
case 49:
{ return KtTokens.IN_KEYWORD ;
}
case 152: break;
case 49:
case 154: break;
case 50:
{ return KtTokens.IF_KEYWORD ;
}
case 153: break;
case 50:
case 155: break;
case 51:
{ return KtTokens.MULTEQ ;
}
case 154: break;
case 51:
case 156: break;
case 52:
{ return KtTokens.AS_KEYWORD ;
}
case 155: break;
case 52:
case 157: break;
case 53:
{ return KtTokens.DO_KEYWORD ;
}
case 156: break;
case 53:
case 158: break;
case 54:
{ return KtTokens.EQEQ ;
}
case 157: break;
case 54:
case 159: break;
case 55:
{ return KtTokens.DOUBLE_ARROW;
}
case 158: break;
case 55:
case 160: break;
case 56:
{ return KtTokens.PLUSEQ ;
}
case 159: break;
case 56:
case 161: break;
case 57:
{ return KtTokens.PLUSPLUS ;
}
case 160: break;
case 57:
case 162: break;
case 58:
{ return KtTokens.LTEQ ;
}
case 161: break;
case 58:
case 163: break;
case 59:
{ return KtTokens.GTEQ ;
}
case 162: break;
case 59:
case 164: break;
case 60:
{ return KtTokens.ANDAND ;
}
case 163: break;
case 60:
case 165: break;
case 61:
{ return KtTokens.OROR ;
}
case 164: break;
case 61:
case 166: break;
case 62:
{ return KtTokens.PERCEQ ;
}
case 165: break;
case 62:
case 167: break;
case 63:
{ return KtTokens.COLONCOLON;
}
case 166: break;
case 63:
case 168: break;
case 64:
{ return KtTokens.DOUBLE_SEMICOLON;
}
case 167: break;
case 64:
case 169: break;
case 65:
{ pushState(SHORT_TEMPLATE_ENTRY);
yypushback(yylength() - 1);
return KtTokens.SHORT_TEMPLATE_ENTRY_START;
}
case 168: break;
case 65:
case 170: break;
case 66:
{ pushState(LONG_TEMPLATE_ENTRY); return KtTokens.LONG_TEMPLATE_ENTRY_START;
}
case 169: break;
case 66:
case 171: break;
case 67:
{ return KtTokens.ESCAPE_SEQUENCE;
}
case 170: break;
case 67:
case 172: break;
case 68:
{ commentDepth++;
}
case 171: break;
case 68:
case 173: break;
case 69:
{ if (commentDepth > 0) {
commentDepth--;
}
@@ -1245,66 +1250,66 @@ class _JetLexer implements FlexLexer {
return commentStateToTokenType(state);
}
}
case 172: break;
case 69:
case 174: break;
case 70:
{ yypushback(2); return KtTokens.INTEGER_LITERAL;
}
case 173: break;
case 70:
case 175: break;
case 71:
{ pushState(DOC_COMMENT);
commentDepth = 0;
commentStart = getTokenStart();
}
case 174: break;
case 71:
case 176: break;
case 72:
{ return KtTokens.NOT_IS;
}
case 175: break;
case 72:
case 177: break;
case 73:
{ return KtTokens.NOT_IN;
}
case 176: break;
case 73:
case 178: break;
case 74:
{ return KtTokens.EXCLEQEQEQ;
}
case 177: break;
case 74:
case 179: break;
case 75:
{ return KtTokens.RESERVED ;
}
case 178: break;
case 75:
case 180: break;
case 76:
{ pushState(RAW_STRING); return KtTokens.OPEN_QUOTE;
}
case 179: break;
case 76:
case 181: break;
case 77:
{ return KtTokens.TRY_KEYWORD ;
}
case 180: break;
case 77:
case 182: break;
case 78:
{ return KtTokens.AS_SAFE;
}
case 181: break;
case 78:
case 183: break;
case 79:
{ return KtTokens.FUN_KEYWORD ;
}
case 182: break;
case 79:
case 184: break;
case 80:
{ return KtTokens.FOR_KEYWORD ;
}
case 183: break;
case 80:
case 185: break;
case 81:
{ return KtTokens.VAL_KEYWORD ;
}
case 184: break;
case 81:
case 186: break;
case 82:
{ return KtTokens.VAR_KEYWORD ;
}
case 185: break;
case 82:
case 187: break;
case 83:
{ return KtTokens.EQEQEQ ;
}
case 186: break;
case 83:
case 188: break;
case 84:
{ int length = yytext().length();
if (length <= 3) { // closing """
popState();
@@ -1315,91 +1320,91 @@ class _JetLexer implements FlexLexer {
return KtTokens.REGULAR_STRING_PART;
}
}
case 187: break;
case 84:
case 189: break;
case 85:
{ return KtTokens.BLOCK_COMMENT;
}
case 188: break;
case 85:
case 190: break;
case 86:
{ yypushback(3); return KtTokens.EXCL;
}
case 189: break;
case 86:
case 191: break;
case 87:
{ return KtTokens.THIS_KEYWORD ;
}
case 190: break;
case 87:
case 192: break;
case 88:
{ return KtTokens.TRUE_KEYWORD ;
}
case 191: break;
case 88:
case 193: break;
case 89:
{ return KtTokens.ELSE_KEYWORD ;
}
case 192: break;
case 89:
case 194: break;
case 90:
{ return KtTokens.NULL_KEYWORD ;
}
case 193: break;
case 90:
case 195: break;
case 91:
{ return KtTokens.WHEN_KEYWORD ;
}
case 194: break;
case 91:
case 196: break;
case 92:
{ popState(); return KtTokens.THIS_KEYWORD;
}
case 195: break;
case 92:
case 197: break;
case 93:
{ return KtTokens.THROW_KEYWORD ;
}
case 196: break;
case 93:
case 198: break;
case 94:
{ return KtTokens.SUPER_KEYWORD ;
}
case 197: break;
case 94:
case 199: break;
case 95:
{ return KtTokens.FALSE_KEYWORD ;
}
case 198: break;
case 95:
case 200: break;
case 96:
{ return KtTokens.CLASS_KEYWORD ;
}
case 199: break;
case 96:
case 201: break;
case 97:
{ return KtTokens.BREAK_KEYWORD ;
}
case 200: break;
case 97:
case 202: break;
case 98:
{ return KtTokens.WHILE_KEYWORD ;
}
case 201: break;
case 98:
case 203: break;
case 99:
{ return KtTokens.TYPEOF_KEYWORD ;
}
case 202: break;
case 99:
case 204: break;
case 100:
{ return KtTokens.RETURN_KEYWORD ;
}
case 203: break;
case 100:
case 205: break;
case 101:
{ return KtTokens.OBJECT_KEYWORD ;
}
case 204: break;
case 101:
case 206: break;
case 102:
{ return KtTokens.PACKAGE_KEYWORD ;
}
case 205: break;
case 102:
case 207: break;
case 103:
{ return KtTokens.CONTINUE_KEYWORD ;
}
case 206: break;
case 103:
case 208: break;
case 104:
{ return KtTokens.TYPE_ALIAS_KEYWORD ;
}
case 207: break;
case 104:
case 209: break;
case 105:
{ return KtTokens.INTERFACE_KEYWORD ;
}
case 208: break;
case 210: break;
default:
zzScanError(ZZ_NO_MATCH);
}

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.
@@ -136,6 +136,7 @@ private val MODIFIERS_TO_REPLACE = mapOf(
private val MODIFIERS_ORDER = listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD,
FINAL_KEYWORD, OPEN_KEYWORD, ABSTRACT_KEYWORD,
OVERRIDE_KEYWORD,
LATEINIT_KEYWORD,
SUSPEND_KEYWORD,
INNER_KEYWORD,
ENUM_KEYWORD, COMPANION_KEYWORD, INFIX_KEYWORD, OPERATOR_KEYWORD, DATA_KEYWORD)

View File

@@ -23,12 +23,12 @@ object KotlinStubVersions {
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
// if you are not 100% sure it can be avoided.
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
const val SOURCE_STUB_VERSION = 121
const val SOURCE_STUB_VERSION = 123
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
private const val BINARY_STUB_VERSION = 58
private const val BINARY_STUB_VERSION = 60
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
// Increasing this version will lead to reindexing of all classfiles.

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi.stubs.elements;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
@@ -63,4 +64,9 @@ public class KtParameterElementType extends KtStubElementType<KotlinParameterStu
return new KotlinParameterStubImpl(parentStub, fqName, name, isMutable, hasValOrValNode, hasDefaultValue);
}
@Override
public void indexStub(@NotNull KotlinParameterStub stub, @NotNull IndexSink sink) {
StubIndexService.getInstance().indexParameter(stub, sink);
}
}

View File

@@ -87,12 +87,9 @@ public abstract class KtStubElementType<StubT extends StubElement, PsiT extends
@Override
public boolean shouldCreateStub(ASTNode node) {
PsiElement psi = node.getPsi();
if (psi instanceof KtClassOrObject) {
if (psi instanceof KtClassOrObject || psi instanceof KtFunction) {
return true;
}
if (psi instanceof KtFunction) {
return !((KtFunction) psi).isLocal();
}
if (psi instanceof KtProperty) {
return !((KtProperty) psi).isLocal();
}

View File

@@ -44,6 +44,9 @@ open class StubIndexService protected constructor() {
open fun indexProperty(stub: KotlinPropertyStub, sink: IndexSink) {
}
open fun indexParameter(stub: KotlinParameterStub, sink: IndexSink) {
}
open fun indexAnnotation(stub: KotlinAnnotationEntryStub, sink: IndexSink) {
}

View File

@@ -56,6 +56,7 @@ import java.util.*;
import static org.jetbrains.kotlin.config.LanguageFeature.TopLevelSealedInheritance;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.isEffectivelyExternal;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class BodyResolver {
@@ -165,7 +166,7 @@ public class BodyResolver {
@NotNull KtSecondaryConstructor constructor,
@NotNull ClassConstructorDescriptor descriptor
) {
if (descriptor.isHeader() || DescriptorUtils.isEffectivelyExternal(descriptor)) {
if (descriptor.isHeader() || isEffectivelyExternal(descriptor)) {
// For header and external classes, we do not resolve constructor delegation calls because they are prohibited
return DataFlowInfo.Companion.getEMPTY();
}
@@ -366,7 +367,7 @@ public class BodyResolver {
descriptor.getUnsubstitutedPrimaryConstructor() != null &&
superClass.getKind() != ClassKind.INTERFACE &&
!superClass.getConstructors().isEmpty() &&
!descriptor.isHeader() && !DescriptorUtils.isEffectivelyExternal(descriptor) &&
!descriptor.isHeader() && !isEffectivelyExternal(descriptor) &&
!ErrorUtils.isError(superClass)
) {
trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));

View File

@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@@ -697,7 +698,7 @@ class DeclarationsChecker(
}
else {
val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false
val isExternal = DescriptorUtils.isEffectivelyExternal(propertyDescriptor)
val isExternal = propertyDescriptor.isEffectivelyExternal()
if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit && !isHeader && isUninitialized && !isExternal) {
if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) {
trace.report(MUST_BE_INITIALIZED.on(property))
@@ -737,7 +738,7 @@ class DeclarationsChecker(
val containingDescriptor = functionDescriptor.containingDeclaration
val hasAbstractModifier = function.hasModifier(KtTokens.ABSTRACT_KEYWORD)
val hasExternalModifier = DescriptorUtils.isEffectivelyExternal(functionDescriptor)
val hasExternalModifier = functionDescriptor.isEffectivelyExternal()
if (containingDescriptor is ClassDescriptor) {
val inInterface = containingDescriptor.kind == ClassKind.INTERFACE

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.createDeprecationDiagnostic
import org.jetbrains.kotlin.resolve.getDeprecations
@@ -30,6 +31,7 @@ class DeprecatedClassifierUsageChecker : ClassifierUsageChecker {
element: PsiElement,
languageVersionSettings: LanguageVersionSettings
) {
if (element.parent is KtThisExpression) return
for (deprecation in targetDescriptor.getDeprecations(languageVersionSettings)) {
trace.report(createDeprecationDiagnostic(element, deprecation, languageVersionSettings))
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 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.
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
import org.jetbrains.kotlin.resolve.LocalVariableResolver
import org.jetbrains.kotlin.resolve.TypeResolver
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -84,8 +85,9 @@ class DestructuringDeclarationResolver(
if (receiver == null) return errorType()
val expectedType = getExpectedTypeForComponent(context, entry)
val newContext = context.replaceExpectedType(expectedType).replaceContextDependency(ContextDependency.INDEPENDENT)
val results = fakeCallResolver.resolveFakeCall(
context.replaceExpectedType(expectedType), receiver, componentName,
newContext, receiver, componentName,
entry, initializer ?: entry, FakeCallKind.COMPONENT, emptyList()
)

View File

@@ -16,7 +16,8 @@
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.build.GeneratedJvmClass
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
@@ -31,26 +32,36 @@ class GradleIncrementalCacheImpl(
private val reporter: ICReporter
) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
companion object {
private val SOURCES_TO_CLASSFILES = "sources-to-classfiles"
private val GENERATED_SOURCE_SNAPSHOTS = "generated-source-snapshot"
private val SOURCE_TO_OUTPUT_FILES = "source-to-output"
private val SOURCE_SNAPSHOTS = "source-snapshot"
}
internal val sourceToClassfilesMap = registerMap(SourceToClassfilesMap(SOURCES_TO_CLASSFILES.storageFile))
internal val generatedSourceSnapshotMap = registerMap(FileSnapshotMap(GENERATED_SOURCE_SNAPSHOTS.storageFile))
internal val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile))
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile))
fun removeClassfilesBySources(sources: Iterable<File>): Unit =
sources.forEach { sourceToClassfilesMap.remove(it) }
// generatedFiles can contain multiple entries with the same source file
// for example Kapt3 IC will generate a .java stub and .class stub for each source file
fun registerOutputForSourceFiles(generatedFiles: List<GeneratedFile<*>>) {
val sourceToOutput = MultiMap<File, File>()
override fun saveFileToCache(generatedClass: GeneratedJvmClass<TargetId>): CompilationResult {
generatedClass.sourceFiles.forEach { sourceToClassfilesMap.add(it, generatedClass.outputFile) }
return super.saveFileToCache(generatedClass)
for (generatedFile in generatedFiles) {
for (source in generatedFile.sourceFiles) {
sourceToOutput.putValue(source, generatedFile.outputFile)
}
}
for ((source, outputs) in sourceToOutput.entrySet()) {
sourceToOutputMap[source] = outputs
}
}
inner class SourceToClassfilesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
fun add(sourceFile: File, classFile: File) {
storage.append(sourceFile.absolutePath, classFile.absolutePath)
fun removeOutputForSourceFiles(sources: Iterable<File>) {
sources.forEach { sourceToOutputMap.remove(it) }
}
inner class SourceToOutputFilesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
storage[sourceFile.absolutePath] = outputFiles.map { it.absolutePath }
}
operator fun get(sourceFile: File): Collection<File> =

View File

@@ -267,7 +267,7 @@ class IncrementalJvmCompilerRunner(
when (compilationMode) {
is CompilationMode.Incremental -> {
dirtySources = ArrayList(compilationMode.dirtyFiles)
args.classpathAsList += args.destinationAsFile
args.classpathAsList += args.destinationAsFile.apply { mkdirs() }
}
is CompilationMode.Rebuild -> {
dirtySources = allKotlinSources.toMutableList()
@@ -288,7 +288,7 @@ class IncrementalJvmCompilerRunner(
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
val outdatedClasses = caches.incrementalCache.classesBySources(dirtySources)
caches.incrementalCache.markOutputClassesDirty(dirtySources)
caches.incrementalCache.removeClassfilesBySources(dirtySources)
caches.incrementalCache.removeOutputForSourceFiles(dirtySources)
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
@@ -300,8 +300,8 @@ class IncrementalJvmCompilerRunner(
val compilerOutput = compileChanged(listOf(targetId), sourcesToCompile.toSet(), args, { caches.incrementalCache }, lookupTracker, messageCollector)
exitCode = compilerOutput.exitCode
val generatedClassFiles = compilerOutput.generatedFiles
anyClassesCompiled = anyClassesCompiled || generatedClassFiles.isNotEmpty() || removedKotlinSources.isNotEmpty()
val generatedFiles = compilerOutput.generatedFiles
anyClassesCompiled = anyClassesCompiled || generatedFiles.isNotEmpty() || removedKotlinSources.isNotEmpty()
if (exitCode == ExitCode.OK) {
dirtySourcesSinceLastTimeFile.delete()
@@ -313,15 +313,16 @@ class IncrementalJvmCompilerRunner(
if (compilationMode is CompilationMode.Incremental) {
val dirtySourcesSet = dirtySources.toHashSet()
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedClassFiles).filter { it !in dirtySourcesSet }
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedFiles).filter { it !in dirtySourcesSet }
if (additionalDirtyFiles.isNotEmpty()) {
dirtySources.addAll(additionalDirtyFiles)
continue
}
}
allGeneratedFiles.addAll(generatedClassFiles)
val compilationResult = updateIncrementalCaches(listOf(targetId), generatedClassFiles,
allGeneratedFiles.addAll(generatedFiles)
caches.incrementalCache.registerOutputForSourceFiles(generatedFiles)
val compilationResult = updateIncrementalCaches(listOf(targetId), generatedFiles,
compiledWithErrors = exitCode != ExitCode.OK,
getIncrementalCache = { caches.incrementalCache })

View File

@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.config.IncrementalCompilation
import java.io.File
internal const val STANDALONE_CACHE_VERSION = 0
internal const val STANDALONE_CACHE_VERSION = 1
internal const val STANDALONE_VERSION_FILE_NAME = "standalone-ic-format-version.txt"
fun standaloneCacheVersion(dataRoot: File): CacheVersion =

View File

@@ -69,7 +69,7 @@ abstract class LightClassGenerationSupport {
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
abstract fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>

View File

@@ -247,3 +247,11 @@ object LightClassUtil {
override fun iterator(): Iterator<PsiMethod> = allMethods.iterator()
}
}
fun KtNamedDeclaration.getAccessorLightMethods(): LightClassUtil.PropertyAccessorsPsiMethods {
return when (this) {
is KtProperty -> LightClassUtil.getLightClassPropertyMethods(this)
is KtParameter -> LightClassUtil.getLightClassPropertyMethods(this)
else -> throw IllegalStateException("Unexpected property type: ${this}")
}
}

View File

@@ -44,8 +44,8 @@ import org.jetbrains.kotlin.asJava.builder.LightClassData
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightSimpleModifierList
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -180,7 +180,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
override fun getName(): String? = classOrObject.nameAsName?.asString()
private val _modifierList: PsiModifierList by lazyPub { KtLightSimpleModifierList(this@KtLightClassForSourceDeclaration, computeModifiers()) }
private val _modifierList: PsiModifierList by lazyPub { KtLightClassModifierList(this) }
override fun getModifierList(): PsiModifierList? = _modifierList
@@ -390,7 +390,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
val fqName = FqNameUnsafe(qualifiedName)
val mappedQName =
if (fqName.isSafe)
JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName.toSafe())?.asSingleFqName()?.asString()
JavaToKotlinClassMap.mapJavaToKotlin(fqName.toSafe())?.asSingleFqName()?.asString()
else null
if (qualifiedName == mappedQName) return true
@@ -452,8 +452,28 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
override val originKind: LightClassOriginKind
get() = LightClassOriginKind.SOURCE
private class KtLightClassModifierList(containingClass: KtLightClassForSourceDeclaration)
: KtLightModifierList<KtLightClassForSourceDeclaration>(containingClass) {
private val modifiers by lazyPub { containingClass.computeModifiers() }
override fun hasModifierProperty(name: String): Boolean {
if (name != PsiModifier.FINAL) {
return name in modifiers
}
val isFinalByPsi = PsiModifier.FINAL in modifiers
// annotations can make class open via 'allopen' plugin
if (!owner.isPossiblyAffectedByAllOpen() || !isFinalByPsi) return isFinalByPsi
return clsDelegate.hasModifierProperty(PsiModifier.FINAL)
}
}
}
fun KtLightClassForSourceDeclaration.isPossiblyAffectedByAllOpen() = !isAnnotationType && !isInterface && kotlinOrigin.annotationEntries.isNotEmpty()
fun getOutermostClassOrObject(classOrObject: KtClassOrObject): KtClassOrObject {
val outermostClass = KtPsiUtil.getOutermostClassOrObject(classOrObject) ?:
throw IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.text)
@@ -487,4 +507,4 @@ fun KtClassOrObject.defaultJavaAncestorQualifiedName(): String? {
isInterface() -> CommonClassNames.JAVA_LANG_OBJECT // see com.intellij.psi.impl.PsiClassImplUtil.getSuperClass
else -> CommonClassNames.JAVA_LANG_OBJECT
}
}
}

View File

@@ -16,5 +16,12 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.impl.light.LightElement
import com.intellij.util.IncorrectOperationException
// NOTE: avoid using blocking lazy in light classes, it leads to deadlocks
fun <T> lazyPub(initializer: () -> T) = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
fun <T> lazyPub(initializer: () -> T) = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
fun LightElement.cannotModify(): Nothing {
throw IncorrectOperationException("Modification not implemented.")
}

View File

@@ -18,13 +18,12 @@ package org.jetbrains.kotlin.asJava.elements
import com.intellij.psi.*
import com.intellij.psi.impl.PsiVariableEx
import com.intellij.util.IncorrectOperationException
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForEnumEntry
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.KtNamedDeclaration
@@ -41,8 +40,7 @@ sealed class KtLightFieldImpl<D : PsiField>(
@Suppress("UNCHECKED_CAST")
get() = super.clsDelegate as D
@Throws(IncorrectOperationException::class)
override fun setInitializer(initializer: PsiExpression?) = throw IncorrectOperationException("Not supported")
override fun setInitializer(initializer: PsiExpression?) = cannotModify()
override fun getType() = clsDelegate.type
@@ -52,8 +50,7 @@ sealed class KtLightFieldImpl<D : PsiField>(
override fun hasInitializer() = clsDelegate.hasInitializer()
@Throws(IncorrectOperationException::class)
override fun normalizeDeclaration() = throw IncorrectOperationException("Not supported")
override fun normalizeDeclaration() = cannotModify()
override fun computeConstantValue() = clsDelegate.computeConstantValue()

View File

@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.asJava.builder.LightElementOrigin
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.classes.isPossiblyAffectedByAllOpen
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -79,7 +81,10 @@ private class KtLightMemberModifierList(
) : KtLightModifierList<KtLightMember<*>>(owner) {
override fun hasModifierProperty(name: String) = when {
name == PsiModifier.ABSTRACT && isImplementationInInterface() -> false
// pretend this method behaves like a default method
name == PsiModifier.DEFAULT && isImplementationInInterface() -> true
name == PsiModifier.FINAL && ((owner.containingClass as? KtLightClassForSourceDeclaration)?.isPossiblyAffectedByAllOpen() ?: false) ->
clsDelegate.hasModifierProperty(name)
dummyDelegate != null -> {
when {
name in visibilityModifiers && isMethodOverride() ->
@@ -90,6 +95,10 @@ private class KtLightMemberModifierList(
else -> clsDelegate.hasModifierProperty(name)
}
override fun hasExplicitModifier(name: String) =
// kotlin methods can't be truly default atm, that way we can avoid being reported on by diagnostics, namely android lint
if (name == PsiModifier.DEFAULT) false else super.hasExplicitModifier(name)
private fun isMethodOverride() = owner is KtLightMethod && owner.kotlinOrigin?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false
private fun isImplementationInInterface()

View File

@@ -20,10 +20,13 @@ import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.scope.PsiScopeProcessor
import com.intellij.psi.util.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.builder.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.builder.MemberIndex
import org.jetbrains.kotlin.asJava.builder.memberIndex
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.propertyNameByAccessor
import org.jetbrains.kotlin.asJava.unwrapped
@@ -93,7 +96,7 @@ class KtLightMethodImpl private constructor(
nameExpression.replace(KtPsiFactory(this).createStringTemplate(name))
}
else {
val toRename = kotlinOrigin as? PsiNamedElement ?: throwCanNotModify()
val toRename = kotlinOrigin as? PsiNamedElement ?: cannotModify()
toRename.setName(newNameForOrigin)
}
return this
@@ -104,12 +107,9 @@ class KtLightMethodImpl private constructor(
if (it.isValid) {
it.delete()
}
} ?: throwCanNotModify()
} ?: cannotModify()
}
// TODO: add message
private fun throwCanNotModify(): Nothing = throw IncorrectOperationException()
override fun getModifierList(): PsiModifierList {
if (calculatingReturnType.get() == true) {
return KotlinJavaPsiFacade.getInstance(project).emptyModifierList

View File

@@ -22,6 +22,7 @@ import com.intellij.psi.*
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.*
@@ -187,8 +188,7 @@ class KtLightAnnotationForSourceEntry(
override fun hashCode() = kotlinOrigin.hashCode()
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?): T
= clsDelegate.setDeclaredAttributeValue(attributeName, value)
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify()
}
class KtLightNonSourceAnnotation(
@@ -196,8 +196,7 @@ class KtLightNonSourceAnnotation(
): KtLightAbstractAnnotation(parent, { clsDelegate }) {
override val kotlinOrigin: KtAnnotationEntry? get() = null
override fun getQualifiedName() = clsDelegate.qualifiedName
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?)
= clsDelegate.setDeclaredAttributeValue(attributeName, value)
override fun <T : PsiAnnotationMemberValue?> setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify()
override fun findAttributeValue(attributeName: String?) = clsDelegate.findAttributeValue(attributeName)
override fun findDeclaredAttributeValue(attributeName: String?) = clsDelegate.findDeclaredAttributeValue(attributeName)
}
@@ -244,8 +243,6 @@ class KtLightNullabilityAnnotation(member: KtLightElement<*, PsiModifierListOwne
override fun findDeclaredAttributeValue(attributeName: String?) = null
}
private fun cannotModify(): Nothing = error("Cannot modify") // TODO: meaningful message?
internal fun isNullabilityAnnotation(qualifiedName: String?) = qualifiedName in backendNullabilityAnnotations
private val backendNullabilityAnnotations = arrayOf(Nullable::class.java.name, NotNull::class.java.name)

View File

@@ -92,7 +92,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
findClassesAndObjects(qualifiedName, scope, answer);
answer.addAll(lightClassGenerationSupport.getFacadeClasses(qualifiedName, scope));
answer.addAll(lightClassGenerationSupport.getMultifilePartClasses(qualifiedName, scope));
answer.addAll(lightClassGenerationSupport.getKotlinInternalClasses(qualifiedName, scope));
return sortByClasspath(answer, scope).toArray(new PsiClass[answer.size()]);
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.asJava
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry

View File

@@ -64,15 +64,23 @@ internal class ExplicitReceiverScopeTowerProcessor<C: Candidate>(
}
private fun resolveAsMember(): Collection<C> {
val members =
MemberScopeTowerLevel(scopeTower, explicitReceiver)
.collectCandidates(null).filter { !it.requiresExtensionReceiver }
return members.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) }
val members = mutableListOf<C>()
for (memberCandidate in MemberScopeTowerLevel(scopeTower, explicitReceiver).collectCandidates(null)) {
if (!memberCandidate.requiresExtensionReceiver) {
members.add(candidateFactory.createCandidate(memberCandidate, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null))
}
}
return members
}
private fun resolveAsExtension(level: ScopeTowerLevel): Collection<C> {
val extensions = level.collectCandidates(explicitReceiver).filter { it.requiresExtensionReceiver }
return extensions.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver) }
val extensions = mutableListOf<C>()
for (extensionCandidate in level.collectCandidates(explicitReceiver)) {
if (extensionCandidate.requiresExtensionReceiver) {
extensions.add(candidateFactory.createCandidate(extensionCandidate, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver))
}
}
return extensions
}
}
@@ -85,9 +93,12 @@ private class QualifierScopeTowerProcessor<C: Candidate>(
override fun simpleProcess(data: TowerData): Collection<C> {
if (data != TowerData.Empty) return emptyList()
val staticMembers = QualifierScopeTowerLevel(scopeTower, qualifier).collectCandidates(null)
.filter { !it.requiresExtensionReceiver }
.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
val staticMembers = mutableListOf<C>()
for (towerCandidate in QualifierScopeTowerLevel(scopeTower, qualifier).collectCandidates(null)) {
if (!towerCandidate.requiresExtensionReceiver) {
staticMembers.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null))
}
}
return staticMembers
}
}
@@ -99,19 +110,21 @@ private class NoExplicitReceiverScopeTowerProcessor<C: Candidate>(
override fun simpleProcess(data: TowerData): Collection<C>
= when(data) {
is TowerData.TowerLevel -> {
data.level.collectCandidates(null).filter { !it.requiresExtensionReceiver }.map {
candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null)
val result = mutableListOf<C>()
for (towerCandidate in data.level.collectCandidates(null)) {
if (!towerCandidate.requiresExtensionReceiver) {
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null))
}
}
result
}
is TowerData.BothTowerLevelAndImplicitReceiver -> {
val result = mutableListOf<C>()
data.level.collectCandidates(data.implicitReceiver).filter { it.requiresExtensionReceiver }.forEach {
result.add(
candidateFactory.createCandidate(
it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver))
for (towerCandidate in data.level.collectCandidates(data.implicitReceiver)) {
if (towerCandidate.requiresExtensionReceiver) {
result.add(candidateFactory.createCandidate(towerCandidate, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver))
}
}
result
}
else -> emptyList()

View File

@@ -0,0 +1,25 @@
@test.AllOpen
public class C {
private final int p;
public void f() { /* compiled code */ }
public void g() { /* compiled code */ }
public int getP() { /* compiled code */ }
public C() { /* compiled code */ }
public static final class D {
public final void z() { /* compiled code */ }
public D() { /* compiled code */ }
}
@test.AllOpen
public static class H {
public void j() { /* compiled code */ }
public H() { /* compiled code */ }
}
}

View File

@@ -0,0 +1,26 @@
// test.C
package test
annotation class AllOpen
@AllOpen
class C {
fun f() {}
fun g() {}
val p: Int
class D {
fun z() {
}
}
@AllOpen
class H {
fun j() {}
}
}
// LAZINESS:NoLaziness

View File

@@ -0,0 +1,38 @@
public final class Container {
public Container() { /* compiled code */ }
public static final class MyString implements java.lang.CharSequence {
public int getLength() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public error.NonExistentClass chars() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public error.NonExistentClass codePoints() { /* compiled code */ }
public char get(int index) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public java.lang.CharSequence subSequence(int startIndex, int endIndex) { /* compiled code */ }
public MyString() { /* compiled code */ }
}
public static final class MyNumber extends java.lang.Number {
public byte toByte() { /* compiled code */ }
public char toChar() { /* compiled code */ }
public double toDouble() { /* compiled code */ }
public float toFloat() { /* compiled code */ }
public int toInt() { /* compiled code */ }
public long toLong() { /* compiled code */ }
public short toShort() { /* compiled code */ }
public MyNumber() { /* compiled code */ }
}
}

View File

@@ -0,0 +1,47 @@
// p1.Container
package p1
class Container {
class MyString : CharSequence {
override val length: Int
get() = 0
override fun chars(): IntStream = error("")
override fun codePoints(): IntStream = error("")
override fun get(index: Int): Char = 'c'
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = MyString()
}
class MyNumber : Number {
override fun toByte(): Byte {
TODO("not implemented")
}
override fun toChar(): Char {
TODO("not implemented")
}
override fun toDouble(): Double {
TODO("not implemented")
}
override fun toFloat(): Float {
TODO("not implemented")
}
override fun toInt(): Int {
TODO("not implemented")
}
override fun toLong(): Long {
TODO("not implemented")
}
override fun toShort(): Short {
TODO("not implemented")
}
}
}

View File

@@ -0,0 +1,5 @@
public final class TypeHierarchyMap <TValue> implements java.util.Map<java.lang.Class<?>,TValue>, kotlin.collections.Map<java.lang.Class<?>,TValue>, kotlin.jvm.internal.markers.KMappedMarker {
public boolean containsKey(@org.jetbrains.annotations.NotNull java.lang.Class key) { /* compiled code */ }
public TypeHierarchyMap() { /* compiled code */ }
}

View File

@@ -0,0 +1,8 @@
// p1.TypeHierarchyMap
package p1
class TypeHierarchyMap<TValue> : Map<Class<*>, TValue> {
override fun containsKey(key: Class<*>): Boolean {
TODO("not implemented")
}
}

View File

@@ -0,0 +1,43 @@
public final class SmartSet <T> extends kotlin.collections.AbstractSet<T> implements java.util.Set<T>, kotlin.collections.MutableSet<T>, kotlin.jvm.internal.markers.KMutableSet {
private java.lang.Object data;
private int size;
private static final int ARRAY_THRESHOLD = 5;
public static final SmartSet.Companion Companion;
public int getSize() { /* compiled code */ }
public void setSize(int i) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public java.util.Iterator<T> iterator() { /* compiled code */ }
public boolean add(T element) { /* compiled code */ }
public void clear() { /* compiled code */ }
public boolean contains(java.lang.Object element) { /* compiled code */ }
private SmartSet() { /* compiled code */ }
@kotlin.jvm.JvmStatic
@org.jetbrains.annotations.NotNull
public static final <T> SmartSet<T> create() { /* compiled code */ }
@kotlin.jvm.JvmStatic
@org.jetbrains.annotations.NotNull
public static final <T> SmartSet<T> create(@org.jetbrains.annotations.NotNull java.util.Collection<? extends T> set) { /* compiled code */ }
public static final class Companion {
private final int getARRAY_THRESHOLD() { /* compiled code */ }
@kotlin.jvm.JvmStatic
@org.jetbrains.annotations.NotNull
public final <T> SmartSet<T> create() { /* compiled code */ }
@kotlin.jvm.JvmStatic
@org.jetbrains.annotations.NotNull
public final <T> SmartSet<T> create(@org.jetbrains.annotations.NotNull java.util.Collection<? extends T> set) { /* compiled code */ }
private Companion() { /* compiled code */ }
}
}

View File

@@ -0,0 +1,35 @@
// SmartSet
class SmartSet<T> private constructor() : AbstractSet<T>(), MutableSet<T> {
companion object {
private val ARRAY_THRESHOLD = 5
@JvmStatic
fun <T> create() = SmartSet<T>()
@JvmStatic
fun <T> create(set: Collection<T>): SmartSet<T> = TODO()
}
private var data: Any? = null
override var size: Int = 0
override fun iterator(): MutableIterator<T> = TODO()
override fun add(element: T): Boolean = TODO()
override fun clear() {
data = null
size = 0
}
override fun contains(element: T): Boolean = when {
size == 0 -> false
size == 1 -> data == element
size < ARRAY_THRESHOLD -> element in data as Array<T>
else -> element in data as Set<T>
}
}

View File

@@ -1,6 +1,8 @@
Usage: kotlinc-js <options> <source files>
where advanced options include:
-Xtypedarrays Translate primitive arrays to JS typed arrays
-Xtyped-arrays Translate primitive arrays to JS typed arrays
-Xfriend-modules-disabled Disable internal declaration export
-Xfriend-modules=<path> Paths to friend modules
-Xno-inline Disable method inlining
-Xrepeat=<count> Repeat compilation (for performance analysis)
-Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes)
@@ -14,4 +16,4 @@ where advanced options include:
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
Advanced options are non-standard and may be changed or removed without any notice.
OK
OK

View File

@@ -0,0 +1,4 @@
$TESTDATA_DIR$/javaSrcWrongPackage.kt
$TESTDATA_DIR$/javaSrcWrongPackage
-d
$TEMP_DIR$

View File

@@ -0,0 +1 @@
fun test(): A.Nested = A().nested()

View File

@@ -0,0 +1,7 @@
compiler/testData/cli/jvm/javaSrcWrongPackage.kt:1:13: error: unresolved reference: A
fun test(): A.Nested = A().nested()
^
compiler/testData/cli/jvm/javaSrcWrongPackage.kt:1:24: error: unresolved reference: A
fun test(): A.Nested = A().nested()
^
COMPILATION_ERROR

View File

@@ -0,0 +1,9 @@
package foo;
public class A {
public Nested nested() {
return new Nested();
}
public static class Nested {}
}

View File

@@ -0,0 +1,11 @@
$TESTDATA_DIR$/singleJavaFileRoots/test.kt
$TESTDATA_DIR$/singleJavaFileRoots/DefaultPackage.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/A.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/B.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/ext/SeveralClasses.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/ClassClass.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/InterfaceClass.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/EnumClass.java
$TESTDATA_DIR$/singleJavaFileRoots/lib/classKinds/AnnotationClass.java
-d
$TEMP_DIR$

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