mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-21 15:52:06 +00:00
Compare commits
265 Commits
push/pdn_b
...
v1.2.51
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3f5293647 | ||
|
|
bf5b1f871c | ||
|
|
a41469484d | ||
|
|
b2836fa195 | ||
|
|
13823a5299 | ||
|
|
c5a030000b | ||
|
|
c9767532b5 | ||
|
|
9b85b1b173 | ||
|
|
30c16a654e | ||
|
|
4ce9b7f797 | ||
|
|
f92bc49977 | ||
|
|
933afcfa34 | ||
|
|
da1da0e52d | ||
|
|
8cf3871750 | ||
|
|
9838ed8e14 | ||
|
|
decbe7dcb0 | ||
|
|
a3eb82380d | ||
|
|
adabcc5c02 | ||
|
|
b86dec0511 | ||
|
|
738f2202ac | ||
|
|
fd07c698f1 | ||
|
|
ae4c547547 | ||
|
|
691737dbf0 | ||
|
|
363dbba402 | ||
|
|
78aed39efc | ||
|
|
d7fadb2661 | ||
|
|
fcb03eda67 | ||
|
|
fd0e2abbef | ||
|
|
927ebe0de8 | ||
|
|
647bb5f232 | ||
|
|
811a6d044e | ||
|
|
18a5c4c6b1 | ||
|
|
90a6c3c5d4 | ||
|
|
ba57ae0337 | ||
|
|
f32e13ee4b | ||
|
|
65a1ab606c | ||
|
|
101e2f6d6a | ||
|
|
0b1c3f3a68 | ||
|
|
08c02acf62 | ||
|
|
3c5a2fc90a | ||
|
|
cf835ce375 | ||
|
|
4ff404c342 | ||
|
|
8df104c8ff | ||
|
|
697bee6e5b | ||
|
|
2fd5a1a25b | ||
|
|
cfb00723be | ||
|
|
19e779c5cd | ||
|
|
349bfbcaad | ||
|
|
849dd09fb9 | ||
|
|
1aec99536b | ||
|
|
7795ac1839 | ||
|
|
8a8d2587dd | ||
|
|
965937b8a4 | ||
|
|
7608fd71d5 | ||
|
|
045dfc021e | ||
|
|
fb0574d2ff | ||
|
|
96db6abfc5 | ||
|
|
cb9fb6a641 | ||
|
|
a0e7649167 | ||
|
|
67331ab3a8 | ||
|
|
6e69b19df9 | ||
|
|
f23a96a82a | ||
|
|
6935b7578b | ||
|
|
c5b9f83ac3 | ||
|
|
66612379c8 | ||
|
|
81d965add2 | ||
|
|
6215258ad7 | ||
|
|
a0e3060157 | ||
|
|
71d089f280 | ||
|
|
13d747f46f | ||
|
|
24b79b498d | ||
|
|
0333a6063f | ||
|
|
6672b38370 | ||
|
|
02f857bd77 | ||
|
|
23032e4f9f | ||
|
|
a70fa6871a | ||
|
|
5ed5de727e | ||
|
|
56a4feff48 | ||
|
|
d50ea1196d | ||
|
|
a558358982 | ||
|
|
a7ff35c03e | ||
|
|
6b63fb7f1f | ||
|
|
688377f5c4 | ||
|
|
d6e506d50e | ||
|
|
b2f055f52f | ||
|
|
275a5bb2d9 | ||
|
|
74009c311c | ||
|
|
e83d4dcefc | ||
|
|
4235a77f74 | ||
|
|
cda370366a | ||
|
|
89495e2730 | ||
|
|
d90fbc55d2 | ||
|
|
c71ea33b0e | ||
|
|
24387fcccb | ||
|
|
bf493b9a7f | ||
|
|
67b2f27dfe | ||
|
|
fcc0425648 | ||
|
|
e226f1bdcf | ||
|
|
cd2aff258b | ||
|
|
7ee91a90fb | ||
|
|
11e046eca1 | ||
|
|
2d541de5b0 | ||
|
|
e24df1b8b7 | ||
|
|
b5c8da9867 | ||
|
|
7dc10f316e | ||
|
|
7fd0dd327b | ||
|
|
5fbeddbd5a | ||
|
|
b916af81ef | ||
|
|
85ed9eebd1 | ||
|
|
0fddc25cd9 | ||
|
|
771aa0e9e4 | ||
|
|
31ddcabcee | ||
|
|
1f4635ab08 | ||
|
|
97ea12e8d4 | ||
|
|
e6323afc27 | ||
|
|
e1b15b668d | ||
|
|
feab7f2e70 | ||
|
|
399337653d | ||
|
|
2e8c9d44e3 | ||
|
|
6635d0a93f | ||
|
|
5fefb86f5a | ||
|
|
65344fc057 | ||
|
|
011e186c66 | ||
|
|
5806de9886 | ||
|
|
03421c5953 | ||
|
|
0d84d1014d | ||
|
|
e9629023e3 | ||
|
|
1d98e527db | ||
|
|
c502488a18 | ||
|
|
43e6283139 | ||
|
|
46ff33268e | ||
|
|
aeda20993f | ||
|
|
9bb72961ac | ||
|
|
694c8fa21e | ||
|
|
b46f69e022 | ||
|
|
58d499397f | ||
|
|
e0d5714ba1 | ||
|
|
0aeebcfbf2 | ||
|
|
9d91d8c634 | ||
|
|
a6d7b80dba | ||
|
|
b7c0805300 | ||
|
|
43b7433c39 | ||
|
|
1374918760 | ||
|
|
d9720495ca | ||
|
|
b82efb0a03 | ||
|
|
713c271723 | ||
|
|
b53f230f41 | ||
|
|
86f673362a | ||
|
|
3d0db05173 | ||
|
|
723664bc92 | ||
|
|
76ecba56f6 | ||
|
|
6a026f6ce2 | ||
|
|
a996bcf90e | ||
|
|
280cb9d0d7 | ||
|
|
27d1c1e05e | ||
|
|
8cca489c12 | ||
|
|
2266861ef4 | ||
|
|
b4a710a6a1 | ||
|
|
5b7940163d | ||
|
|
7b55f57ef2 | ||
|
|
72f55d908c | ||
|
|
349a187782 | ||
|
|
5989671057 | ||
|
|
31eaf45f2a | ||
|
|
b3cef661af | ||
|
|
ac340107f5 | ||
|
|
77df1ef527 | ||
|
|
533de6d0e9 | ||
|
|
7a88566979 | ||
|
|
09af555698 | ||
|
|
d7aa7b5b65 | ||
|
|
ce8de4c1b1 | ||
|
|
f59885510c | ||
|
|
b89cac274a | ||
|
|
db0b4b29fa | ||
|
|
8062966b74 | ||
|
|
533bd7c9bb | ||
|
|
b2234b1a53 | ||
|
|
85541aa9fc | ||
|
|
80ea6dce99 | ||
|
|
175f1b5b8d | ||
|
|
afba9c2e75 | ||
|
|
d4d0fc1a36 | ||
|
|
47ffa04f61 | ||
|
|
708e89c83e | ||
|
|
b43641a5aa | ||
|
|
f976383758 | ||
|
|
8095c7cdda | ||
|
|
a026c59aa6 | ||
|
|
f66f1e70d6 | ||
|
|
2078103269 | ||
|
|
23a49b8dec | ||
|
|
4ed8cd69ee | ||
|
|
3cf7a9d4e4 | ||
|
|
02738ddc04 | ||
|
|
c7dea060f9 | ||
|
|
03b9a18328 | ||
|
|
8f77eeed3c | ||
|
|
051e32058c | ||
|
|
f794c7bf3a | ||
|
|
a0b38ab6b8 | ||
|
|
17bbc693b5 | ||
|
|
792339bf6a | ||
|
|
a241400d42 | ||
|
|
161926d967 | ||
|
|
fd5d2275ce | ||
|
|
831c1fc66c | ||
|
|
1a9b6cbd64 | ||
|
|
27c3396d19 | ||
|
|
2ae054e79a | ||
|
|
9ec26b7f57 | ||
|
|
dc29e95c50 | ||
|
|
6203b03905 | ||
|
|
a2ff59a1d8 | ||
|
|
e9f0a1f602 | ||
|
|
f19ac848e4 | ||
|
|
2924c7fead | ||
|
|
764c8308e5 | ||
|
|
9cea01a2ef | ||
|
|
83b44aebe5 | ||
|
|
217253aaee | ||
|
|
f5a805fa4c | ||
|
|
fa911f61a4 | ||
|
|
fc692cda6a | ||
|
|
7ad0b90227 | ||
|
|
9e335d0f50 | ||
|
|
eae4153373 | ||
|
|
57d192d87b | ||
|
|
e3e8b549fb | ||
|
|
bda0f0db70 | ||
|
|
57c7c7c92c | ||
|
|
4ac17ab81d | ||
|
|
99ba778e62 | ||
|
|
bcfad29ae9 | ||
|
|
8a6bedf5f0 | ||
|
|
488a0c3adb | ||
|
|
eb091c32d0 | ||
|
|
424df2432a | ||
|
|
dff1da823c | ||
|
|
e72449229c | ||
|
|
e0fb7059e4 | ||
|
|
7f0007e93a | ||
|
|
eefe268730 | ||
|
|
709948168d | ||
|
|
4e3af8434e | ||
|
|
753f53ddab | ||
|
|
e9db300e6b | ||
|
|
3c9071ae84 | ||
|
|
4d77b34712 | ||
|
|
abea42c42b | ||
|
|
b5a9844359 | ||
|
|
ca736b50e9 | ||
|
|
fb9b9909be | ||
|
|
2d1b0b3008 | ||
|
|
1df8d2a9f3 | ||
|
|
0b6e27d1af | ||
|
|
d5764f0fb6 | ||
|
|
e83a4ae72b | ||
|
|
21d51548db | ||
|
|
ecf84523c1 | ||
|
|
747580d87c | ||
|
|
544f900268 | ||
|
|
1a94884fa9 | ||
|
|
1aebe45dd8 | ||
|
|
6cea85642c |
32
.idea/misc.xml
generated
32
.idea/misc.xml
generated
@@ -44,6 +44,38 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.validation.constraints.NotNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectResources">
|
||||
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
|
||||
</component>
|
||||
|
||||
481
ChangeLog.md
481
ChangeLog.md
@@ -1,5 +1,486 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 1.2.50
|
||||
|
||||
### Compiler
|
||||
|
||||
- [`KT-23360`](https://youtrack.jetbrains.com/issue/KT-23360) Do not serialize annotations with retention SOURCE to metadata
|
||||
- [`KT-24278`](https://youtrack.jetbrains.com/issue/KT-24278) Hard-code to kotlin compiler annotation for android library migration
|
||||
- [`KT-24472`](https://youtrack.jetbrains.com/issue/KT-24472) Support argfiles in kotlinc with -Xargfile
|
||||
- [`KT-24593`](https://youtrack.jetbrains.com/issue/KT-24593) Support -XXLanguage:{+|-}LanguageFeature compiler arguments to enable/disable specific features
|
||||
- [`KT-24637`](https://youtrack.jetbrains.com/issue/KT-24637) Introduce "progressive" mode of compiler
|
||||
|
||||
#### Backend. JS
|
||||
|
||||
- [`KT-23094`](https://youtrack.jetbrains.com/issue/KT-23094) JS compiler: Delegation fails to pass the continuation parameter to child suspend function
|
||||
- [`KT-23582`](https://youtrack.jetbrains.com/issue/KT-23582) JS: Fails to inline, produces bad code
|
||||
- [`KT-24335`](https://youtrack.jetbrains.com/issue/KT-24335) JS: Invalid implement of external interface
|
||||
|
||||
#### Backend. JVM
|
||||
|
||||
- [`KT-12330`](https://youtrack.jetbrains.com/issue/KT-12330) Slightly improve generated bytecode for data class equals/hashCode methods
|
||||
- [`KT-18576`](https://youtrack.jetbrains.com/issue/KT-18576) Debugger fails to show decomposed suspend lambda parameters
|
||||
- [`KT-22063`](https://youtrack.jetbrains.com/issue/KT-22063) Add intrinsics for javaObjectType and javaPrimitiveType
|
||||
- [`KT-23402`](https://youtrack.jetbrains.com/issue/KT-23402) Internal error: Couldn't inline method call because the compiler couldn't obtain compiled body for inline function with reified type parameter
|
||||
- [`KT-23704`](https://youtrack.jetbrains.com/issue/KT-23704) Unstable `checkExpressionValueIsNotNull()` generation in bytecode
|
||||
- [`KT-23707`](https://youtrack.jetbrains.com/issue/KT-23707) Unstable bridge generation order
|
||||
- [`KT-23857`](https://youtrack.jetbrains.com/issue/KT-23857) Annotation with target TYPE is not applicable to TYPE_USE in Java sources
|
||||
- [`KT-23910`](https://youtrack.jetbrains.com/issue/KT-23910) @JvmOverloads doesn't work with default arguments in common code
|
||||
- [`KT-24427`](https://youtrack.jetbrains.com/issue/KT-24427) Protected function having toArray-like signature from collection becomes public in bytecode
|
||||
- [`KT-24661`](https://youtrack.jetbrains.com/issue/KT-24661) Support binary compatibility mode for @JvmDefault
|
||||
|
||||
#### Frontend
|
||||
|
||||
- [`KT-21129`](https://youtrack.jetbrains.com/issue/KT-21129) Unused parameter in property setter is not reported
|
||||
- [`KT-21157`](https://youtrack.jetbrains.com/issue/KT-21157) Kotlin script: engine can take forever to eval certain code after several times
|
||||
- [`KT-22740`](https://youtrack.jetbrains.com/issue/KT-22740) REPL slows down during extensions compiling
|
||||
- [`KT-23124`](https://youtrack.jetbrains.com/issue/KT-23124) Kotlin multiplatform project causes IntelliJ build errors
|
||||
- [`KT-23209`](https://youtrack.jetbrains.com/issue/KT-23209) Compiler throwing frontend exception
|
||||
- [`KT-23589`](https://youtrack.jetbrains.com/issue/KT-23589) Report a warning on local annotation classes
|
||||
- [`KT-23760`](https://youtrack.jetbrains.com/issue/KT-23760) Unable to implement common interface with fun member function with typealiased parameter
|
||||
|
||||
### Android
|
||||
|
||||
- [`KT-23244`](https://youtrack.jetbrains.com/issue/KT-23244) Option to Disable View Binding generation in Kotlin Android Extensions Plugin
|
||||
|
||||
### IDE
|
||||
|
||||
- [`KT-8407`](https://youtrack.jetbrains.com/issue/KT-8407) TestNG: running tests from context creates new run configuration every time
|
||||
- [`KT-9218`](https://youtrack.jetbrains.com/issue/KT-9218) Searching for compilable files takes too long
|
||||
- [`KT-15019`](https://youtrack.jetbrains.com/issue/KT-15019) Editor: `args` reference in .kts file is red
|
||||
- [`KT-18769`](https://youtrack.jetbrains.com/issue/KT-18769) Expand Selection on opening curly brace should select the entire block right away
|
||||
- [`KT-19055`](https://youtrack.jetbrains.com/issue/KT-19055) Idea hangs on copy-paste big Kotlin files
|
||||
- [`KT-20605`](https://youtrack.jetbrains.com/issue/KT-20605) Unresolved reference on instance from common module function
|
||||
- [`KT-20824`](https://youtrack.jetbrains.com/issue/KT-20824) Type mismatch for common function taking a non-mapped Kotlin's expected class from stdlib-common, with actual typealias on JVM
|
||||
- [`KT-20897`](https://youtrack.jetbrains.com/issue/KT-20897) Can't navigate to declaration after PsiInvalidElementAccessException exception
|
||||
- [`KT-22527`](https://youtrack.jetbrains.com/issue/KT-22527) Kotlin UAST does not evaluate values inside delegation expressions
|
||||
- [`KT-22868`](https://youtrack.jetbrains.com/issue/KT-22868) Implementing an `expected class` declaration using `actual typealias` produces "good code that is red"
|
||||
- [`KT-22922`](https://youtrack.jetbrains.com/issue/KT-22922) Override Members should add experimental annotation when required
|
||||
- [`KT-23384`](https://youtrack.jetbrains.com/issue/KT-23384) Hotspot in org.jetbrains.kotlin.idea.caches.resolve.IDELightClassGenerationSupport.getKotlinInternalClasses(FqName, GlobalSearchScope) IDELightClassGenerationSupport.kt ?
|
||||
- [`KT-23408`](https://youtrack.jetbrains.com/issue/KT-23408) Don't render @NonNull and @Nullable annotations in parameter info for Java methods
|
||||
- [`KT-23557`](https://youtrack.jetbrains.com/issue/KT-23557) Expression Bodies should have implicit `return` in Uast
|
||||
- [`KT-23745`](https://youtrack.jetbrains.com/issue/KT-23745) Unable to implement common interface
|
||||
- [`KT-23746`](https://youtrack.jetbrains.com/issue/KT-23746) Logger$EmptyThrowable "[kts] cannot find a valid script definition annotation on the class class ScriptTemplateWithArgs" with LivePlugin enabled
|
||||
- [`KT-23975`](https://youtrack.jetbrains.com/issue/KT-23975) Move Kotlin internal actions under Idea Internal actions menu
|
||||
- [`KT-24268`](https://youtrack.jetbrains.com/issue/KT-24268) Other main menu item
|
||||
- [`KT-24438`](https://youtrack.jetbrains.com/issue/KT-24438) ISE “The provided plugin org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar is not compatible with this version of compiler” after rebuilding simple Gradle-based project via JPS.
|
||||
|
||||
#### IDE. Configuration
|
||||
|
||||
- [`KT-10935`](https://youtrack.jetbrains.com/issue/KT-10935) Add menu entry to create new kotlin .kts scripts
|
||||
- [`KT-20511`](https://youtrack.jetbrains.com/issue/KT-20511) Library added from maven (using IDEA UI) is not detected as Kotlin/JS library (since type="repository")
|
||||
- [`KT-20665`](https://youtrack.jetbrains.com/issue/KT-20665) Kotlin Gradle script created by New Project/Module wizard fails with Gradle 4.1+
|
||||
- [`KT-21844`](https://youtrack.jetbrains.com/issue/KT-21844) Create Kotlin class dialog: make class abstract automatically
|
||||
- [`KT-22305`](https://youtrack.jetbrains.com/issue/KT-22305) Language and API versions of Kotlin compiler are “Latest” by default in some ways of creating new project
|
||||
- [`KT-23261`](https://youtrack.jetbrains.com/issue/KT-23261) New MPP design: please show popup with error message if module name is not set
|
||||
- [`KT-23638`](https://youtrack.jetbrains.com/issue/KT-23638) Kotlin plugin breaks project opening for PhpStorm/WebStorm
|
||||
- [`KT-23658`](https://youtrack.jetbrains.com/issue/KT-23658) Unclear options “Gradle” and “Gradle (Javascript)” on configuring Kotlin in Gradle- and Maven-based projects
|
||||
- [`KT-23845`](https://youtrack.jetbrains.com/issue/KT-23845) IntelliJ Maven Plugin does not pass javaParameters option to Kotlin facet
|
||||
- [`KT-23980`](https://youtrack.jetbrains.com/issue/KT-23980) Move "Update Channel" from "Configure Kotlin Plugin Updates" to settings
|
||||
- [`KT-24504`](https://youtrack.jetbrains.com/issue/KT-24504) Existent JPS-based Kotlin/JS module is converted to new format, while New Project wizard and facet manipulations still create old format
|
||||
|
||||
#### IDE. Debugger
|
||||
|
||||
- [`KT-23886`](https://youtrack.jetbrains.com/issue/KT-23886) Both java and kotlin breakpoints in kotlin files
|
||||
- [`KT-24136`](https://youtrack.jetbrains.com/issue/KT-24136) Debugger: update drop-down menu for the line with lambdas
|
||||
|
||||
#### IDE. Editing
|
||||
|
||||
- [`KT-2582`](https://youtrack.jetbrains.com/issue/KT-2582) When user inputs triple quote, add matching triple quote automatically
|
||||
- [`KT-5206`](https://youtrack.jetbrains.com/issue/KT-5206) Long lists of arguments are not foldable
|
||||
- [`KT-23457`](https://youtrack.jetbrains.com/issue/KT-23457) Auto-import and Import quick fix do not suggest classes from common module [Common test can't find class with word `Abstract` in name.]
|
||||
- [`KT-23235`](https://youtrack.jetbrains.com/issue/KT-23235) Super slow editing with auto imports enabled
|
||||
|
||||
#### IDE. Gradle
|
||||
|
||||
- [`KT-23234`](https://youtrack.jetbrains.com/issue/KT-23234) Test names for tests containing inner classes are sporadically reported to teamcity runs.
|
||||
- [`KT-23383`](https://youtrack.jetbrains.com/issue/KT-23383) Optional plugin dependency for kotlin gradle plugin 'java' subsystem dependent features
|
||||
- [`KT-22588`](https://youtrack.jetbrains.com/issue/KT-22588) Resolver for 'project source roots and libraries for platform JVM' does not know how to resolve on Gradle Kotlin DSL project without Java and Kotlin
|
||||
- [`KT-23616`](https://youtrack.jetbrains.com/issue/KT-23616) Synchronize script dependencies not at Gradle Sync
|
||||
- [`KT-24444`](https://youtrack.jetbrains.com/issue/KT-24444) Do not store proxy objects from Gradle importer in the project model
|
||||
- [`KT-24586`](https://youtrack.jetbrains.com/issue/KT-24586) MVNFE “Cannot resolve external dependency org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.41 because no repositories are defined.” on creating Gradle project with Kotlin only (probably due to lack of repositories block)
|
||||
- [`KT-24671`](https://youtrack.jetbrains.com/issue/KT-24671) dependencies missed in buildscript block after creating new Gradle-based project in 173 IDEA
|
||||
|
||||
#### IDE. Inspections and Intentions
|
||||
|
||||
##### New Features
|
||||
|
||||
- [`KT-7822`](https://youtrack.jetbrains.com/issue/KT-7822) Convert foreach to for loop should place caret on the variable declaration
|
||||
- [`KT-9943`](https://youtrack.jetbrains.com/issue/KT-9943) Quick fix/Intention to indent a raw string
|
||||
- [`KT-15063`](https://youtrack.jetbrains.com/issue/KT-15063) Inspection for coroutine: unused Deferred result
|
||||
- [`KT-16085`](https://youtrack.jetbrains.com/issue/KT-16085) Inspection "main should return Unit"
|
||||
- [`KT-20305`](https://youtrack.jetbrains.com/issue/KT-20305) Inspection: Refactor sealed sub-class to object
|
||||
- [`KT-21413`](https://youtrack.jetbrains.com/issue/KT-21413) Missing inspection: parentheses can be deleted when the only constructor parameter is a function not existing
|
||||
- [`KT-23137`](https://youtrack.jetbrains.com/issue/KT-23137) Intention for converting to block comment and vise versa
|
||||
- [`KT-23266`](https://youtrack.jetbrains.com/issue/KT-23266) Add intention(s) to put arguments / parameters on one line
|
||||
- [`KT-23419`](https://youtrack.jetbrains.com/issue/KT-23419) Intention to replace vararg with array and vice versa
|
||||
- [`KT-23617`](https://youtrack.jetbrains.com/issue/KT-23617) Add inspection: redundant internal in local anonymous object / class
|
||||
- [`KT-23775`](https://youtrack.jetbrains.com/issue/KT-23775) IntelliJ plugin: improve "accessor call that can be replaced with property"
|
||||
- [`KT-24235`](https://youtrack.jetbrains.com/issue/KT-24235) Inspection to replace async.await with withContext
|
||||
- [`KT-24263`](https://youtrack.jetbrains.com/issue/KT-24263) Add `Make variable immutable` quickfix for const
|
||||
- [`KT-24433`](https://youtrack.jetbrains.com/issue/KT-24433) Inspection for coroutines: unused async result
|
||||
|
||||
##### Performance Improvements
|
||||
|
||||
- [`KT-23566`](https://youtrack.jetbrains.com/issue/KT-23566) "Can be private" works on ResolutionResultsCache.kt (from Kotlin project) enormously slow
|
||||
|
||||
##### Fixes
|
||||
|
||||
- [`KT-6364`](https://youtrack.jetbrains.com/issue/KT-6364) Incorrect quick-fixes are suggested for nullable extension function call
|
||||
- [`KT-11156`](https://youtrack.jetbrains.com/issue/KT-11156) Incorrect highlighting for nested class in "Redundant SAM-constructor" inspection
|
||||
- [`KT-11427`](https://youtrack.jetbrains.com/issue/KT-11427) "Replace if with when" does not take break / continue into account
|
||||
- [`KT-11740`](https://youtrack.jetbrains.com/issue/KT-11740) Invert if condition intention should not remove line breaks
|
||||
- [`KT-12042`](https://youtrack.jetbrains.com/issue/KT-12042) "Merge with next when" is not applicable when the statements delimited by semicolon or comment
|
||||
- [`KT-12168`](https://youtrack.jetbrains.com/issue/KT-12168) "Remove explicit type specification" intention produce incompilable code in case of function type
|
||||
- [`KT-14391`](https://youtrack.jetbrains.com/issue/KT-14391) RemoveUnnecessaryParenthesesIntention lost comment on closing parenthesis
|
||||
- [`KT-14556`](https://youtrack.jetbrains.com/issue/KT-14556) Quickfix to suggest use of spread operator does not work with mapOf
|
||||
- [`KT-15195`](https://youtrack.jetbrains.com/issue/KT-15195) Redundant parentheses shouldn't be reported if lambda is not on the same line
|
||||
- [`KT-16770`](https://youtrack.jetbrains.com/issue/KT-16770) Change type of function quickfix does not propose most idiomatic solutions
|
||||
- [`KT-19629`](https://youtrack.jetbrains.com/issue/KT-19629) "Convert to primary constructor" quick fix should not move `init{...}` section down
|
||||
- [`KT-20123`](https://youtrack.jetbrains.com/issue/KT-20123) Kotlin Gradle script: “Refactoring cannot be performed. Cannot modify build.gradle.kts” for some refactorings and intentions
|
||||
- [`KT-20332`](https://youtrack.jetbrains.com/issue/KT-20332) Unused property declaration suppression by annotation doesn't work if annotation is targeted to getter
|
||||
- [`KT-21878`](https://youtrack.jetbrains.com/issue/KT-21878) "arrayOf() call can be replaced by array litteral [...]" quick fix inserts extra parentheses
|
||||
- [`KT-22092`](https://youtrack.jetbrains.com/issue/KT-22092) Intention "Specify return type explicitly": Propose types from overriden declarations
|
||||
- [`KT-22615`](https://youtrack.jetbrains.com/issue/KT-22615) "Replace with" intention does not work for equal names
|
||||
- [`KT-22632`](https://youtrack.jetbrains.com/issue/KT-22632) Gutter icon "go to actual declaration" is absent for enum values on actual side
|
||||
- [`KT-22741`](https://youtrack.jetbrains.com/issue/KT-22741) Wrong suggestion for `Replace 'if' expression with elvis expression`
|
||||
- [`KT-22831`](https://youtrack.jetbrains.com/issue/KT-22831) Inspection for converting to elvis operator does not work for local vars
|
||||
- [`KT-22860`](https://youtrack.jetbrains.com/issue/KT-22860) "Add annotation target" quick fix does not take into account existent annotations in Java source
|
||||
- [`KT-22918`](https://youtrack.jetbrains.com/issue/KT-22918) Create interface quickfix is missing 'current class' container
|
||||
- [`KT-23133`](https://youtrack.jetbrains.com/issue/KT-23133) "Remove redundant calls of the conversion method" wrongly shown for Boolan to Int conversion
|
||||
- [`KT-23167`](https://youtrack.jetbrains.com/issue/KT-23167) Report "use expression body" also on left brace
|
||||
- [`KT-23194`](https://youtrack.jetbrains.com/issue/KT-23194) Inspection "map.put() should be converted to assignment" leads to red code in case of labled return
|
||||
- [`KT-23303`](https://youtrack.jetbrains.com/issue/KT-23303) "Might be const" inspection does not check explicit type specification
|
||||
- [`KT-23320`](https://youtrack.jetbrains.com/issue/KT-23320) Quick fix to add constructor invocation doesn't work for sealed classes
|
||||
- [`KT-23321`](https://youtrack.jetbrains.com/issue/KT-23321) Intention to move type to separate file shouldn't be available for sealed classes
|
||||
- [`KT-23346`](https://youtrack.jetbrains.com/issue/KT-23346) Lift Assignment quick fix incorrectly processes block assignments
|
||||
- [`KT-23377`](https://youtrack.jetbrains.com/issue/KT-23377) Simplify boolean expression produces incorrect results when mixing nullable and non-nullable variables
|
||||
- [`KT-23465`](https://youtrack.jetbrains.com/issue/KT-23465) False positive `suspicious callable reference` on lambda invoke with parameters
|
||||
- [`KT-23511`](https://youtrack.jetbrains.com/issue/KT-23511) "Remove parameter" quick fix makes generic function call incompilable when type could be inferred from removed parameter only
|
||||
- [`KT-23513`](https://youtrack.jetbrains.com/issue/KT-23513) "Remove parameter" quick fix makes caret jump to the top of the editor
|
||||
- [`KT-23559`](https://youtrack.jetbrains.com/issue/KT-23559) Wrong hint text for "assignment can be replaced with operator assignment"
|
||||
- [`KT-23608`](https://youtrack.jetbrains.com/issue/KT-23608) AE “Failed to create expression from text” after applying quick fix “Convert too long character literal to string”
|
||||
- [`KT-23620`](https://youtrack.jetbrains.com/issue/KT-23620) False positive `Redundant Companion reference` on calling object from companion
|
||||
- [`KT-23634`](https://youtrack.jetbrains.com/issue/KT-23634) 'Add use-site target' intention drops annotation arguments
|
||||
- [`KT-23753`](https://youtrack.jetbrains.com/issue/KT-23753) "Remove variable" quick fix should not remove comment
|
||||
- [`KT-23756`](https://youtrack.jetbrains.com/issue/KT-23756) Bogus "Might be const" warning in object expression
|
||||
- [`KT-23778`](https://youtrack.jetbrains.com/issue/KT-23778) "Convert function to property" intention shows broken warning
|
||||
- [`KT-23796`](https://youtrack.jetbrains.com/issue/KT-23796) "Create extension function/property" quick fix suggests one for nullable type while creates for not-null
|
||||
- [`KT-23801`](https://youtrack.jetbrains.com/issue/KT-23801) "Convert to constructor" (IntelliJ) quick fix uses wrong use-site target for annotating properties
|
||||
- [`KT-23977`](https://youtrack.jetbrains.com/issue/KT-23977) wrong hint Unit redundant
|
||||
- [`KT-24066`](https://youtrack.jetbrains.com/issue/KT-24066) 'Remove redundant Unit' false positive when Unit is returned as Any
|
||||
- [`KT-24165`](https://youtrack.jetbrains.com/issue/KT-24165) @Deprecated ReplaceWith Constant gets replaced with nothing
|
||||
- [`KT-24207`](https://youtrack.jetbrains.com/issue/KT-24207) Add parameter intent/red bulb should use auto casted type.
|
||||
- [`KT-24215`](https://youtrack.jetbrains.com/issue/KT-24215) ReplaceWith produces broken code for lambda following default parameter
|
||||
|
||||
#### IDE. Multiplatform
|
||||
|
||||
- [`KT-20406`](https://youtrack.jetbrains.com/issue/KT-20406) Overload resolution ambiguity in IDE on expect class / actual typealias from kotlin-stdlib-common / kotlin-stdlib
|
||||
- [`KT-24316`](https://youtrack.jetbrains.com/issue/KT-24316) Missing dependencies in Kotlin MPP when using gradle composite builds
|
||||
|
||||
#### IDE. Navigation
|
||||
|
||||
- [`KT-7622`](https://youtrack.jetbrains.com/issue/KT-7622) Searching usages of a field/constructor parameter in a private class seems to scan through the whole project
|
||||
- [`KT-23182`](https://youtrack.jetbrains.com/issue/KT-23182) Find Usages checks whether there are unused variables in functions which contain search result candidates
|
||||
- [`KT-23223`](https://youtrack.jetbrains.com/issue/KT-23223) Navigate to actual declaration from actual usage
|
||||
|
||||
#### IDE. Refactorings
|
||||
|
||||
- [`KT-12078`](https://youtrack.jetbrains.com/issue/KT-12078) Introduce Variable adds explicit type when invoked on anonymous object
|
||||
- [`KT-15517`](https://youtrack.jetbrains.com/issue/KT-15517) Change signature refactoring shows confusing warning dialog
|
||||
- [`KT-22387`](https://youtrack.jetbrains.com/issue/KT-22387) Change signature reports "Type cannot be resolved" for class from different package
|
||||
- [`KT-22669`](https://youtrack.jetbrains.com/issue/KT-22669) Refactor / Copy Kotlin source to plain text causes CCE: "PsiPlainTextFileImpl cannot be cast to KtFile" at CopyKotlinDeclarationsHandler$doCopy$2$1$1.invoke()
|
||||
- [`KT-22888`](https://youtrack.jetbrains.com/issue/KT-22888) Rename completion cuts off all characters except letters from existent name
|
||||
- [`KT-23298`](https://youtrack.jetbrains.com/issue/KT-23298) AE: "2 declarations in null..." on rename of a field to `object` or `class`
|
||||
- [`KT-23563`](https://youtrack.jetbrains.com/issue/KT-23563) null by org.jetbrains.kotlin.idea.refactoring.rename.KotlinMemberInplaceRenameHandler$RenamerImpl exception on trying in-place Rename of non-scratch functions
|
||||
- [`KT-23613`](https://youtrack.jetbrains.com/issue/KT-23613) Kotlin safe delete processor handles java code when it should not
|
||||
- [`KT-23644`](https://youtrack.jetbrains.com/issue/KT-23644) Named parameters in generated Kotlin Annotations
|
||||
- [`KT-23714`](https://youtrack.jetbrains.com/issue/KT-23714) Add Parameter quickfix not working when the called method is in java.
|
||||
- [`KT-23838`](https://youtrack.jetbrains.com/issue/KT-23838) Do not search for usages in other files when renaming local variable
|
||||
- [`KT-24069`](https://youtrack.jetbrains.com/issue/KT-24069) 'Create from usage' doesn't use type info with smart casts
|
||||
|
||||
#### IDE. Scratch
|
||||
|
||||
- [`KT-6928`](https://youtrack.jetbrains.com/issue/KT-6928) Support Kotlin scratch files
|
||||
- [`KT-23441`](https://youtrack.jetbrains.com/issue/KT-23441) Scratch options reset on IDE restart
|
||||
- [`KT-23480`](https://youtrack.jetbrains.com/issue/KT-23480) java.util.NoSuchElementException: "Collection contains no element matching the predicate" on run of a scratch file with unresolved function parameter
|
||||
- [`KT-23587`](https://youtrack.jetbrains.com/issue/KT-23587) Scratch: references from scratch file aren't taken into account
|
||||
- [`KT-24016`](https://youtrack.jetbrains.com/issue/KT-24016) Make long scratch output lines readable
|
||||
- [`KT-24315`](https://youtrack.jetbrains.com/issue/KT-24315) Checkbox labels aren't aligned in scratch panel
|
||||
- [`KT-24636`](https://youtrack.jetbrains.com/issue/KT-24636) Run Scratch when there are compilation errors in module
|
||||
|
||||
#### Tools. J2K
|
||||
|
||||
- [`KT-22989`](https://youtrack.jetbrains.com/issue/KT-22989) Exception "Assertion failed: Refactorings should be invoked inside transaction" on creating UI Component/Notification
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-10456`](https://youtrack.jetbrains.com/issue/KT-10456) Common Int.toString(radix: Int) method
|
||||
- [`KT-22298`](https://youtrack.jetbrains.com/issue/KT-22298) Improve docs for Array.copyOf(newSize: Int)
|
||||
- [`KT-22400`](https://youtrack.jetbrains.com/issue/KT-22400) coroutineContext shall be in kotlin.coroutines.experimental package
|
||||
- [`KT-23356`](https://youtrack.jetbrains.com/issue/KT-23356) Cross-platform function to convert CharArray slice to String
|
||||
- [`KT-23920`](https://youtrack.jetbrains.com/issue/KT-23920) CharSequence.trimEnd calls substring instead of subSequence
|
||||
- [`KT-24353`](https://youtrack.jetbrains.com/issue/KT-24353) Add support for junit 5 in kotlin.test
|
||||
- [`KT-24371`](https://youtrack.jetbrains.com/issue/KT-24371) Invalid @returns tag does not display in Android Studio popup properly
|
||||
|
||||
### Gradle plugin
|
||||
|
||||
- [`KT-20214`](https://youtrack.jetbrains.com/issue/KT-20214) NoClassDefFound from Gradle (should report missing tools.jar)
|
||||
- [`KT-20608`](https://youtrack.jetbrains.com/issue/KT-20608) Cannot reference operator overloads across submodules (.kotlin_module not loaded when a module name has a slash)
|
||||
- [`KT-22431`](https://youtrack.jetbrains.com/issue/KT-22431) Inter-project incremental compilation does not work with Android plugin 2.3+
|
||||
- [`KT-22510`](https://youtrack.jetbrains.com/issue/KT-22510) Common sources aren't added when compiling custom source set with Gradle multiplatform plugin
|
||||
- [`KT-22623`](https://youtrack.jetbrains.com/issue/KT-22623) Kotlin JVM tasks in independent projects are not executed in parallel with Gradle 4.2+ and Kotlin 1.2.20+
|
||||
- [`KT-23092`](https://youtrack.jetbrains.com/issue/KT-23092) Gradle plugin for MPP common modules should not remove the 'compileJava' task from `project.tasks`
|
||||
- [`KT-23574`](https://youtrack.jetbrains.com/issue/KT-23574) 'archivesBaseName' does not affect module name in common modules
|
||||
- [`KT-23719`](https://youtrack.jetbrains.com/issue/KT-23719) Incorrect Gradle Warning for expectedBy in kotlin-platform-android module
|
||||
- [`KT-23878`](https://youtrack.jetbrains.com/issue/KT-23878) Kapt: Annotation processors are run when formatting is changed
|
||||
- [`KT-24420`](https://youtrack.jetbrains.com/issue/KT-24420) Kapt plugin: Kapt task has overlapping outputs (and inputs) with Gradle's JavaCompile task
|
||||
- [`KT-24440`](https://youtrack.jetbrains.com/issue/KT-24440) Gradle daemon OOM due to function descriptors stuck forever
|
||||
|
||||
### Tools. kapt
|
||||
|
||||
- [`KT-23286`](https://youtrack.jetbrains.com/issue/KT-23286) kapt + nonascii = weird pathes
|
||||
- [`KT-23427`](https://youtrack.jetbrains.com/issue/KT-23427) kapt: for element with multiple annotations, annotation values erroneously use default when first annotation uses default
|
||||
- [`KT-23721`](https://youtrack.jetbrains.com/issue/KT-23721) Warning informing user that 'tools.jar' is absent in the plugin classpath is not show when there is also an error
|
||||
- [`KT-23898`](https://youtrack.jetbrains.com/issue/KT-23898) Kapt: Do now show a warning for APs from 'annotationProcessor' configuration also declared in 'kapt' configuration
|
||||
- [`KT-23964`](https://youtrack.jetbrains.com/issue/KT-23964) Kotlin Gradle plugin does not define inputs and outputs of annotation processors
|
||||
|
||||
## 1.2.41
|
||||
|
||||
### Compiler – Fixes
|
||||
- [`KT-23901`](https://youtrack.jetbrains.com/issue/KT-23901) Incremental compilation fails on Java 9
|
||||
- [`KT-23931`](https://youtrack.jetbrains.com/issue/KT-23931) Exception on optimizing eternal loops
|
||||
- [`KT-23900`](https://youtrack.jetbrains.com/issue/KT-23900) Exception on some cases with nested arrays
|
||||
- [`KT-23809`](https://youtrack.jetbrains.com/issue/KT-23809) Exception on processing complex hierarchies with `suspend` functions when `-Xdump-declarations-to` is active
|
||||
|
||||
### Other
|
||||
- [`KT-23973`](https://youtrack.jetbrains.com/issue/KT-23973) New compiler behavior lead to ambiguous mappings in Spring Boot temporarily reverted
|
||||
|
||||
## 1.2.40
|
||||
|
||||
### Compiler
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-22703`](https://youtrack.jetbrains.com/issue/KT-22703) Allow expect/actual annotation constructors to have default values
|
||||
- [`KT-19159`](https://youtrack.jetbrains.com/issue/KT-19159) Support `crossinline` lambda parameters of `suspend` function type
|
||||
- [`KT-21913`](https://youtrack.jetbrains.com/issue/KT-21913) Support default arguments for expected declarations
|
||||
- [`KT-19120`](https://youtrack.jetbrains.com/issue/KT-19120) Provide extra compiler arguments in `ScriptTemplateDefinition`
|
||||
- [`KT-19415`](https://youtrack.jetbrains.com/issue/KT-19415) Introduce `@JvmDefault` annotation
|
||||
- [`KT-21515`](https://youtrack.jetbrains.com/issue/KT-21515) Restrict visibility of classifiers inside `companion object`s
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-10057`](https://youtrack.jetbrains.com/issue/KT-10057) Use `lcmp` instruction instead of `kotlin/jvm/internal/Intrinsics.compare`
|
||||
- [`KT-14258`](https://youtrack.jetbrains.com/issue/KT-14258) Suboptimal codegen for private fieldaccess to private field in companion object
|
||||
- [`KT-18731`](https://youtrack.jetbrains.com/issue/KT-18731) `==` between enums should use reference equality, not `Intrinsics.areEqual()`.
|
||||
- [`KT-22714`](https://youtrack.jetbrains.com/issue/KT-22714) Unnecessary checkcast to array of object from an array of specific type
|
||||
- [`KT-5177`](https://youtrack.jetbrains.com/issue/KT-5177) Optimize code generation for `for` loop with `withIndex()`
|
||||
- [`KT-19477`](https://youtrack.jetbrains.com/issue/KT-19477) Allow to implement several common modules with a single platform module
|
||||
- [`KT-21347`](https://youtrack.jetbrains.com/issue/KT-21347) Add compiler warning about using kotlin-stdlib-jre7 or kotlin-stdlib-jre8 artifacts
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-16424`](https://youtrack.jetbrains.com/issue/KT-16424) Broken bytecode for nullable generic methods
|
||||
- [`KT-17171`](https://youtrack.jetbrains.com/issue/KT-17171) `ClassCastException` in case of SAM conversion with `out` variance
|
||||
- [`KT-19399`](https://youtrack.jetbrains.com/issue/KT-19399) Incorrect bytecode generated for inline functions in some complex cases
|
||||
- [`KT-21696`](https://youtrack.jetbrains.com/issue/KT-21696) Incorrect warning for use-site target on extension function
|
||||
- [`KT-22031`](https://youtrack.jetbrains.com/issue/KT-22031) Non-`abstract` expect classes should not have `abstract` members
|
||||
- [`KT-22260`](https://youtrack.jetbrains.com/issue/KT-22260) Never flag `inline suspend fun` with `NOTHING_TO_INLINE`
|
||||
- [`KT-22352`](https://youtrack.jetbrains.com/issue/KT-22352) Expect/actual checker can't handle properties and functions with the same name
|
||||
- [`KT-22652`](https://youtrack.jetbrains.com/issue/KT-22652) Interface with default overrides is not perceived as a SAM
|
||||
- [`KT-22904`](https://youtrack.jetbrains.com/issue/KT-22904) Incorrect bytecode generated for withIndex iteration on `Array<Int>`
|
||||
- [`KT-22906`](https://youtrack.jetbrains.com/issue/KT-22906) Invalid class name generated for lambda created from method reference in anonymous object
|
||||
- [`KT-23044`](https://youtrack.jetbrains.com/issue/KT-23044) Overriden public property with internal setter cannot be found in runtime
|
||||
- [`KT-23104`](https://youtrack.jetbrains.com/issue/KT-23104) Incorrect code generated for LHS of an intrinsified `in` operator in case of generic type substituted with `Character`
|
||||
- [`KT-23309`](https://youtrack.jetbrains.com/issue/KT-23309) Minor spelling errors in JVM internal error messages
|
||||
- [`KT-22001`](https://youtrack.jetbrains.com/issue/KT-22001) JS: compiler crashes on += with "complex" receiver
|
||||
- [`KT-23239`](https://youtrack.jetbrains.com/issue/KT-23239) JS: Default arguments for non-final member function support is missing for MPP
|
||||
- [`KT-17091`](https://youtrack.jetbrains.com/issue/KT-17091) Converting to SAM Java type appends non-deterministic hash to class name
|
||||
- [`KT-21521`](https://youtrack.jetbrains.com/issue/KT-21521) Compilation exception when trying to compile a `suspend` function with `tailrec` keyword
|
||||
- [`KT-21605`](https://youtrack.jetbrains.com/issue/KT-21605) Cross-inlined coroutine with captured outer receiver creates unverifiable code
|
||||
- [`KT-21864`](https://youtrack.jetbrains.com/issue/KT-21864) Expect-actual matcher doesn't consider generic upper bounds
|
||||
- [`KT-21906`](https://youtrack.jetbrains.com/issue/KT-21906) `ACTUAL_MISSING` is reported for actual constructor of non-actual class
|
||||
- [`KT-21939`](https://youtrack.jetbrains.com/issue/KT-21939) Improve `ACTUAL_MISSING` diagnostics message
|
||||
- [`KT-22513`](https://youtrack.jetbrains.com/issue/KT-22513) Flaky "JarURLConnection.getUseCaches" NPE during compilation when using compiler plugins
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-11208`](https://youtrack.jetbrains.com/issue/KT-11208) `readLine()` shouldn't use buffered reader
|
||||
|
||||
### IDE
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-10368`](https://youtrack.jetbrains.com/issue/KT-10368) Run Action for Kotlin Scratch Files
|
||||
- [`KT-16892`](https://youtrack.jetbrains.com/issue/KT-16892) Shortcut to navigate between header and impl
|
||||
- [`KT-23005`](https://youtrack.jetbrains.com/issue/KT-23005) Support `prefix`/`suffix` attributes for language injection in Kotlin with annotations and comments
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-19484`](https://youtrack.jetbrains.com/issue/KT-19484) KotlinBinaryClassCache retains a lot of memory
|
||||
- [`KT-23183`](https://youtrack.jetbrains.com/issue/KT-23183) `ConfigureKotlinNotification.getNotificationString()` scans modules with Kotlin files twice
|
||||
- [`KT-23380`](https://youtrack.jetbrains.com/issue/KT-23380) Improve IDE performance when working with Spring projects
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-15482`](https://youtrack.jetbrains.com/issue/KT-15482) `KotlinNullPointerException` in IDE from expected class with nested class
|
||||
- [`KT-15739`](https://youtrack.jetbrains.com/issue/KT-15739) Internal visibility across common and platform-dependent modules
|
||||
- [`KT-19025`](https://youtrack.jetbrains.com/issue/KT-19025) Not imported `build.gradle.kts` is all red
|
||||
- [`KT-19165`](https://youtrack.jetbrains.com/issue/KT-19165) IntelliJ should suggest to reload Gradle projects when `build.gradle.kts` changes
|
||||
- [`KT-20282`](https://youtrack.jetbrains.com/issue/KT-20282) 'Move statement up' works incorrectly for statement after `finally` block if `try` block contains closure
|
||||
- [`KT-20521`](https://youtrack.jetbrains.com/issue/KT-20521) Kotlin Gradle script: valid `build.gradle.kts` is red and becomes normal only after reopening the project
|
||||
- [`KT-20592`](https://youtrack.jetbrains.com/issue/KT-20592) `KotlinNullPointerException`: nested class inside expect / actual interface
|
||||
- [`KT-21013`](https://youtrack.jetbrains.com/issue/KT-21013) "Move statement up/down" fails for multiline declarations
|
||||
- [`KT-21420`](https://youtrack.jetbrains.com/issue/KT-21420) `.gradle.kts` editor should do no semantic highlighting until the first successful dependency resolver response
|
||||
- [`KT-21683`](https://youtrack.jetbrains.com/issue/KT-21683) Language injection: JPAQL. Injection should be present for "query" parameter of `@NamedNativeQueries`
|
||||
- [`KT-21745`](https://youtrack.jetbrains.com/issue/KT-21745) Warning and quickfix about kotlin-stdlib-jre7/8 -> kotlin-stdlib-jdk7/8 in Maven
|
||||
- [`KT-21746`](https://youtrack.jetbrains.com/issue/KT-21746) Warning and quickfix about kotlin-stdlib-jre7/8 -> kotlin-stdlib-jdk7/8 in Gradle
|
||||
- [`KT-21753`](https://youtrack.jetbrains.com/issue/KT-21753) Language injection: SpEL. Not injected for key in `@Caching`
|
||||
- [`KT-21771`](https://youtrack.jetbrains.com/issue/KT-21771) All annotations in `Annotations.kt` from kotlin-test-js module wrongly have ACTUAL_MISSING
|
||||
- [`KT-21831`](https://youtrack.jetbrains.com/issue/KT-21831) Opening class from `kotlin-stdlib-jdk8.jar` fails with EE: "Stub list in ... length differs from PSI"
|
||||
- [`KT-22229`](https://youtrack.jetbrains.com/issue/KT-22229) Kotlin local delegated property Import auto-removed with "Java: Optimize imports on the fly"
|
||||
- [`KT-22724`](https://youtrack.jetbrains.com/issue/KT-22724) ISE: "psiFile must not be null" at `KotlinNodeJsRunConfigurationProducer.setupConfigurationFromContext()`
|
||||
- [`KT-22817`](https://youtrack.jetbrains.com/issue/KT-22817) Hitting 'Propagate Parameters' in Change Signature throws `UnsupportedOperationException`
|
||||
- [`KT-22851`](https://youtrack.jetbrains.com/issue/KT-22851) Apply button is always active on Kotlin compiler settings tab
|
||||
- [`KT-22858`](https://youtrack.jetbrains.com/issue/KT-22858) Multiplatform: String constructor parameter is reported in Java file of jvm module on creation of a new instance of a class from common module
|
||||
- [`KT-22865`](https://youtrack.jetbrains.com/issue/KT-22865) Support multiple expectedBy dependencies when importing project from Gradle or Maven
|
||||
- [`KT-22873`](https://youtrack.jetbrains.com/issue/KT-22873) Common module-based light classes do not see JDK
|
||||
- [`KT-22874`](https://youtrack.jetbrains.com/issue/KT-22874) Exception on surround with "if else" when resulting if should be wrapped with `()`
|
||||
- [`KT-22925`](https://youtrack.jetbrains.com/issue/KT-22925) Unable to view Type Hierarchy from constructor call in expression
|
||||
- [`KT-22926`](https://youtrack.jetbrains.com/issue/KT-22926) Confusing behavior of Type Hierarchy depending on the caret position at superclass constructor
|
||||
- [`KT-23097`](https://youtrack.jetbrains.com/issue/KT-23097) Enhance multiplatform project wizard
|
||||
- [`KT-23271`](https://youtrack.jetbrains.com/issue/KT-23271) Warn about using kotlin-stdlib-jre* libs in `dependencyManagement` section in Maven with `eap` and `dev` Kotlin versions
|
||||
- [`KT-20672`](https://youtrack.jetbrains.com/issue/KT-20672) IDE can't resolve references to elements from files with `@JvmPackageName`
|
||||
- [`KT-23546`](https://youtrack.jetbrains.com/issue/KT-23546) Variable name auto-completion popup gets in the way
|
||||
- [`KT-23546`](https://youtrack.jetbrains.com/issue/KT-23546) Do not show duplicated names in variables completion list
|
||||
- [`KT-19120`](https://youtrack.jetbrains.com/issue/KT-19120) Use script compiler options on script dependencies in the IDE as well
|
||||
|
||||
### IDE. Gradle. Script
|
||||
|
||||
- [`KT-23228`](https://youtrack.jetbrains.com/issue/KT-23228) Do not highlight `.gradle.kts` files in non-Gradle projects
|
||||
|
||||
### IDE. Inspections and Intentions
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-16382`](https://youtrack.jetbrains.com/issue/KT-16382) Intention to convert `expr.unsafeCast<Type>()` to `expr as Type` and vice versa
|
||||
- [`KT-20439`](https://youtrack.jetbrains.com/issue/KT-20439) Intentions to add/remove labeled return to last expression in a lambda
|
||||
- [`KT-22011`](https://youtrack.jetbrains.com/issue/KT-22011) Inspection to report the usage of Java Collections methods on immutable Kotlin Collections
|
||||
- [`KT-22933`](https://youtrack.jetbrains.com/issue/KT-22933) Intention/inspection to convert Pair constructor to `to` function
|
||||
- [`KT-19871`](https://youtrack.jetbrains.com/issue/KT-19871) Intentions for specifying use-site targets for an annotation
|
||||
- [`KT-22971`](https://youtrack.jetbrains.com/issue/KT-22971) Inspection to highlight and remove unnecessary explicit companion object references
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-12226`](https://youtrack.jetbrains.com/issue/KT-12226) "Convert concatenation to template" does not process `$` sign as a Char
|
||||
- [`KT-15858`](https://youtrack.jetbrains.com/issue/KT-15858) "Replace with a `foreach` function call" intention breaks code
|
||||
- [`KT-16332`](https://youtrack.jetbrains.com/issue/KT-16332) Add braces to 'if' statement intention does not put end-of-line comment properly into braces
|
||||
- [`KT-17058`](https://youtrack.jetbrains.com/issue/KT-17058) "Create implementations from headers": each implementation gets own file
|
||||
- [`KT-17306`](https://youtrack.jetbrains.com/issue/KT-17306) Don't report package name mismatch if there's no Java code in the module
|
||||
- [`KT-19730`](https://youtrack.jetbrains.com/issue/KT-19730) Quickfix for delegated properties boilerplate generation doesn't work on locals
|
||||
- [`KT-21005`](https://youtrack.jetbrains.com/issue/KT-21005) "Missing KDoc inspection" is broken
|
||||
- [`KT-21082`](https://youtrack.jetbrains.com/issue/KT-21082) "Create actual declaration" of top-level subclass of expected `sealed class` in the same file as actual declaration of sealed class present
|
||||
- [`KT-22110`](https://youtrack.jetbrains.com/issue/KT-22110) "Can be joined with assignment" inspection underlining extends into comment
|
||||
- [`KT-22329`](https://youtrack.jetbrains.com/issue/KT-22329) "Create class" quickfix is not suggested in `when` branch
|
||||
- [`KT-22428`](https://youtrack.jetbrains.com/issue/KT-22428) Create member function from usage shouldn't present type parameters as options
|
||||
- [`KT-22492`](https://youtrack.jetbrains.com/issue/KT-22492) "Specify explicit lambda signature" intention is available only on lambda braces
|
||||
- [`KT-22719`](https://youtrack.jetbrains.com/issue/KT-22719) Incorrect warning 'Redundant semicolon' when having method call before lambda expression
|
||||
- [`KT-22861`](https://youtrack.jetbrains.com/issue/KT-22861) "Add annotation target" quickfix is not available on annotation with use site target
|
||||
- [`KT-22862`](https://youtrack.jetbrains.com/issue/KT-22862) "Add annotation target" quickfix does not process existent annotations with use site target
|
||||
- [`KT-22917`](https://youtrack.jetbrains.com/issue/KT-22917) Update order of containers for `create class` quickfix
|
||||
- [`KT-22949`](https://youtrack.jetbrains.com/issue/KT-22949) NPE on conversion of `run`/`apply` with explicit lambda signature to `let`/`also`
|
||||
- [`KT-22950`](https://youtrack.jetbrains.com/issue/KT-22950) Convert stdlib extension function to scoping function works incorrectly in case of explicit lambda signature
|
||||
- [`KT-22954`](https://youtrack.jetbrains.com/issue/KT-22954) "Sort modifiers" quickfix works incorrectly when method is annotated
|
||||
- [`KT-22970`](https://youtrack.jetbrains.com/issue/KT-22970) Add explicit this intention/inspection missing for lambda invocation
|
||||
- [`KT-23109`](https://youtrack.jetbrains.com/issue/KT-23109) "Remove redundant 'if' statement" inspection breaks code with labeled return
|
||||
- [`KT-23215`](https://youtrack.jetbrains.com/issue/KT-23215) "Add function to supertype" quickfix works incorrectly
|
||||
- [`KT-14270`](https://youtrack.jetbrains.com/issue/KT-14270) Intentions "Add/Remove braces" should be applied to the statement where caret is if there several nested statements one into another
|
||||
- [`KT-21743`](https://youtrack.jetbrains.com/issue/KT-21743) Method reference not correctly moved into parentheses
|
||||
- [`KT-23045`](https://youtrack.jetbrains.com/issue/KT-23045) AE “Failed to create expression from text” on concatenating string with broken quote mark char literal
|
||||
- [`KT-23046`](https://youtrack.jetbrains.com/issue/KT-23046) CCE ”KtBinaryExpression cannot be cast to KtStringTemplateExpression” on concatenating broken quote mark char literal with string
|
||||
- [`KT-23227`](https://youtrack.jetbrains.com/issue/KT-23227) "Add annotation target" quickfix is not suggested for `field:` use-site target
|
||||
|
||||
### IDE. Refactorings
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-13255`](https://youtrack.jetbrains.com/issue/KT-13255) Refactor / Rename: renaming local variable or class to existing name gives no warning
|
||||
- [`KT-13284`](https://youtrack.jetbrains.com/issue/KT-13284) Refactor / Rename: superfluous imports and FQNs in Java using `@JvmOverloads` functions
|
||||
- [`KT-13907`](https://youtrack.jetbrains.com/issue/KT-13907) Rename refactoring warns about name conflict if there is function with different signature but the same name
|
||||
- [`KT-13986`](https://youtrack.jetbrains.com/issue/KT-13986) Full qualified names of classes in comments should be changed after class Move, if comment contains backquotes
|
||||
- [`KT-14671`](https://youtrack.jetbrains.com/issue/KT-14671) `typealias`: refactor/rename should propose to rename occurrences in comments
|
||||
- [`KT-15039`](https://youtrack.jetbrains.com/issue/KT-15039) Extra usage is found for a parameter in data class in destructuring construction
|
||||
- [`KT-15228`](https://youtrack.jetbrains.com/issue/KT-15228) Extract function from inline function should create public function
|
||||
- [`KT-15302`](https://youtrack.jetbrains.com/issue/KT-15302) Reference to typealias in SAM conversion is not found
|
||||
- [`KT-16510`](https://youtrack.jetbrains.com/issue/KT-16510) Can't rename quoted identifier `is`
|
||||
- [`KT-17827`](https://youtrack.jetbrains.com/issue/KT-17827) Refactor / Move corrupts bound references when containing class of member element is changed
|
||||
- [`KT-19561`](https://youtrack.jetbrains.com/issue/KT-19561) Name conflict warning when renaming method to a name matching an extension method with the same name exists
|
||||
- [`KT-20178`](https://youtrack.jetbrains.com/issue/KT-20178) Refactor → Rename can't make companion object name empty
|
||||
- [`KT-22282`](https://youtrack.jetbrains.com/issue/KT-22282) Moving a Kotlin file to another package does not change imports in itself
|
||||
- [`KT-22482`](https://youtrack.jetbrains.com/issue/KT-22482) Rename refactoring insert qualifier for non related property call
|
||||
- [`KT-22661`](https://youtrack.jetbrains.com/issue/KT-22661) Refactor/Move: top level field reference is not imported automatically after move to the source root
|
||||
- [`KT-22678`](https://youtrack.jetbrains.com/issue/KT-22678) Refactor / Copy: "Class uses constructor which will be inaccessible after move" when derived class has a protected constructor
|
||||
- [`KT-22692`](https://youtrack.jetbrains.com/issue/KT-22692) Refactor/Move: unnecessary curly braces added on moving to a separate file a top level function with a top level field usage
|
||||
- [`KT-22745`](https://youtrack.jetbrains.com/issue/KT-22745) Refactor/Move inserts FQ function name at the call site if there is a field same named as the function
|
||||
- [`KT-22747`](https://youtrack.jetbrains.com/issue/KT-22747) Moving top-level function to a different (existing) file doesn't update references from Java
|
||||
- [`KT-22751`](https://youtrack.jetbrains.com/issue/KT-22751) Refactor/Rename: type alias name clash is not reported
|
||||
- [`KT-22769`](https://youtrack.jetbrains.com/issue/KT-22769) Refactor/Move: there is no warning on moving sealed class or its inheritors to another file
|
||||
- [`KT-22771`](https://youtrack.jetbrains.com/issue/KT-22771) Refactor/Move: there is no warning on moving nested class to another class with stricter visibility
|
||||
- [`KT-22812`](https://youtrack.jetbrains.com/issue/KT-22812) Refactor/Rename extension functions incorrectly conflicts with other extension functions
|
||||
- [`KT-23065`](https://youtrack.jetbrains.com/issue/KT-23065) Refactor/Move: Specify the warning message on moving sealed class inheritors without moving the sealed class itself
|
||||
|
||||
### IDE. Script
|
||||
|
||||
- [`KT-22647`](https://youtrack.jetbrains.com/issue/KT-22647) Run script Action in IDE should use Kotlin compiler from the IDE plugin
|
||||
- [`KT-18930`](https://youtrack.jetbrains.com/issue/KT-18930) IDEA is unstable With Gradle Kotlin DSL
|
||||
- [`KT-21042`](https://youtrack.jetbrains.com/issue/KT-21042) Gradle Script Kotlin project is full-red
|
||||
- [`KT-11618`](https://youtrack.jetbrains.com/issue/KT-11618) Running .kts file from IntelliJ IDEA doesn't allow to import classes in other files which are also part of the project
|
||||
|
||||
|
||||
### IDE. Debugger
|
||||
|
||||
- [`KT-22205`](https://youtrack.jetbrains.com/issue/KT-22205) Breakpoints won't work for Kotlin testing with JUnit
|
||||
|
||||
### JavaScript
|
||||
|
||||
- [`KT-22019`](https://youtrack.jetbrains.com/issue/KT-22019) Fix wrong list sorting order
|
||||
|
||||
### Tools. CLI
|
||||
|
||||
- [`KT-22777`](https://youtrack.jetbrains.com/issue/KT-22777) Unstable language version setting has no effect when attached runtime has lower version
|
||||
|
||||
### Tools. Gradle
|
||||
|
||||
- [`KT-22824`](https://youtrack.jetbrains.com/issue/KT-22824) `expectedBy` dependency should be expressed as `compile` dependency in POM
|
||||
- [`KT-15371`](https://youtrack.jetbrains.com/issue/KT-15371) Multiplatform: setting free compiler args can break build
|
||||
- [`KT-22864`](https://youtrack.jetbrains.com/issue/KT-22864) Allow multiple expectedBy configuration dependencies in Gradle
|
||||
- [`KT-22895`](https://youtrack.jetbrains.com/issue/KT-22895) 'kotlin-runtime' library is missing in the compiler classpath sometimes
|
||||
- [`KT-23085`](https://youtrack.jetbrains.com/issue/KT-23085) Use proper names for the Gradle task inputs/outputs added at runtime
|
||||
- [`KT-23694`](https://youtrack.jetbrains.com/issue/KT-23694) Fix parallel build in Kotlin IC – invalid KotlinCoreEnvironment disposal
|
||||
|
||||
### Tools. Android
|
||||
- Android Extensions: Support fragments from kotlinx package;
|
||||
|
||||
### Tools. Incremental Compile
|
||||
|
||||
- [`KT-20516`](https://youtrack.jetbrains.com/issue/KT-20516) "Unresolved reference" when project declares same class as its dependency
|
||||
- [`KT-22542`](https://youtrack.jetbrains.com/issue/KT-22542) "Source file or directory not found" for incremental compilation with Kobalt
|
||||
- [`KT-23165`](https://youtrack.jetbrains.com/issue/KT-23165) Incremental compilation is sometimes broken after moving one class
|
||||
|
||||
### Tools. JPS
|
||||
|
||||
- [`KT-16091`](https://youtrack.jetbrains.com/issue/KT-16091) Incremental compilation ignores changes in Java static field
|
||||
- [`KT-22995`](https://youtrack.jetbrains.com/issue/KT-22995) EA-91869 - NA: `LookupStorage.<init>`
|
||||
|
||||
### Tools. kapt
|
||||
|
||||
- [`KT-21735`](https://youtrack.jetbrains.com/issue/KT-21735) Kapt cache was not cleared sometimes
|
||||
|
||||
### Tools. REPL
|
||||
|
||||
- [`KT-21611`](https://youtrack.jetbrains.com/issue/KT-21611) REPL: Empty lines should be ignored
|
||||
|
||||
## 1.2.30
|
||||
|
||||
### Android
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.io.File
|
||||
|
||||
internal class FileToIdMap(file: File) : BasicMap<File, Int>(file, FileKeyDescriptor, IntExternalizer) {
|
||||
@@ -34,5 +33,12 @@ internal class FileToIdMap(file: File) : BasicMap<File, Int>(file, FileKeyDescri
|
||||
storage.remove(file)
|
||||
}
|
||||
|
||||
fun toMap(): Map<File, Int> = storage.keys.keysToMap { storage[it]!! }
|
||||
fun toMap(): Map<File, Int> {
|
||||
val result = HashMap<File, Int>()
|
||||
for (key in storage.keys) {
|
||||
val value = storage[key] ?: continue
|
||||
result[key] = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import proguard.gradle.ProGuardTask
|
||||
buildscript {
|
||||
extra["defaultSnapshotVersion"] = "1.2-SNAPSHOT"
|
||||
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.50-dev-880", onlySuccessBootstrap = false))
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.51-eap-115", projectExtId = "Kotlin_1250_Compiler", onlySuccessBootstrap = false))
|
||||
|
||||
val mirrorRepo: String? = findProperty("maven.repository.mirror")?.toString()
|
||||
|
||||
@@ -22,7 +22,7 @@ buildscript {
|
||||
"https://jcenter.bintray.com/",
|
||||
"https://plugins.gradle.org/m2",
|
||||
"http://dl.bintray.com/kotlin/kotlinx",
|
||||
"https://repo.gradle.org/gradle/libs-releases-local", // for native-platform
|
||||
"https://repo.gradle.org/gradle/ext-releases-local", // for native-platform
|
||||
"https://jetbrains.bintray.com/intellij-third-party-dependencies", // for jflex
|
||||
"https://dl.bintray.com/jetbrains/markdown" // for org.jetbrains:markdown
|
||||
)
|
||||
@@ -48,6 +48,15 @@ plugins {
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
pill {
|
||||
excludedDirs(
|
||||
"out",
|
||||
"buildSrc/build",
|
||||
"buildSrc/prepare-deps/android-dx/build",
|
||||
"buildSrc/prepare-deps/intellij-sdk/build"
|
||||
)
|
||||
}
|
||||
|
||||
buildScan {
|
||||
setTermsOfServiceUrl("https://gradle.com/terms-of-service")
|
||||
setTermsOfServiceAgree("yes")
|
||||
@@ -223,6 +232,7 @@ val coreLibProjects = listOf(
|
||||
":kotlin-test:kotlin-test-common",
|
||||
":kotlin-test:kotlin-test-jvm",
|
||||
":kotlin-test:kotlin-test-junit",
|
||||
":kotlin-test:kotlin-test-junit5",
|
||||
":kotlin-test:kotlin-test-testng",
|
||||
":kotlin-test:kotlin-test-js",
|
||||
":kotlin-reflect"
|
||||
@@ -565,28 +575,13 @@ val zipPlugin by task<Zip> {
|
||||
val cidrPlugin by task<Copy> {
|
||||
dependsOn(ideaPlugin)
|
||||
into(cidrPluginDir)
|
||||
from(ideaPluginDir) {
|
||||
exclude("lib/kotlin-plugin.jar")
|
||||
|
||||
exclude("lib/uast-kotlin.jar")
|
||||
exclude("lib/uast-kotlin-ide.jar")
|
||||
exclude("lib/android-ide.jar")
|
||||
exclude("lib/android-output-parser-ide.jar")
|
||||
exclude("lib/android-extensions-ide.jar")
|
||||
exclude("lib/android-extensions-compiler.jar")
|
||||
exclude("lib/kapt3-idea.jar")
|
||||
exclude("lib/j2k.jar")
|
||||
exclude("lib/jps-ide.jar")
|
||||
exclude("lib/jps/**")
|
||||
exclude("kotlinc/**")
|
||||
exclude("lib/maven-ide.jar")
|
||||
}
|
||||
from(ideaPluginDir) { exclude("lib/kotlin-plugin.jar") }
|
||||
from(cidrKotlinPlugin) { into("lib") }
|
||||
}
|
||||
|
||||
val zipCidrPlugin by task<Zip> {
|
||||
val destPath = project.findProperty("pluginZipPath") as String?
|
||||
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR.zip"
|
||||
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR"
|
||||
val destFile = File(destPath)
|
||||
|
||||
destinationDir = destFile.parentFile
|
||||
|
||||
@@ -12,7 +12,7 @@ import proguard.gradle.ProGuardTask
|
||||
buildscript {
|
||||
extra["defaultSnapshotVersion"] = "1.2-SNAPSHOT"
|
||||
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.50-dev-880", onlySuccessBootstrap = false))
|
||||
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.50-eap-85", projectExtId = "Kotlin_1250_Compiler", onlySuccessBootstrap = false))
|
||||
|
||||
val mirrorRepo: String? = findProperty("maven.repository.mirror")?.toString()
|
||||
|
||||
@@ -22,7 +22,7 @@ buildscript {
|
||||
"https://jcenter.bintray.com/",
|
||||
"https://plugins.gradle.org/m2",
|
||||
"http://dl.bintray.com/kotlin/kotlinx",
|
||||
"https://repo.gradle.org/gradle/libs-releases-local", // for native-platform
|
||||
"https://repo.gradle.org/gradle/ext-releases-local", // for native-platform
|
||||
"https://jetbrains.bintray.com/intellij-third-party-dependencies", // for jflex
|
||||
"https://dl.bintray.com/jetbrains/markdown" // for org.jetbrains:markdown
|
||||
)
|
||||
@@ -48,6 +48,15 @@ plugins {
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
pill {
|
||||
excludedDirs(
|
||||
"out",
|
||||
"buildSrc/build",
|
||||
"buildSrc/prepare-deps/android-dx/build",
|
||||
"buildSrc/prepare-deps/intellij-sdk/build"
|
||||
)
|
||||
}
|
||||
|
||||
buildScan {
|
||||
setTermsOfServiceUrl("https://gradle.com/terms-of-service")
|
||||
setTermsOfServiceAgree("yes")
|
||||
@@ -222,6 +231,7 @@ val coreLibProjects = listOf(
|
||||
":kotlin-test:kotlin-test-common",
|
||||
":kotlin-test:kotlin-test-jvm",
|
||||
":kotlin-test:kotlin-test-junit",
|
||||
":kotlin-test:kotlin-test-junit5",
|
||||
":kotlin-test:kotlin-test-testng",
|
||||
":kotlin-test:kotlin-test-js",
|
||||
":kotlin-reflect"
|
||||
@@ -564,28 +574,13 @@ val zipPlugin by task<Zip> {
|
||||
val cidrPlugin by task<Copy> {
|
||||
dependsOn(ideaPlugin)
|
||||
into(cidrPluginDir)
|
||||
from(ideaPluginDir) {
|
||||
exclude("lib/kotlin-plugin.jar")
|
||||
|
||||
exclude("lib/uast-kotlin.jar")
|
||||
exclude("lib/uast-kotlin-ide.jar")
|
||||
exclude("lib/android-ide.jar")
|
||||
exclude("lib/android-output-parser-ide.jar")
|
||||
exclude("lib/android-extensions-ide.jar")
|
||||
exclude("lib/android-extensions-compiler.jar")
|
||||
exclude("lib/kapt3-idea.jar")
|
||||
exclude("lib/j2k.jar")
|
||||
exclude("lib/jps-ide.jar")
|
||||
exclude("lib/jps/**")
|
||||
exclude("kotlinc/**")
|
||||
exclude("lib/maven-ide.jar")
|
||||
}
|
||||
from(ideaPluginDir) { exclude("lib/kotlin-plugin.jar") }
|
||||
from(cidrKotlinPlugin) { into("lib") }
|
||||
}
|
||||
|
||||
val zipCidrPlugin by task<Zip> {
|
||||
val destPath = project.findProperty("pluginZipPath") as String?
|
||||
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR.zip"
|
||||
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR"
|
||||
val destFile = File(destPath)
|
||||
|
||||
destinationDir = destFile.parentFile
|
||||
|
||||
@@ -33,9 +33,9 @@ plugins {
|
||||
|
||||
gradlePlugin {
|
||||
(plugins) {
|
||||
"jps-compatible-base" {
|
||||
id = "jps-compatible-base"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatibleBasePlugin"
|
||||
"pill-configurable" {
|
||||
id = "pill-configurable"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin"
|
||||
}
|
||||
"jps-compatible" {
|
||||
id = "jps-compatible"
|
||||
@@ -68,7 +68,7 @@ repositories {
|
||||
extra["buildSrcKotlinRepo"]?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
maven(url = "https://repo.gradle.org/gradle/libs-releases-local") // for native-platform
|
||||
maven(url = "https://repo.gradle.org/gradle/ext-releases-local") // for native-platform
|
||||
jcenter()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
|
||||
buildscript {
|
||||
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
|
||||
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
|
||||
extra["versions.shadow"] = "2.0.2"
|
||||
extra["versions.native-platform"] = "0.14"
|
||||
|
||||
repositories {
|
||||
buildSrcKotlinRepo?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$buildSrcKotlinVersion")
|
||||
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:$buildSrcKotlinVersion")
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("buildSrcKotlinVersion: " + extra["buildSrcKotlinVersion"])
|
||||
logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
|
||||
logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT)
|
||||
|
||||
apply {
|
||||
plugin("kotlin")
|
||||
plugin("kotlin-sam-with-receiver")
|
||||
}
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
`java-gradle-plugin`
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
(plugins) {
|
||||
"jps-compatible-base" {
|
||||
id = "jps-compatible-base"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatibleBasePlugin"
|
||||
}
|
||||
"jps-compatible" {
|
||||
id = "jps-compatible"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
val v = it.toString()
|
||||
if (v.isBlank()) true
|
||||
else v.toBoolean()
|
||||
}
|
||||
|
||||
rootProject.apply {
|
||||
from(rootProject.file("../versions.gradle.kts"))
|
||||
}
|
||||
|
||||
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
|
||||
val intellijUltimateEnabled by extra(project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild)
|
||||
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
|
||||
|
||||
extra["intellijRepo"] = "https://www.jetbrains.com/intellij-repository"
|
||||
extra["intellijReleaseType"] = "snapshots" // or "snapshots"
|
||||
extra["versions.androidDxSources"] = "5.0.0_r2"
|
||||
|
||||
extra["customDepsOrg"] = "kotlin.build.custom.deps"
|
||||
|
||||
repositories {
|
||||
extra["buildSrcKotlinRepo"]?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
maven(url = "https://repo.gradle.org/gradle/libs-releases-local") // for native-platform
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
|
||||
compile("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
|
||||
compile("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
|
||||
compile("com.jakewharton.dex:dex-method-list:3.0.0")
|
||||
// TODO: adding the dep to the plugin breaks the build unexpectedly, resolve and uncomment
|
||||
// compile("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.extra["bootstrap_kotlin_version"]}")
|
||||
// Shadow plugin is used in many projects of the main build. Once it's no longer used in buildSrc, please move this dependency to the root project
|
||||
compile("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}")
|
||||
compile("org.ow2.asm:asm-all:6.0_BETA")
|
||||
}
|
||||
|
||||
samWithReceiver {
|
||||
annotation("org.gradle.api.HasImplicitReceiver")
|
||||
}
|
||||
|
||||
fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit =
|
||||
extensions.configure("samWithReceiver", configure)
|
||||
|
||||
tasks["build"].dependsOn(":prepare-deps:android-dx:build", ":prepare-deps:intellij-sdk:build")
|
||||
@@ -12,4 +12,4 @@ class DependencyMapper(
|
||||
|
||||
class MappedDependency(val main: PDependency, val deferred: List<PDependency> = emptyList())
|
||||
|
||||
class ParserContext(val dependencyMappers: List<DependencyMapper>)
|
||||
class ParserContext(val dependencyMappers: List<DependencyMapper>, val variant: PillExtension.Variant)
|
||||
39
buildSrc/src/main/kotlin/pill/extension.kt
Normal file
39
buildSrc/src/main/kotlin/pill/extension.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.pill
|
||||
|
||||
import java.io.File
|
||||
import org.gradle.api.Project
|
||||
|
||||
open class PillExtension {
|
||||
enum class Variant {
|
||||
// Default variant (./gradlew pill)
|
||||
BASE() { override val includes = setOf(BASE) },
|
||||
|
||||
// Full variant (./gradlew pill -Dpill.variant=full)
|
||||
FULL() { override val includes = setOf(BASE, FULL) },
|
||||
|
||||
// Do not import the project to JPS model, but set some options for it
|
||||
NONE() { override val includes = emptySet<Variant>() },
|
||||
|
||||
// 'BASE' if the "jps-compatible" plugin is applied, 'NONE' otherwise
|
||||
DEFAULT() { override val includes = emptySet<Variant>() };
|
||||
|
||||
abstract val includes: Set<Variant>
|
||||
}
|
||||
|
||||
open var variant: Variant = Variant.DEFAULT
|
||||
|
||||
open var importAsLibrary: Boolean = false
|
||||
|
||||
open var excludedDirs: List<File> = emptyList()
|
||||
|
||||
fun Project.excludedDirs(vararg dirs: String) {
|
||||
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
|
||||
}
|
||||
|
||||
open var libraryPath: File? = null
|
||||
set(v) {
|
||||
importAsLibrary = true
|
||||
field = v
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,10 @@ fun generateKotlinPluginArtifactFile(rootProject: Project): PFile {
|
||||
.findByName(EmbeddedComponents.CONFIGURATION_NAME)?.resolvedConfiguration
|
||||
|
||||
if (embeddedComponents != null) {
|
||||
for ((_, _, dependency) in listOf(embeddedComponents to Scope.COMPILE).collectDependencies()) {
|
||||
val configuration = CollectedConfiguration(embeddedComponents, Scope.COMPILE)
|
||||
for (dependencyInfo in listOf(configuration).collectDependencies()) {
|
||||
val dependency = (dependencyInfo as? DependencyInfo.ResolvedDependencyInfo)?.dependency ?: continue
|
||||
|
||||
if (dependency.configuration == "runtimeElements") {
|
||||
archiveForJar.add(ModuleOutput(dependency.moduleName + ".src"))
|
||||
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.pill
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
@@ -11,6 +12,7 @@ import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.internal.HasConvention
|
||||
import org.jetbrains.kotlin.pill.POrderRoot.*
|
||||
import org.jetbrains.kotlin.pill.PSourceRoot.*
|
||||
import org.jetbrains.kotlin.pill.PillExtension.*
|
||||
import java.io.File
|
||||
import java.util.LinkedList
|
||||
|
||||
@@ -41,13 +43,34 @@ data class PContentRoot(
|
||||
|
||||
data class PSourceRoot(
|
||||
val path: File,
|
||||
val kind: Kind
|
||||
val kind: Kind,
|
||||
val kotlinOptions: PSourceRootKotlinOptions?
|
||||
) {
|
||||
enum class Kind {
|
||||
PRODUCTION, TEST, RESOURCES, TEST_RESOURCES;
|
||||
enum class Kind { PRODUCTION, TEST, RESOURCES, TEST_RESOURCES }
|
||||
}
|
||||
|
||||
val isResources get() = this == RESOURCES || this == TEST_RESOURCES
|
||||
}
|
||||
data class PSourceRootKotlinOptions(
|
||||
val noStdlib: Boolean?,
|
||||
val noReflect: Boolean?,
|
||||
val moduleName: String?,
|
||||
val apiVersion: String?,
|
||||
val languageVersion: String?,
|
||||
val jvmTarget: String?,
|
||||
val addCompilerBuiltIns: Boolean?,
|
||||
val loadBuiltInsFromDependencies: Boolean?,
|
||||
val extraArguments: List<String>
|
||||
) {
|
||||
fun intersect(other: PSourceRootKotlinOptions) = PSourceRootKotlinOptions(
|
||||
if (noStdlib == other.noStdlib) noStdlib else null,
|
||||
if (noReflect == other.noReflect) noReflect else null,
|
||||
if (moduleName == other.moduleName) moduleName else null,
|
||||
if (apiVersion == other.apiVersion) apiVersion else null,
|
||||
if (languageVersion == other.languageVersion) languageVersion else null,
|
||||
if (jvmTarget == other.jvmTarget) jvmTarget else null,
|
||||
if (addCompilerBuiltIns == other.addCompilerBuiltIns) addCompilerBuiltIns else null,
|
||||
if (loadBuiltInsFromDependencies == other.loadBuiltInsFromDependencies) loadBuiltInsFromDependencies else null,
|
||||
extraArguments.intersect(other.extraArguments).toList()
|
||||
)
|
||||
}
|
||||
|
||||
data class POrderRoot(
|
||||
@@ -83,9 +106,16 @@ fun parse(project: Project, libraries: List<PLibrary>, context: ParserContext):
|
||||
error("$project is not a root project")
|
||||
}
|
||||
|
||||
val modules = project.allprojects
|
||||
.filter { it.plugins.hasPlugin(JpsCompatiblePlugin::class.java) }
|
||||
.flatMap { parseModules(it) }
|
||||
fun Project.matchesSelectedVariant(): Boolean {
|
||||
val extension = this.extensions.findByType(PillExtension::class.java) ?: return true
|
||||
val projectVariant = extension.variant.takeUnless { it == Variant.DEFAULT } ?: Variant.BASE
|
||||
return projectVariant in context.variant.includes
|
||||
}
|
||||
|
||||
val (includedProjects, excludedProjects) = project.allprojects
|
||||
.partition { it.plugins.hasPlugin(JpsCompatiblePlugin::class.java) && it.matchesSelectedVariant() }
|
||||
|
||||
val modules = includedProjects.flatMap { parseModules(it, excludedProjects) }
|
||||
|
||||
return PProject("Kotlin", project.projectDir, modules, libraries)
|
||||
}
|
||||
@@ -108,12 +138,7 @@ private val TEST_CONFIGURATION_MAPPING = mapOf(
|
||||
listOf("jpsTest") to Scope.TEST
|
||||
)
|
||||
|
||||
private val SOURCE_SET_MAPPING = mapOf(
|
||||
"main" to Kind.PRODUCTION,
|
||||
"test" to Kind.TEST
|
||||
)
|
||||
|
||||
private fun ParserContext.parseModules(project: Project): List<PModule> {
|
||||
private fun ParserContext.parseModules(project: Project, excludedProjects: List<Project>): List<PModule> {
|
||||
val (productionContentRoots, testContentRoots) = parseContentRoots(project).partition { !it.forTests }
|
||||
|
||||
val modules = mutableListOf<PModule>()
|
||||
@@ -121,7 +146,10 @@ private fun ParserContext.parseModules(project: Project): List<PModule> {
|
||||
fun getJavaExcludedDirs() = project.plugins.findPlugin(IdeaPlugin::class.java)
|
||||
?.model?.module?.excludeDirs?.toList() ?: emptyList()
|
||||
|
||||
val allExcludedDirs = getJavaExcludedDirs() + project.buildDir
|
||||
fun getPillExcludedDirs() = project.extensions.getByType(PillExtension::class.java).excludedDirs
|
||||
|
||||
val allExcludedDirs = getPillExcludedDirs() + getJavaExcludedDirs() + project.buildDir +
|
||||
(if (project == project.rootProject) excludedProjects.map { it.buildDir } else emptyList())
|
||||
|
||||
var productionSourcesModule: PModule? = null
|
||||
|
||||
@@ -162,8 +190,8 @@ private fun ParserContext.parseModules(project: Project): List<PModule> {
|
||||
}
|
||||
}
|
||||
|
||||
val mainModuleFileRelativePath = when {
|
||||
project == project.rootProject -> File(project.rootProject.projectDir, project.name + ".iml")
|
||||
val mainModuleFileRelativePath = when (project) {
|
||||
project.rootProject -> File(project.rootProject.projectDir, project.name + ".iml")
|
||||
else -> getModuleFile()
|
||||
}
|
||||
|
||||
@@ -199,55 +227,97 @@ private fun parseSourceRoots(project: Project): List<PSourceRoot> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val kotlinTasksBySourceSet = project.tasks
|
||||
.filter { it.name.startsWith("compile") && it.name.endsWith("Kotlin") }
|
||||
.associateBy { it.invokeInternal("getSourceSetName") }
|
||||
|
||||
val sourceRoots = mutableListOf<PSourceRoot>()
|
||||
|
||||
project.configure<JavaPluginConvention> {
|
||||
for ((sourceSetName, kind) in SOURCE_SET_MAPPING) {
|
||||
val sourceSet = sourceSets.findByName(sourceSetName) ?: continue
|
||||
for (sourceSet in project.sourceSets) {
|
||||
val kotlinCompileTask = kotlinTasksBySourceSet[sourceSet.name]
|
||||
val kind = if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME) Kind.TEST else Kind.PRODUCTION
|
||||
|
||||
fun Any.getKotlin(): SourceDirectorySet {
|
||||
val kotlinMethod = javaClass.getMethod("getKotlin")
|
||||
val oldIsAccessible = kotlinMethod.isAccessible
|
||||
try {
|
||||
kotlinMethod.isAccessible = true
|
||||
return kotlinMethod(this) as SourceDirectorySet
|
||||
} finally {
|
||||
kotlinMethod.isAccessible = oldIsAccessible
|
||||
}
|
||||
fun Any.getKotlin(): SourceDirectorySet {
|
||||
val kotlinMethod = javaClass.getMethod("getKotlin")
|
||||
val oldIsAccessible = kotlinMethod.isAccessible
|
||||
try {
|
||||
kotlinMethod.isAccessible = true
|
||||
return kotlinMethod(this) as SourceDirectorySet
|
||||
} finally {
|
||||
kotlinMethod.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinSourceDirectories = (sourceSet as HasConvention).convention
|
||||
.plugins["kotlin"]?.getKotlin()?.srcDirs
|
||||
?: emptySet()
|
||||
|
||||
val directories = (sourceSet.java.sourceDirectories.files + kotlinSourceDirectories).toList()
|
||||
.filter { it.exists() }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: continue
|
||||
|
||||
val kotlinOptions = kotlinCompileTask?.let { getKotlinOptions(it) }
|
||||
|
||||
for (resourceRoot in sourceSet.resources.sourceDirectories.files) {
|
||||
if (!resourceRoot.exists() || resourceRoot in directories) {
|
||||
continue
|
||||
}
|
||||
|
||||
val kotlinSourceDirectories = (sourceSet as HasConvention).convention
|
||||
.plugins["kotlin"]?.getKotlin()?.srcDirs
|
||||
?: emptySet()
|
||||
|
||||
val directories = (sourceSet.java.sourceDirectories.files + kotlinSourceDirectories).toList()
|
||||
.filter { it.exists() }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?: continue
|
||||
|
||||
for (resourceRoot in sourceSet.resources.sourceDirectories.files) {
|
||||
if (!resourceRoot.exists() || resourceRoot in directories) {
|
||||
continue
|
||||
}
|
||||
|
||||
val resourceRootKind = when (kind) {
|
||||
Kind.PRODUCTION -> Kind.RESOURCES
|
||||
Kind.TEST -> Kind.TEST_RESOURCES
|
||||
else -> error("Invalid source root kind $kind")
|
||||
}
|
||||
|
||||
sourceRoots += PSourceRoot(resourceRoot, resourceRootKind)
|
||||
val resourceRootKind = when (kind) {
|
||||
Kind.PRODUCTION -> Kind.RESOURCES
|
||||
Kind.TEST -> Kind.TEST_RESOURCES
|
||||
else -> error("Invalid source root kind $kind")
|
||||
}
|
||||
|
||||
for (directory in directories) {
|
||||
sourceRoots += PSourceRoot(directory, kind)
|
||||
}
|
||||
sourceRoots += PSourceRoot(resourceRoot, resourceRootKind, kotlinOptions)
|
||||
}
|
||||
|
||||
for (directory in directories) {
|
||||
sourceRoots += PSourceRoot(directory, kind, kotlinOptions)
|
||||
}
|
||||
}
|
||||
|
||||
return sourceRoots
|
||||
}
|
||||
|
||||
private fun getKotlinOptions(kotlinCompileTask: Any): PSourceRootKotlinOptions? {
|
||||
val compileArguments = kotlinCompileTask.invokeInternal("getSerializedCompilerArguments") as List<String>
|
||||
fun parseBoolean(name: String) = compileArguments.contains("-$name")
|
||||
fun parseString(name: String) = compileArguments.dropWhile { it != "-$name" }.drop(1).firstOrNull()
|
||||
|
||||
val addCompilerBuiltins = "Xadd-compiler-builtins"
|
||||
val loadBuiltinsFromDependencies = "Xload-builtins-from-dependencies"
|
||||
|
||||
val extraArguments = compileArguments.filter {
|
||||
it.startsWith("-X") && it != "-$addCompilerBuiltins" && it != "-$loadBuiltinsFromDependencies"
|
||||
}
|
||||
|
||||
return PSourceRootKotlinOptions(
|
||||
parseBoolean("no-stdlib"),
|
||||
parseBoolean("no-reflect"),
|
||||
parseString("module-name"),
|
||||
parseString("api-version"),
|
||||
parseString("language-version"),
|
||||
parseString("jvm-target"),
|
||||
parseBoolean(addCompilerBuiltins),
|
||||
parseBoolean(loadBuiltinsFromDependencies),
|
||||
extraArguments
|
||||
)
|
||||
}
|
||||
|
||||
private fun Any.invokeInternal(name: String, instance: Any = this): Any? {
|
||||
val method = javaClass.methods.single { it.name.startsWith(name) && it.parameterTypes.isEmpty() }
|
||||
|
||||
val oldIsAccessible = method.isAccessible
|
||||
try {
|
||||
method.isAccessible = true
|
||||
return method.invoke(instance)
|
||||
} finally {
|
||||
method.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
private fun ParserContext.parseDependencies(project: Project, forTests: Boolean): List<POrderRoot> {
|
||||
val configurationMapping = if (forTests) TEST_CONFIGURATION_MAPPING else CONFIGURATION_MAPPING
|
||||
|
||||
@@ -255,20 +325,34 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
val mainRoots = mutableListOf<POrderRoot>()
|
||||
val deferredRoots = mutableListOf<POrderRoot>()
|
||||
|
||||
fun collectConfigurations(): List<Pair<ResolvedConfiguration, Scope>> {
|
||||
val configurations = mutableListOf<Pair<ResolvedConfiguration, Scope>>()
|
||||
fun collectConfigurations(): List<CollectedConfiguration> {
|
||||
val configurations = mutableListOf<CollectedConfiguration>()
|
||||
|
||||
for ((configurationNames, scope) in configurationMapping) {
|
||||
for (configurationName in configurationNames) {
|
||||
val configuration = findByName(configurationName)?.also { it.resolve() } ?: continue
|
||||
configurations += Pair(configuration.resolvedConfiguration, scope)
|
||||
|
||||
val extraDependencies = resolveExtraDependencies(configuration)
|
||||
configurations += CollectedConfiguration(configuration.resolvedConfiguration, scope, extraDependencies)
|
||||
}
|
||||
}
|
||||
|
||||
return configurations
|
||||
}
|
||||
|
||||
nextDependency@ for ((configuration, scope, dependency) in collectConfigurations().collectDependencies()) {
|
||||
nextDependency@ for (dependencyInfo in collectConfigurations().collectDependencies()) {
|
||||
val scope = dependencyInfo.scope
|
||||
|
||||
if (dependencyInfo is DependencyInfo.CustomDependencyInfo) {
|
||||
val files = dependencyInfo.files
|
||||
val library = PLibrary(files.firstOrNull()?.nameWithoutExtension ?: "unnamed", classes = files)
|
||||
|
||||
mainRoots += POrderRoot(PDependency.ModuleLibrary(library), scope)
|
||||
continue
|
||||
}
|
||||
|
||||
val dependency = (dependencyInfo as DependencyInfo.ResolvedDependencyInfo).dependency
|
||||
|
||||
for (mapper in dependencyMappers) {
|
||||
if (dependency.moduleGroup == mapper.group
|
||||
&& dependency.moduleName == mapper.module
|
||||
@@ -277,12 +361,7 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
val mappedDependency = mapper.mapping(dependency)
|
||||
|
||||
if (mappedDependency != null) {
|
||||
val orderRoot = POrderRoot(mappedDependency.main, scope)
|
||||
if (mappedDependency.main is PDependency.Module) {
|
||||
mainRoots += orderRoot
|
||||
} else {
|
||||
mainRoots += orderRoot
|
||||
}
|
||||
mainRoots += POrderRoot(mappedDependency.main, scope)
|
||||
|
||||
for (deferredDep in mappedDependency.deferred) {
|
||||
deferredRoots += POrderRoot(deferredDep, scope)
|
||||
@@ -293,10 +372,10 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
if (dependency.configuration == "runtimeElements" && scope != Scope.TEST) {
|
||||
mainRoots += POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope)
|
||||
mainRoots += if (dependency.configuration == "runtimeElements" && scope != Scope.TEST) {
|
||||
POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope)
|
||||
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
|
||||
mainRoots += POrderRoot(
|
||||
POrderRoot(
|
||||
PDependency.Module(dependency.moduleName + ".test"),
|
||||
scope,
|
||||
isProductionOnTestDependency = true
|
||||
@@ -304,7 +383,7 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
} else {
|
||||
val classes = dependency.moduleArtifacts.map { it.file }
|
||||
val library = PLibrary(dependency.moduleName, classes)
|
||||
mainRoots += POrderRoot(PDependency.ModuleLibrary(library), scope)
|
||||
POrderRoot(PDependency.ModuleLibrary(library), scope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,9 +391,23 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveExtraDependencies(configuration: Configuration): List<File> {
|
||||
return configuration.dependencies
|
||||
.filterIsInstance<SelfResolvingDependency>()
|
||||
.map { it.resolve() }
|
||||
.filter { isGradleApiDependency(it) }
|
||||
.flatMap { it }
|
||||
}
|
||||
|
||||
private fun isGradleApiDependency(files: Iterable<File>): Boolean {
|
||||
return listOf("gradle-api", "groovy-all").all { dep ->
|
||||
files.any { it.extension == "jar" && it.name.startsWith("$dep-") }
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
|
||||
val dependenciesByScope = roots.groupBy { it.scope }.mapValues { it.value.mapTo(mutableSetOf()) { it.dependency } }
|
||||
fun depenciesFor(scope: Scope) = dependenciesByScope[scope] ?: emptySet<PDependency>()
|
||||
fun dependenciesFor(scope: Scope) = dependenciesByScope[scope] ?: emptySet<PDependency>()
|
||||
|
||||
val result = mutableSetOf<POrderRoot>()
|
||||
for (root in roots.distinct()) {
|
||||
@@ -325,16 +418,16 @@ private fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
|
||||
continue
|
||||
}
|
||||
|
||||
if ((scope == Scope.PROVIDED || scope == Scope.RUNTIME) && dependency in depenciesFor(Scope.COMPILE)) {
|
||||
if ((scope == Scope.PROVIDED || scope == Scope.RUNTIME) && dependency in dependenciesFor(Scope.COMPILE)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (scope == Scope.PROVIDED && dependency in depenciesFor(Scope.RUNTIME)) {
|
||||
if (scope == Scope.PROVIDED && dependency in dependenciesFor(Scope.RUNTIME)) {
|
||||
result += POrderRoot(dependency, Scope.COMPILE)
|
||||
continue
|
||||
}
|
||||
|
||||
if (scope == Scope.RUNTIME && dependency in depenciesFor(Scope.PROVIDED)) {
|
||||
if (scope == Scope.RUNTIME && dependency in dependenciesFor(Scope.PROVIDED)) {
|
||||
result += POrderRoot(dependency, Scope.COMPILE)
|
||||
continue
|
||||
}
|
||||
@@ -345,17 +438,29 @@ private fun removeDuplicates(roots: List<POrderRoot>): List<POrderRoot> {
|
||||
return result.toList()
|
||||
}
|
||||
|
||||
data class DependencyInfo(val configuration: ResolvedConfiguration, val scope: Scope, val dependency: ResolvedDependency)
|
||||
data class CollectedConfiguration(
|
||||
val configuration: ResolvedConfiguration,
|
||||
val scope: Scope,
|
||||
val extraDependencies: List<File> = emptyList())
|
||||
|
||||
fun List<Pair<ResolvedConfiguration, Scope>>.collectDependencies(): List<DependencyInfo> {
|
||||
sealed class DependencyInfo(val scope: Scope) {
|
||||
class ResolvedDependencyInfo(scope: Scope, val dependency: ResolvedDependency) : DependencyInfo(scope)
|
||||
class CustomDependencyInfo(scope: Scope, val files: List<File>) : DependencyInfo(scope)
|
||||
}
|
||||
|
||||
fun List<CollectedConfiguration>.collectDependencies(): List<DependencyInfo> {
|
||||
val dependencies = mutableListOf<DependencyInfo>()
|
||||
|
||||
val unprocessed = LinkedList<DependencyInfo>()
|
||||
val existing = mutableSetOf<Pair<Scope, ResolvedDependency>>()
|
||||
|
||||
for ((configuration, scope) in this) {
|
||||
for ((configuration, scope, extraDependencies) in this) {
|
||||
for (dependency in configuration.firstLevelModuleDependencies) {
|
||||
unprocessed += DependencyInfo(configuration, scope, dependency)
|
||||
unprocessed += DependencyInfo.ResolvedDependencyInfo(scope, dependency)
|
||||
}
|
||||
|
||||
if (!extraDependencies.isEmpty()) {
|
||||
unprocessed += DependencyInfo.CustomDependencyInfo(scope, extraDependencies)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +468,8 @@ fun List<Pair<ResolvedConfiguration, Scope>>.collectDependencies(): List<Depende
|
||||
val info = unprocessed.removeAt(0)
|
||||
dependencies += info
|
||||
|
||||
info as? DependencyInfo.ResolvedDependencyInfo ?: continue
|
||||
|
||||
val data = Pair(info.scope, info.dependency)
|
||||
existing += data
|
||||
|
||||
@@ -371,9 +478,16 @@ fun List<Pair<ResolvedConfiguration, Scope>>.collectDependencies(): List<Depende
|
||||
continue
|
||||
}
|
||||
|
||||
unprocessed += DependencyInfo(info.configuration, info.scope, child)
|
||||
unprocessed += DependencyInfo.ResolvedDependencyInfo(info.scope, child)
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies
|
||||
}
|
||||
}
|
||||
|
||||
private val Project.sourceSets: SourceSetContainer
|
||||
get() {
|
||||
lateinit var result: SourceSetContainer
|
||||
project.configure<JavaPluginConvention> { result = sourceSets }
|
||||
return result
|
||||
}
|
||||
@@ -17,7 +17,7 @@ interface PathContext {
|
||||
}
|
||||
}
|
||||
|
||||
class ProjectContext private constructor(val projectDir: File) : PathContext {
|
||||
class ProjectContext private constructor(private val projectDir: File) : PathContext {
|
||||
constructor(project: PProject) : this(project.rootDirectory)
|
||||
constructor(project: Project) : this(project.projectDir)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.pill
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
@@ -10,16 +11,15 @@ import shadow.org.jdom2.output.Format
|
||||
import shadow.org.jdom2.output.XMLOutputter
|
||||
import java.io.File
|
||||
|
||||
class JpsCompatibleBasePlugin : Plugin<Project> {
|
||||
class PillConfigurablePlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
project.configurations.create(EmbeddedComponents.CONFIGURATION_NAME)
|
||||
project.extensions.create("pill", PillExtension::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
class JpsCompatiblePlugin : Plugin<Project> {
|
||||
companion object {
|
||||
private const val JPS_LIBRARY_PATH = "jpsLibraryPath"
|
||||
|
||||
private fun mapper(module: String, vararg configurations: String): DependencyMapper {
|
||||
return DependencyMapper("org.jetbrains.kotlin", module, *configurations) { MappedDependency(PDependency.Library(module)) }
|
||||
}
|
||||
@@ -47,21 +47,24 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
fun getProjectLibraries(rootProject: Project): List<PLibrary> {
|
||||
val distLibDir = File(rootProject.extra["distLibDir"].toString())
|
||||
fun distJar(name: String) = File(rootProject.projectDir, "dist/kotlinc/lib/$name.jar")
|
||||
fun projectFile(path: String) = File(rootProject.projectDir, path)
|
||||
|
||||
val libraries = rootProject.allprojects
|
||||
.filter { it.extra.has(JPS_LIBRARY_PATH) }
|
||||
.map { library ->
|
||||
val libraryPath = library.extra.get(JPS_LIBRARY_PATH).toString()
|
||||
.mapNotNull { library ->
|
||||
val libraryExtension = library.extensions.findByType(PillExtension::class.java)
|
||||
?.takeIf { it.importAsLibrary }
|
||||
?: return@mapNotNull null
|
||||
|
||||
val libraryPath = libraryExtension.libraryPath ?: distLibDir
|
||||
val archivesBaseName = library.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName ?: library.name
|
||||
|
||||
fun List<File>.filterExisting() = filter { it.exists() }
|
||||
|
||||
PLibrary(
|
||||
library.name,
|
||||
classes = listOf(File(libraryPath, archivesBaseName + ".jar")).filterExisting(),
|
||||
sources = listOf(File(libraryPath, archivesBaseName + "-sources.jar")).filterExisting()
|
||||
classes = listOf(File(libraryPath, "$archivesBaseName.jar")).filterExisting(),
|
||||
sources = listOf(File(libraryPath, "$archivesBaseName-sources.jar")).filterExisting()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,15 +73,18 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
override fun apply(project: Project) {
|
||||
project.plugins.apply(JpsCompatibleBasePlugin::class.java)
|
||||
project.plugins.apply(PillConfigurablePlugin::class.java)
|
||||
// 'jpsTest' does not require the 'tests-jar' artifact
|
||||
project.configurations.create("jpsTest")
|
||||
|
||||
if (project == project.rootProject) {
|
||||
project.tasks.create("pill") {
|
||||
doLast { pill(project) }
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
TaskUtils.useAndroidJar(this)
|
||||
|
||||
if (System.getProperty("pill.android.tests", "false") == "true") {
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.create("unpill") {
|
||||
@@ -103,8 +109,22 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
private fun pill(rootProject: Project) {
|
||||
initEnvironment(rootProject)
|
||||
|
||||
val variantOptionValue = System.getProperty("pill.variant", "base").toUpperCase()
|
||||
val variant = PillExtension.Variant.values().firstOrNull { it.name == variantOptionValue }
|
||||
?: run {
|
||||
rootProject.logger.error("Invalid variant name: $variantOptionValue")
|
||||
return
|
||||
}
|
||||
|
||||
rootProject.logger.lifecycle("Pill: Setting up project for the '${variant.name.toLowerCase()}' variant...")
|
||||
|
||||
if (variant == PillExtension.Variant.NONE || variant == PillExtension.Variant.DEFAULT) {
|
||||
rootProject.logger.error("'none' and 'default' should not be passed as a Pill variant property value")
|
||||
return
|
||||
}
|
||||
|
||||
val projectLibraries = getProjectLibraries(rootProject)
|
||||
val parserContext = ParserContext(getDependencyMappers(projectLibraries))
|
||||
val parserContext = ParserContext(getDependencyMappers(projectLibraries), variant)
|
||||
|
||||
val jpsProject = parse(rootProject, projectLibraries, parserContext)
|
||||
.mapLibraries(this::attachPlatformSources, this::attachAsmSources)
|
||||
@@ -202,8 +222,9 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
|
||||
fun addOrReplaceOptionValue(name: String, value: Any) {
|
||||
options = options.filter { !it.startsWith("-D$name=") } + listOf("-D$name=$value")
|
||||
fun addOrReplaceOptionValue(name: String, value: Any?) {
|
||||
val optionsWithoutNewValue = options.filter { !it.startsWith("-D$name=") }
|
||||
options = if (value == null) optionsWithoutNewValue else (optionsWithoutNewValue + listOf("-D$name=$value"))
|
||||
}
|
||||
|
||||
val robolectricClasspath = project.rootProject
|
||||
@@ -211,16 +232,21 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
.configurations.getByName("robolectricClasspath")
|
||||
.files.joinToString(File.pathSeparator)
|
||||
|
||||
val androidJarPath = project.configurations.getByName("androidJar").singleFile
|
||||
val androidSdkPath = project.configurations.getByName("androidSdk").singleFile
|
||||
|
||||
addOrReplaceOptionValue("idea.home.path", platformDirProjectRelative)
|
||||
addOrReplaceOptionValue("ideaSdk.androidPlugin.path", platformDirProjectRelative + "/plugins/android/lib")
|
||||
addOrReplaceOptionValue("robolectric.classpath", robolectricClasspath)
|
||||
addOrReplaceOptionValue("use.pill", "true")
|
||||
|
||||
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
|
||||
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
|
||||
val isAndroidStudioBunch = project.findProperty("versions.androidStudioRelease") != null
|
||||
addOrReplaceOptionValue("idea.platform.prefix", if (isAndroidStudioBunch) "AndroidStudio" else null)
|
||||
|
||||
val androidJarPath = project.configurations.findByName("androidJar")?.singleFile
|
||||
val androidSdkPath = project.configurations.findByName("androidSdk")?.singleFile
|
||||
|
||||
if (androidJarPath != null && androidSdkPath != null) {
|
||||
addOrReplaceOptionValue("android.sdk", "\$PROJECT_DIR\$/" + androidSdkPath.toRelativeString(projectDir))
|
||||
addOrReplaceOptionValue("android.jar", "\$PROJECT_DIR\$/" + androidJarPath.toRelativeString(projectDir))
|
||||
}
|
||||
|
||||
vmParams.setAttribute("value", options.joinToString(" "))
|
||||
}
|
||||
|
||||
@@ -54,10 +54,57 @@ private fun renderModule(project: PProject, module: PModule) = PFile(
|
||||
xml("component", "name" to "TestModuleProperties", "production-module" to moduleForProductionSources.name)
|
||||
}
|
||||
|
||||
xml("component", "name" to "NewModuleRootManager", "inherit-compiler-output" to "true") {
|
||||
xml("exclude-output")
|
||||
val kotlinCompileOptionsList = module.contentRoots.flatMap { it.sourceRoots }.mapNotNull { it.kotlinOptions }
|
||||
var kotlinCompileOptions = kotlinCompileOptionsList.firstOrNull()
|
||||
for (otherOptions in kotlinCompileOptionsList.drop(1)) {
|
||||
kotlinCompileOptions = kotlinCompileOptions?.intersect(otherOptions)
|
||||
}
|
||||
|
||||
val pathContext = ModuleContext(project, module)
|
||||
val pathContext = ModuleContext(project, module)
|
||||
|
||||
val platformVersion = (kotlinCompileOptions?.jvmTarget ?: "1.8")
|
||||
val classesDirectory = File(project.rootDirectory, "out/production/${module.name}")
|
||||
|
||||
if (kotlinCompileOptions != null) {
|
||||
xml("component", "name" to "FacetManager") {
|
||||
xml("facet", "type" to "kotlin-language", "name" to "Kotlin") {
|
||||
xml("configuration", "version" to 3, "platform" to "JVM $platformVersion", "useProjectSettings" to "false") {
|
||||
xml("compilerSettings") {
|
||||
xml(
|
||||
"option",
|
||||
"name" to "additionalArguments",
|
||||
"value" to kotlinCompileOptions.extraArguments.joinToString(" ")
|
||||
)
|
||||
}
|
||||
xml("compilerArguments") {
|
||||
xml("option", "name" to "destination", "value" to pathContext(classesDirectory))
|
||||
|
||||
fun Any?.option(name: String) {
|
||||
if (this != null) xml("option", "name" to name, "value" to this.toString())
|
||||
}
|
||||
|
||||
kotlinCompileOptions.noStdlib.option("noStdlib")
|
||||
kotlinCompileOptions.noReflect.option("noReflect")
|
||||
kotlinCompileOptions.moduleName.option("moduleName")
|
||||
kotlinCompileOptions.languageVersion.option("languageVersion")
|
||||
kotlinCompileOptions.apiVersion.option("apiVersion")
|
||||
kotlinCompileOptions.addCompilerBuiltIns.option("addCompilerBuiltIns")
|
||||
kotlinCompileOptions.loadBuiltInsFromDependencies.option("loadBuiltInsFromDependencies")
|
||||
|
||||
xml("option", "name" to "pluginOptions") { xml("array") }
|
||||
xml("option", "name" to "pluginClasspaths") { xml("array") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml("component",
|
||||
"name" to "NewModuleRootManager",
|
||||
"LANGUAGE_LEVEL" to "JDK_${platformVersion.replace('.', '_')}",
|
||||
"inherit-compiler-output" to "true"
|
||||
) {
|
||||
xml("exclude-output")
|
||||
|
||||
for (contentRoot in module.contentRoots) {
|
||||
xml("content", pathContext.url(contentRoot.path)) {
|
||||
@@ -98,7 +145,6 @@ private fun renderModule(project: PProject, module: PModule) = PFile(
|
||||
"name" to dependency.name,
|
||||
"level" to "project"
|
||||
)
|
||||
else -> error("Unsupported dependency type: $dependency")
|
||||
}
|
||||
|
||||
if (dependency is PDependency.Module && orderRoot.isProductionOnTestDependency) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import shadow.org.jdom2.Element
|
||||
import shadow.org.jdom2.output.Format
|
||||
import shadow.org.jdom2.output.XMLOutputter
|
||||
|
||||
class xml(val name: String, vararg val args: Pair<String, Any>, block: xml.() -> Unit = {}) {
|
||||
class xml(val name: String, private vararg val args: Pair<String, Any>, block: xml.() -> Unit = {}) {
|
||||
private companion object {
|
||||
fun makeXml(name: String, vararg args: Pair<String, Any>, block: xml.() -> Unit = {}): xml {
|
||||
return xml(name, *args, block = block)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<module name="idea-runner" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$IDEA_HOME_PATH$/system -Didea.config.path=$IDEA_HOME_PATH$/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/ideaSDK/system-idea/log/idea.log" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
|
||||
<module name="idea-runner" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$IDEA_HOME_PATH$/system -Didea.config.path=$IDEA_HOME_PATH$/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.ProcessCanceledException=disabled" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx1250m -XX:ReservedCodeCacheSize=240m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=$PROJECT_DIR$/local/ideaSandbox -Didea.config.path=$PROJECT_DIR$/local/ideaSandbox/config -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.ProcessCanceledException=disabled" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$IDEA_HOME_PATH$" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="" />
|
||||
|
||||
@@ -14,17 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
|
||||
public interface AccessorForCallableDescriptor<T extends CallableMemberDescriptor> {
|
||||
@NotNull
|
||||
T getCalleeDescriptor();
|
||||
interface AccessorForCallableDescriptor<T : CallableMemberDescriptor> {
|
||||
val calleeDescriptor: T
|
||||
|
||||
@Nullable
|
||||
ClassDescriptor getSuperCallTarget();
|
||||
val superCallTarget: ClassDescriptor?
|
||||
|
||||
val accessorKind: AccessorKind
|
||||
}
|
||||
@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
class AccessorForConstructorDescriptor(
|
||||
private val calleeDescriptor: ClassConstructorDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
private val superCallTarget: ClassDescriptor?
|
||||
override val calleeDescriptor: ClassConstructorDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val superCallTarget: ClassDescriptor?,
|
||||
override val accessorKind: AccessorKind
|
||||
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("<init>")),
|
||||
ClassConstructorDescriptor,
|
||||
AccessorForCallableDescriptor<ConstructorDescriptor> {
|
||||
override fun getCalleeDescriptor(): ConstructorDescriptor = calleeDescriptor
|
||||
ClassConstructorDescriptor,
|
||||
AccessorForCallableDescriptor<ConstructorDescriptor> {
|
||||
|
||||
override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.containingDeclaration
|
||||
|
||||
@@ -39,16 +39,15 @@ class AccessorForConstructorDescriptor(
|
||||
|
||||
override fun getReturnType(): KotlinType = super.getReturnType()!!
|
||||
|
||||
override fun getSuperCallTarget(): ClassDescriptor? = superCallTarget
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor) = super.substitute(substitutor) as ClassConstructorDescriptor
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
): AccessorForConstructorDescriptor {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
@@ -57,13 +56,13 @@ class AccessorForConstructorDescriptor(
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||
calleeDescriptor.dispatchReceiverParameter,
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||
calleeDescriptor.dispatchReceiverParameter,
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDescriptor implements AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||
private final FunctionDescriptor calleeDescriptor;
|
||||
private final ClassDescriptor superCallTarget;
|
||||
private final String nameSuffix;
|
||||
|
||||
public AccessorForFunctionDescriptor(
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix
|
||||
) {
|
||||
super(containingDeclaration,
|
||||
Name.identifier("access$" + nameSuffix));
|
||||
this.calleeDescriptor = descriptor;
|
||||
this.superCallTarget = superCallTarget;
|
||||
this.nameSuffix = nameSuffix;
|
||||
|
||||
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
|
||||
descriptor instanceof ConstructorDescriptor || CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(descriptor)
|
||||
? null
|
||||
: descriptor.getDispatchReceiverParameter(),
|
||||
copyTypeParameters(descriptor),
|
||||
copyValueParameters(descriptor),
|
||||
descriptor.getReturnType(),
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL);
|
||||
|
||||
setSuspend(descriptor.isSuspend());
|
||||
if (descriptor.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) {
|
||||
userDataMap = new LinkedHashMap<>();
|
||||
userDataMap.put(
|
||||
CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION,
|
||||
descriptor.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FunctionDescriptorImpl createSubstitutedCopy(
|
||||
@NotNull DeclarationDescriptor newOwner,
|
||||
@Nullable FunctionDescriptor original,
|
||||
@NotNull Kind kind,
|
||||
@Nullable Name newName,
|
||||
@NotNull Annotations annotations,
|
||||
@NotNull SourceElement source
|
||||
) {
|
||||
return new AccessorForFunctionDescriptor(calleeDescriptor, newOwner, superCallTarget, nameSuffix);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getCalleeDescriptor() {
|
||||
return calleeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return superCallTarget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
import java.util.LinkedHashMap
|
||||
|
||||
class AccessorForFunctionDescriptor(
|
||||
override val calleeDescriptor: FunctionDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val superCallTarget: ClassDescriptor?,
|
||||
private val nameSuffix: String,
|
||||
override val accessorKind: AccessorKind
|
||||
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.identifier("access$$nameSuffix")),
|
||||
AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(calleeDescriptor.extensionReceiverParameter),
|
||||
if (calleeDescriptor is ConstructorDescriptor || calleeDescriptor.isJvmStaticInObjectOrClassOrInterface())
|
||||
null
|
||||
else
|
||||
calleeDescriptor.dispatchReceiverParameter,
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
)
|
||||
|
||||
isSuspend = calleeDescriptor.isSuspend
|
||||
if (calleeDescriptor.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) {
|
||||
userDataMap = LinkedHashMap<FunctionDescriptor.UserDataKey<*>, Any>()
|
||||
userDataMap[INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION] =
|
||||
calleeDescriptor.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSubstitutedCopy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
original: FunctionDescriptor?,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
newName: Name?,
|
||||
annotations: Annotations,
|
||||
source: SourceElement
|
||||
): FunctionDescriptorImpl {
|
||||
return AccessorForFunctionDescriptor(calleeDescriptor, newOwner, superCallTarget, nameSuffix, accessorKind)
|
||||
}
|
||||
}
|
||||
@@ -22,19 +22,20 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class AccessorForPropertyBackingField(
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegateType: KotlinType?,
|
||||
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
nameSuffix: String,
|
||||
val fieldAccessorKind: FieldAccessorKind
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegateType: KotlinType?,
|
||||
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
nameSuffix: String,
|
||||
fieldAccessorKind: AccessorKind
|
||||
) : AccessorForPropertyDescriptor(
|
||||
property,
|
||||
delegateType ?: property.type,
|
||||
extensionReceiverParameter?.type,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
null,
|
||||
nameSuffix
|
||||
property,
|
||||
delegateType ?: property.type,
|
||||
extensionReceiverParameter?.type,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
null,
|
||||
nameSuffix,
|
||||
fieldAccessorKind
|
||||
)
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||
private final PropertyDescriptor calleeDescriptor;
|
||||
private final ClassDescriptor superCallTarget;
|
||||
private final String nameSuffix;
|
||||
private final boolean withSyntheticGetterAccessor;
|
||||
private final boolean withSyntheticSetterAccessor;
|
||||
|
||||
public AccessorForPropertyDescriptor(
|
||||
@NotNull PropertyDescriptor property,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix,
|
||||
boolean getterAccessorRequired,
|
||||
boolean setterAccessorRequired
|
||||
) {
|
||||
this(property, property.getType(), DescriptorUtils.getReceiverParameterType(property.getExtensionReceiverParameter()),
|
||||
/* dispatchReceiverParameter = */
|
||||
CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(property) ? null : property.getDispatchReceiverParameter(),
|
||||
containingDeclaration, superCallTarget, nameSuffix,
|
||||
getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
|
||||
protected AccessorForPropertyDescriptor(
|
||||
@NotNull PropertyDescriptor original,
|
||||
@NotNull KotlinType propertyType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix
|
||||
) {
|
||||
this(original, propertyType, receiverType, dispatchReceiverParameter, containingDeclaration, superCallTarget, nameSuffix, true, true);
|
||||
}
|
||||
|
||||
private AccessorForPropertyDescriptor(
|
||||
@NotNull PropertyDescriptor original,
|
||||
@NotNull KotlinType propertyType,
|
||||
@Nullable KotlinType receiverType,
|
||||
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix,
|
||||
boolean getterAccessorRequired,
|
||||
boolean setterAccessorRequired
|
||||
) {
|
||||
super(containingDeclaration, null, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
|
||||
original.isVar(), Name.identifier("access$" + nameSuffix), Kind.DECLARATION, SourceElement.NO_SOURCE,
|
||||
false, false, false, false, false, false);
|
||||
|
||||
this.calleeDescriptor = original;
|
||||
this.superCallTarget = superCallTarget;
|
||||
this.nameSuffix = nameSuffix;
|
||||
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
||||
|
||||
this.withSyntheticGetterAccessor = getterAccessorRequired;
|
||||
this.withSyntheticSetterAccessor = setterAccessorRequired;
|
||||
|
||||
PropertyGetterDescriptorImpl getterDescriptor =
|
||||
getterAccessorRequired ? new Getter(this) : (PropertyGetterDescriptorImpl) original.getGetter();
|
||||
PropertySetterDescriptor setterDescriptor =
|
||||
setterAccessorRequired ? new Setter(this) : original.getSetter();
|
||||
initialize(getterDescriptor, setterDescriptor);
|
||||
}
|
||||
|
||||
public static class Getter extends PropertyGetterDescriptorImpl implements AccessorForCallableDescriptor<PropertyGetterDescriptor> {
|
||||
public Getter(AccessorForPropertyDescriptor property) {
|
||||
super(property, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
|
||||
/* isDefault = */ false, /* isExternal = */ false, /* isInline = */false, Kind.DECLARATION, null, SourceElement.NO_SOURCE);
|
||||
initialize(property.getType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PropertyGetterDescriptor getCalleeDescriptor() {
|
||||
//noinspection ConstantConditions
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallTarget();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Setter extends PropertySetterDescriptorImpl implements AccessorForCallableDescriptor<PropertySetterDescriptor>{
|
||||
public Setter(AccessorForPropertyDescriptor property) {
|
||||
super(property, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
|
||||
/* isDefault = */ false, /* isExternal = */ false, /* isInline = */ false, Kind.DECLARATION, null, SourceElement.NO_SOURCE);
|
||||
initializeDefault();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PropertySetterDescriptor getCalleeDescriptor() {
|
||||
//noinspection ConstantConditions
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getSetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PropertyDescriptor getCalleeDescriptor() {
|
||||
return calleeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor getSuperCallTarget() {
|
||||
return superCallTarget;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getAccessorSuffix() {
|
||||
return nameSuffix;
|
||||
}
|
||||
|
||||
public boolean isWithSyntheticGetterAccessor() {
|
||||
return withSyntheticGetterAccessor;
|
||||
}
|
||||
|
||||
public boolean isWithSyntheticSetterAccessor() {
|
||||
return withSyntheticSetterAccessor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
open class AccessorForPropertyDescriptor private constructor(
|
||||
override val calleeDescriptor: PropertyDescriptor,
|
||||
propertyType: KotlinType,
|
||||
receiverType: KotlinType?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val superCallTarget: ClassDescriptor?,
|
||||
val accessorSuffix: String,
|
||||
val isWithSyntheticGetterAccessor: Boolean,
|
||||
val isWithSyntheticSetterAccessor: Boolean,
|
||||
final override val accessorKind: AccessorKind
|
||||
) : PropertyDescriptorImpl(
|
||||
containingDeclaration,
|
||||
null,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL,
|
||||
calleeDescriptor.isVar,
|
||||
Name.identifier("access$$accessorSuffix"),
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
), AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||
|
||||
constructor(
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
superCallTarget: ClassDescriptor?,
|
||||
nameSuffix: String,
|
||||
getterAccessorRequired: Boolean,
|
||||
setterAccessorRequired: Boolean,
|
||||
accessorKind: AccessorKind
|
||||
) : this(
|
||||
property, property.type, DescriptorUtils.getReceiverParameterType(property.extensionReceiverParameter),
|
||||
/* dispatchReceiverParameter = */
|
||||
if (property.isJvmStaticInObjectOrClassOrInterface()) null else property.dispatchReceiverParameter,
|
||||
containingDeclaration, superCallTarget, nameSuffix,
|
||||
getterAccessorRequired, setterAccessorRequired,
|
||||
accessorKind
|
||||
)
|
||||
|
||||
protected constructor(
|
||||
original: PropertyDescriptor,
|
||||
propertyType: KotlinType,
|
||||
receiverType: KotlinType?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
superCallTarget: ClassDescriptor?,
|
||||
nameSuffix: String,
|
||||
accessorKind: AccessorKind
|
||||
) : this(
|
||||
original,
|
||||
propertyType,
|
||||
receiverType,
|
||||
dispatchReceiverParameter,
|
||||
containingDeclaration,
|
||||
superCallTarget,
|
||||
nameSuffix,
|
||||
true,
|
||||
true,
|
||||
accessorKind
|
||||
)
|
||||
|
||||
init {
|
||||
setType(propertyType, emptyList<TypeParameterDescriptorImpl>(), dispatchReceiverParameter, receiverType)
|
||||
|
||||
val getterDescriptor =
|
||||
if (isWithSyntheticGetterAccessor) Getter(this, accessorKind) else calleeDescriptor.getter as PropertyGetterDescriptorImpl?
|
||||
val setterDescriptor = if (isWithSyntheticSetterAccessor) Setter(this, accessorKind) else calleeDescriptor.setter
|
||||
initialize(getterDescriptor, setterDescriptor)
|
||||
}
|
||||
|
||||
class Getter(property: AccessorForPropertyDescriptor, override val accessorKind: AccessorKind) : PropertyGetterDescriptorImpl(
|
||||
property,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
), AccessorForCallableDescriptor<PropertyGetterDescriptor> {
|
||||
|
||||
override val calleeDescriptor: PropertyGetterDescriptor
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).calleeDescriptor.getter!!
|
||||
|
||||
override val superCallTarget: ClassDescriptor?
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).superCallTarget
|
||||
|
||||
init {
|
||||
initialize(property.type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Setter(property: AccessorForPropertyDescriptor, override val accessorKind: AccessorKind) : PropertySetterDescriptorImpl(
|
||||
property,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
), AccessorForCallableDescriptor<PropertySetterDescriptor> {
|
||||
|
||||
override val calleeDescriptor: PropertySetterDescriptor
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).calleeDescriptor.setter!!
|
||||
|
||||
override val superCallTarget: ClassDescriptor?
|
||||
get() = (correspondingProperty as AccessorForPropertyDescriptor).superCallTarget
|
||||
|
||||
init {
|
||||
initializeDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,6 +300,10 @@ public abstract class AnnotationCodegen {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (classDescriptor.isExpect()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
innerClassConsumer.addInnerClassInfoFromAnnotation(classDescriptor);
|
||||
|
||||
String asmTypeDescriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
|
||||
@@ -509,7 +508,7 @@ public class AsmUtil {
|
||||
});
|
||||
}
|
||||
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type, JvmTarget jvmTarget, boolean isInterface) {
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type, JvmTarget jvmTarget) {
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
Type elementType = correctElementType(type);
|
||||
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
||||
@@ -520,7 +519,7 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
else if (type.getSort() == Type.OBJECT) {
|
||||
iv.invokevirtual((isInterface ? AsmTypes.OBJECT_TYPE : type).getInternalName(), "hashCode", "()I", false);
|
||||
iv.invokevirtual("java/lang/Object", "hashCode", "()I", false);
|
||||
}
|
||||
else if (type.getSort() == Type.BOOLEAN) {
|
||||
Label end = new Label();
|
||||
|
||||
@@ -1942,7 +1942,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private CodegenContext getBackingFieldContext(
|
||||
@NotNull FieldAccessorKind accessorKind,
|
||||
@NotNull AccessorKind accessorKind,
|
||||
@NotNull DeclarationDescriptor containingDeclaration
|
||||
) {
|
||||
switch (accessorKind) {
|
||||
@@ -1992,22 +1992,22 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
|
||||
boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
FieldAccessorKind fieldAccessorKind;
|
||||
AccessorKind fieldAccessorKind;
|
||||
if (skipLateinitAssertion) {
|
||||
fieldAccessorKind = FieldAccessorKind.LATEINIT_INTRINSIC;
|
||||
fieldAccessorKind = AccessorKind.LATEINIT_INTRINSIC;
|
||||
}
|
||||
else if (isBackingFieldInClassCompanion &&
|
||||
(forceField ||
|
||||
(Visibilities.isPrivate(propertyDescriptor.getVisibility()) &&
|
||||
isDefaultAccessor(propertyDescriptor.getGetter()) && isDefaultAccessor(propertyDescriptor.getSetter())))) {
|
||||
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
|
||||
fieldAccessorKind = AccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if ((syntheticBackingField &&
|
||||
context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration)) {
|
||||
fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
fieldAccessorKind = AccessorKind.FIELD_FROM_LOCAL;
|
||||
}
|
||||
else {
|
||||
fieldAccessorKind = FieldAccessorKind.NORMAL;
|
||||
fieldAccessorKind = AccessorKind.NORMAL;
|
||||
}
|
||||
boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) ||
|
||||
AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor);
|
||||
@@ -2022,7 +2022,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
CodegenContext backingFieldContext = getBackingFieldContext(fieldAccessorKind, containingDeclaration);
|
||||
boolean isPrivateProperty =
|
||||
fieldAccessorKind != FieldAccessorKind.NORMAL &&
|
||||
fieldAccessorKind != AccessorKind.NORMAL &&
|
||||
(AsmUtil.getVisibilityForBackingField(propertyDescriptor, isDelegatedProperty) & ACC_PRIVATE) != 0;
|
||||
DeclarationDescriptor ownerDescriptor;
|
||||
boolean skipPropertyAccessors;
|
||||
@@ -2033,7 +2033,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
boolean directAccessToSetter = couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context,
|
||||
state.getShouldInlineConstVals());
|
||||
|
||||
if (fieldAccessorKind == FieldAccessorKind.LATEINIT_INTRINSIC) {
|
||||
if (fieldAccessorKind == AccessorKind.LATEINIT_INTRINSIC) {
|
||||
skipPropertyAccessors = !isPrivateProperty || context.getClassOrPackageParentContext() == backingFieldContext;
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
@@ -2042,7 +2042,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
ownerDescriptor = propertyDescriptor;
|
||||
}
|
||||
else if (fieldAccessorKind == FieldAccessorKind.IN_CLASS_COMPANION || fieldAccessorKind == FieldAccessorKind.FIELD_FROM_LOCAL) {
|
||||
else if (fieldAccessorKind == AccessorKind.IN_CLASS_COMPANION || fieldAccessorKind == AccessorKind.FIELD_FROM_LOCAL) {
|
||||
// Do not use accessor 'access<property name>$cp' when the property can be accessed directly by its backing field.
|
||||
skipPropertyAccessors = skipAccessorsForPrivateFieldInOuterClass ||
|
||||
(directAccessToGetter && (!propertyDescriptor.isVar() || directAccessToSetter));
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
||||
import org.jetbrains.kotlin.config.JvmTarget;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -179,7 +180,10 @@ public class FunctionCodegen {
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
if (isInterface(containingDeclaration) && !processInterfaceMethod(functionDescriptor, contextKind, false)) return;
|
||||
if (isInterface(containingDeclaration) &&
|
||||
!processInterfaceMethod(functionDescriptor, contextKind, false, false, state.getJvmDefaultMode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasSpecialBridge = hasSpecialBridgeMethod(functionDescriptor);
|
||||
JvmMethodGenericSignature jvmSignature = strategy.mapMethodSignature(functionDescriptor, typeMapper, contextKind, hasSpecialBridge);
|
||||
@@ -392,7 +396,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
if (!functionDescriptor.isExternal()) {
|
||||
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
|
||||
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode());
|
||||
}
|
||||
else if (staticInCompanionObject) {
|
||||
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
|
||||
@@ -402,7 +406,7 @@ public class FunctionCodegen {
|
||||
Method accessorMethod =
|
||||
typeMapper.mapAsmMethod(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
|
||||
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
|
||||
generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName());
|
||||
generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName(), false);
|
||||
}
|
||||
|
||||
endVisit(mv, null, origin.getElement());
|
||||
@@ -574,7 +578,8 @@ public class FunctionCodegen {
|
||||
@NotNull MethodContext context,
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull FunctionGenerationStrategy strategy,
|
||||
@NotNull MemberCodegen<?> parentCodegen
|
||||
@NotNull MemberCodegen<?> parentCodegen,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
) {
|
||||
mv.visitCode();
|
||||
|
||||
@@ -596,6 +601,20 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else if (isCompatibilityStubInDefaultImpls(functionDescriptor, context, jvmDefaultMode)) {
|
||||
FunctionDescriptor compatibility = ((DefaultImplsClassContext) context.getParentContext()).getInterfaceContext()
|
||||
.getAccessorForJvmDefaultCompatibility(functionDescriptor);
|
||||
int flags = AsmUtil.getMethodAsmFlags(functionDescriptor, OwnerKind.DEFAULT_IMPLS, context.getState());
|
||||
assert (flags & Opcodes.ACC_ABSTRACT) == 0 : "Interface method with body should be non-abstract" + functionDescriptor;
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(compatibility, false);
|
||||
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
method.getAsmMethod(),
|
||||
method.getOwner().getInternalName(),
|
||||
true);
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else {
|
||||
FrameMap frameMap = createFrameMap(
|
||||
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
|
||||
@@ -690,6 +709,16 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCompatibilityStubInDefaultImpls(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodContext context,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
) {
|
||||
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
|
||||
hasJvmDefaultAnnotation(functionDescriptor) &&
|
||||
jvmDefaultMode.isCompatibility();
|
||||
}
|
||||
|
||||
private static void generateLocalVariableTable(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmMethodSignature,
|
||||
@@ -869,7 +898,7 @@ public class FunctionCodegen {
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull MultifileClassFacadeContext context
|
||||
) {
|
||||
generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName());
|
||||
generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName(), false);
|
||||
}
|
||||
|
||||
private static void generateDelegateToMethodBody(
|
||||
@@ -937,9 +966,10 @@ public class FunctionCodegen {
|
||||
boolean isStatic,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull String classToDelegateTo
|
||||
@NotNull String classToDelegateTo,
|
||||
boolean isInterfaceMethodCall
|
||||
) {
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, false);
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, isInterfaceMethodCall);
|
||||
}
|
||||
|
||||
private static boolean needIndexForVar(JvmMethodParameterKind kind) {
|
||||
@@ -1119,7 +1149,7 @@ public class FunctionCodegen {
|
||||
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
||||
|
||||
if (isInterface(contextClass) &&
|
||||
!processInterfaceMethod(functionDescriptor, kind, true)) {
|
||||
!processInterfaceMethod(functionDescriptor, kind, true, false, state.getJvmDefaultMode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1164,6 +1194,17 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
|
||||
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else if (isCompatibilityStubInDefaultImpls(functionDescriptor, owner, state.getJvmDefaultMode())) {
|
||||
mv.visitCode();
|
||||
Method interfaceDefaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
interfaceDefaultMethod,
|
||||
typeMapper.mapOwner(functionDescriptor).getInternalName(),
|
||||
true
|
||||
);
|
||||
endVisit(mv, "default method delegation to interface one", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else {
|
||||
mv.visitCode();
|
||||
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
|
||||
@@ -1538,18 +1579,21 @@ public class FunctionCodegen {
|
||||
public static boolean processInterfaceMethod(
|
||||
@NotNull CallableMemberDescriptor memberDescriptor,
|
||||
@NotNull OwnerKind kind,
|
||||
boolean isDefaultOrSynthetic
|
||||
boolean isDefault,
|
||||
boolean isSynthetic,
|
||||
JvmDefaultMode mode
|
||||
) {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
|
||||
containingDeclaration;
|
||||
|
||||
if (hasJvmDefaultAnnotation(memberDescriptor)) {
|
||||
return kind != OwnerKind.DEFAULT_IMPLS;
|
||||
return (kind != OwnerKind.DEFAULT_IMPLS && !isSynthetic) ||
|
||||
(kind == OwnerKind.DEFAULT_IMPLS && (isSynthetic || mode.isCompatibility()));
|
||||
} else {
|
||||
switch (kind) {
|
||||
case DEFAULT_IMPLS: return true;
|
||||
case IMPLEMENTATION: return !Visibilities.isPrivate(memberDescriptor.getVisibility()) && !isDefaultOrSynthetic;
|
||||
case IMPLEMENTATION: return !Visibilities.isPrivate(memberDescriptor.getVisibility()) && !isDefault && !isSynthetic;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
|
||||
@@ -52,7 +51,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
@@ -575,23 +573,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.ifne(ne);
|
||||
}
|
||||
else {
|
||||
if (isPrimitive(asmType)) {
|
||||
StackValue value = StackValue.cmp(KtTokens.EQEQ, asmType, StackValue.onStack(asmType), StackValue.onStack(asmType));
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
}
|
||||
else if (TypeUtils.isNullableType(propertyDescriptor.getType())) {
|
||||
StackValue value =
|
||||
genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType));
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
}
|
||||
else {
|
||||
Type owner =
|
||||
DescriptorUtils.isInterface(propertyDescriptor.getType().getConstructor().getDeclarationDescriptor())
|
||||
? AsmTypes.OBJECT_TYPE
|
||||
: asmType;
|
||||
iv.invokevirtual(owner.getInternalName(), "equals",
|
||||
Type.getMethodDescriptor(Type.BOOLEAN_TYPE, AsmTypes.OBJECT_TYPE), false);
|
||||
}
|
||||
StackValue value = genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType));
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
iv.ifeq(ne);
|
||||
}
|
||||
}
|
||||
@@ -632,8 +615,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.ifnull(ifNull);
|
||||
}
|
||||
|
||||
genHashCode(mv, iv, asmType, state.getTarget(),
|
||||
DescriptorUtils.isInterface(propertyDescriptor.getType().getConstructor().getDeclarationDescriptor()));
|
||||
genHashCode(mv, iv, asmType, state.getTarget());
|
||||
|
||||
if (ifNull != null) {
|
||||
Label end = new Label();
|
||||
@@ -1422,7 +1404,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateTraitMethods() {
|
||||
if (isInterface(descriptor)) return;
|
||||
if (isJvmInterface(descriptor)) return;
|
||||
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
FunctionDescriptor interfaceFun = entry.getKey();
|
||||
|
||||
@@ -72,21 +72,17 @@ class InterfaceImplBodyCodegen(
|
||||
// If implementation is a default interface method (JVM 8 only)
|
||||
if (implementation.isDefinitelyNotDefaultImplsMethod()) continue
|
||||
|
||||
// We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body
|
||||
val copy = memberDescriptor.copy(memberDescriptor.containingDeclaration, Modality.OPEN, memberDescriptor.visibility,
|
||||
CallableMemberDescriptor.Kind.DECLARATION, true)
|
||||
|
||||
if (memberDescriptor is FunctionDescriptor) {
|
||||
generateDelegationToSuperDefaultImpls(copy as FunctionDescriptor, implementation as FunctionDescriptor)
|
||||
generateDelegationToSuperDefaultImpls(memberDescriptor, implementation as FunctionDescriptor)
|
||||
}
|
||||
else if (memberDescriptor is PropertyDescriptor) {
|
||||
implementation as PropertyDescriptor
|
||||
val getter = (copy as PropertyDescriptor).getter
|
||||
val getter = memberDescriptor.getter
|
||||
val implGetter = implementation.getter
|
||||
if (getter != null && implGetter != null) {
|
||||
generateDelegationToSuperDefaultImpls(getter, implGetter)
|
||||
}
|
||||
val setter = copy.setter
|
||||
val setter = memberDescriptor.setter
|
||||
val implSetter = implementation.setter
|
||||
if (setter != null && implSetter != null) {
|
||||
generateDelegationToSuperDefaultImpls(setter, implSetter)
|
||||
|
||||
@@ -723,8 +723,18 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
markLineNumberForElement(element.getPsiOrParent(), codegen.v);
|
||||
|
||||
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
if (accessorForCallableDescriptor.getAccessorKind() == AccessorKind.JVM_DEFAULT_COMPATIBILITY) {
|
||||
FunctionDescriptor descriptor = unwrapFakeOverrideToAnyDeclaration(original).getOriginal();
|
||||
if (descriptor != original) {
|
||||
descriptor = descriptor
|
||||
.copy(original.getContainingDeclaration(), descriptor.getModality(), descriptor.getVisibility(),
|
||||
descriptor.getKind(), false);
|
||||
}
|
||||
generateMethodCallTo(descriptor, accessor, codegen.v).coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
}
|
||||
else {
|
||||
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
}
|
||||
|
||||
codegen.v.areturn(signature.getReturnType());
|
||||
}
|
||||
@@ -745,9 +755,26 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
FieldAccessorKind fieldAccessorKind = accessor instanceof AccessorForPropertyBackingField
|
||||
? ((AccessorForPropertyBackingField) accessor).getFieldAccessorKind() : null;
|
||||
boolean syntheticBackingField = fieldAccessorKind == FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
if (accessorForCallableDescriptor.getAccessorKind() == AccessorKind.JVM_DEFAULT_COMPATIBILITY) {
|
||||
markLineNumberForElement(element.getPsiOrParent(), codegen.v);
|
||||
PropertyDescriptor descriptor = unwrapFakeOverrideToAnyDeclaration(original).getOriginal();
|
||||
if (descriptor != original) {
|
||||
descriptor = (PropertyDescriptor) descriptor
|
||||
.copy(original.getContainingDeclaration(), descriptor.getModality(), descriptor.getVisibility(),
|
||||
descriptor.getKind(), false);
|
||||
}
|
||||
boolean isGetter = callableDescriptor instanceof PropertyGetterDescriptor;
|
||||
PropertyAccessorDescriptor originalAccessor = isGetter ? descriptor.getGetter(): descriptor.getSetter();
|
||||
PropertyAccessorDescriptor accessorDescriptor = isGetter ? accessor.getGetter() : accessor.getSetter();
|
||||
generateMethodCallTo(originalAccessor, accessorDescriptor, codegen.v)
|
||||
.coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
codegen.v.areturn(signature.getReturnType());
|
||||
return;
|
||||
}
|
||||
|
||||
AccessorKind fieldAccessorKind = accessor instanceof AccessorForPropertyBackingField
|
||||
? accessor.getAccessorKind() : null;
|
||||
boolean syntheticBackingField = fieldAccessorKind == AccessorKind.FIELD_FROM_LOCAL;
|
||||
boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration());
|
||||
boolean forceField = forceFieldForCompanionProperty ||
|
||||
@@ -756,7 +783,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
StackValue property = codegen.intermediateValueForProperty(
|
||||
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(),
|
||||
forceFieldForCompanionProperty, StackValue.none(), null,
|
||||
fieldAccessorKind == FieldAccessorKind.LATEINIT_INTRINSIC
|
||||
fieldAccessorKind == AccessorKind.LATEINIT_INTRINSIC
|
||||
);
|
||||
|
||||
InstructionAdapter iv = codegen.v;
|
||||
@@ -815,7 +842,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
CallableMethod callableMethod = typeMapper.mapToCallableMethod(
|
||||
functionDescriptor,
|
||||
accessorDescriptor instanceof AccessorForCallableDescriptor &&
|
||||
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
||||
(((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null ||
|
||||
((AccessorForCallableDescriptor) accessorDescriptor).getAccessorKind() == AccessorKind.JVM_DEFAULT_COMPATIBILITY)
|
||||
);
|
||||
|
||||
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
|
||||
|
||||
@@ -52,6 +52,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField;
|
||||
import static org.jetbrains.kotlin.codegen.FunctionCodegen.processInterfaceMethod;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTIES;
|
||||
@@ -352,7 +353,7 @@ public class PropertyCodegen {
|
||||
if (annotations.getAllAnnotations().isEmpty()) return;
|
||||
|
||||
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
|
||||
if (!isInterface(contextDescriptor) || FunctionCodegen.processInterfaceMethod(descriptor, kind, true)) {
|
||||
if (!isInterface(contextDescriptor) || processInterfaceMethod(descriptor, kind, false, true, state.getJvmDefaultMode())) {
|
||||
memberCodegen.generateSyntheticAnnotationsMethod(
|
||||
descriptor, getSyntheticMethodSignature(descriptor), annotations, AnnotationUseSiteTarget.PROPERTY
|
||||
);
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import kotlin.Pair;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
@@ -44,6 +45,8 @@ import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl;
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
||||
@@ -694,18 +697,54 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
CallableDescriptor descriptor = call.getResultingDescriptor();
|
||||
if (!(descriptor instanceof FunctionDescriptor)) return;
|
||||
|
||||
recordSamValueForNewInference(call);
|
||||
recordSamConstructorIfNeeded(expression, call);
|
||||
|
||||
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) descriptor);
|
||||
if (original == null) return;
|
||||
|
||||
List<ResolvedValueArgument> valueArguments = call.getValueArgumentsByIndex();
|
||||
if (valueArguments == null) return;
|
||||
|
||||
List<ValueParameterDescriptor> valueParametersWithSAMConversion = new SmartList<>();
|
||||
for (ValueParameterDescriptor valueParameter : original.getValueParameters()) {
|
||||
ValueParameterDescriptor adaptedParameter = descriptor.getValueParameters().get(valueParameter.getIndex());
|
||||
if (KotlinTypeChecker.DEFAULT.equalTypes(adaptedParameter.getType(), valueParameter.getType())) continue;
|
||||
valueParametersWithSAMConversion.add(valueParameter);
|
||||
}
|
||||
writeSamValueForValueParameters(valueParametersWithSAMConversion, call.getValueArgumentsByIndex());
|
||||
}
|
||||
|
||||
private void recordSamValueForNewInference(@NotNull ResolvedCall<?> call) {
|
||||
NewResolvedCallImpl<?> newResolvedCall = null;
|
||||
if (call instanceof NewVariableAsFunctionResolvedCallImpl) {
|
||||
newResolvedCall = ((NewVariableAsFunctionResolvedCallImpl) call).getFunctionCall();
|
||||
}
|
||||
else if(call instanceof NewResolvedCallImpl) {
|
||||
newResolvedCall = (NewResolvedCallImpl<?>) call;
|
||||
}
|
||||
if (newResolvedCall == null) return;
|
||||
|
||||
List<ValueParameterDescriptor> valueParametersWithSAMConversion = new SmartList<>();
|
||||
Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = newResolvedCall.getValueArguments();
|
||||
for (ValueParameterDescriptor valueParameter : arguments.keySet()) {
|
||||
ResolvedValueArgument argument = arguments.get(valueParameter);
|
||||
|
||||
if (!(argument instanceof ExpressionValueArgument)) continue;
|
||||
ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument();
|
||||
|
||||
if (valueArgument == null || newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) == null) continue;
|
||||
|
||||
valueParametersWithSAMConversion.add(valueParameter.getOriginal());
|
||||
}
|
||||
writeSamValueForValueParameters(valueParametersWithSAMConversion, newResolvedCall.getValueArgumentsByIndex());
|
||||
|
||||
}
|
||||
|
||||
private void writeSamValueForValueParameters(
|
||||
@NotNull Collection<ValueParameterDescriptor> valueParametersWithSAMConversion,
|
||||
@Nullable List<ResolvedValueArgument> valueArguments
|
||||
) {
|
||||
if (valueArguments == null) return;
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : valueParametersWithSAMConversion) {
|
||||
SamType samType = SamType.createByValueParameter(valueParameter);
|
||||
if (samType == null) continue;
|
||||
|
||||
|
||||
@@ -48,11 +48,11 @@ import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.util.Textifier
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.io.StringWriter
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.util.*
|
||||
|
||||
fun generateIsCheck(
|
||||
@@ -271,6 +271,7 @@ fun Collection<Type>.withVariableIndices(): List<Pair<Int, Type>> = mutableListO
|
||||
}
|
||||
|
||||
fun FunctionDescriptor.isGenericToArray(): Boolean {
|
||||
if (name.asString() != "toArray") return false
|
||||
if (valueParameters.size != 1 || typeParameters.size != 1) return false
|
||||
|
||||
val returnType = returnType ?: throw AssertionError(toString())
|
||||
@@ -284,6 +285,7 @@ fun FunctionDescriptor.isGenericToArray(): Boolean {
|
||||
}
|
||||
|
||||
fun FunctionDescriptor.isNonGenericToArray(): Boolean {
|
||||
if (name.asString() != "toArray") return false
|
||||
if (!valueParameters.isEmpty() || !typeParameters.isEmpty()) return false
|
||||
|
||||
val returnType = returnType
|
||||
|
||||
@@ -48,16 +48,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
private static class AccessorKey {
|
||||
public final DeclarationDescriptor descriptor;
|
||||
public final ClassDescriptor superCallLabelTarget;
|
||||
public final FieldAccessorKind fieldAccessorKind;
|
||||
public final AccessorKind accessorKind;
|
||||
|
||||
public AccessorKey(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@Nullable ClassDescriptor superCallLabelTarget,
|
||||
@NotNull FieldAccessorKind fieldAccessorKind
|
||||
@NotNull AccessorKind accessorKind
|
||||
) {
|
||||
this.descriptor = descriptor;
|
||||
this.superCallLabelTarget = superCallLabelTarget;
|
||||
this.fieldAccessorKind = fieldAccessorKind;
|
||||
this.accessorKind = accessorKind;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +65,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (!(obj instanceof AccessorKey)) return false;
|
||||
AccessorKey other = (AccessorKey) obj;
|
||||
return descriptor.equals(other.descriptor) &&
|
||||
fieldAccessorKind == other.fieldAccessorKind &&
|
||||
accessorKind == other.accessorKind &&
|
||||
(superCallLabelTarget == null ? other.superCallLabelTarget == null
|
||||
: superCallLabelTarget.equals(other.superCallLabelTarget));
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * descriptor.hashCode() +
|
||||
fieldAccessorKind.hashCode() +
|
||||
accessorKind.hashCode() +
|
||||
(superCallLabelTarget == null ? 0 : superCallLabelTarget.hashCode());
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
private final @NotNull DeclarationDescriptor containingDeclaration;
|
||||
private final @Nullable ClassDescriptor superCallTarget;
|
||||
private final @NotNull String nameSuffix;
|
||||
private final @NotNull AccessorKind accessorKind;
|
||||
|
||||
private AccessorForPropertyDescriptor withSyntheticGetterAndSetter = null;
|
||||
private AccessorForPropertyDescriptor withSyntheticGetter = null;
|
||||
@@ -97,12 +98,14 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@NotNull PropertyDescriptor property,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull String nameSuffix
|
||||
@NotNull String nameSuffix,
|
||||
@NotNull AccessorKind accessorKind
|
||||
) {
|
||||
this.property = property;
|
||||
this.containingDeclaration = containingDeclaration;
|
||||
this.superCallTarget = superCallTarget;
|
||||
this.nameSuffix = nameSuffix;
|
||||
this.accessorKind = accessorKind;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@@ -114,7 +117,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (withSyntheticGetter == null) {
|
||||
withSyntheticGetter = new AccessorForPropertyDescriptor(
|
||||
property, containingDeclaration, superCallTarget, nameSuffix,
|
||||
true, false);
|
||||
true, false, accessorKind);
|
||||
}
|
||||
return withSyntheticGetter;
|
||||
}
|
||||
@@ -122,7 +125,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (withSyntheticSetter == null) {
|
||||
withSyntheticSetter = new AccessorForPropertyDescriptor(
|
||||
property, containingDeclaration, superCallTarget, nameSuffix,
|
||||
false, true);
|
||||
false, true, accessorKind);
|
||||
}
|
||||
return withSyntheticSetter;
|
||||
}
|
||||
@@ -136,7 +139,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (withSyntheticGetterAndSetter == null) {
|
||||
withSyntheticGetterAndSetter = new AccessorForPropertyDescriptor(
|
||||
property, containingDeclaration, superCallTarget, nameSuffix,
|
||||
true, true);
|
||||
true, true, accessorKind);
|
||||
}
|
||||
return withSyntheticGetterAndSetter;
|
||||
}
|
||||
@@ -402,12 +405,24 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
boolean getterAccessorRequired,
|
||||
boolean setterAccessorRequired
|
||||
) {
|
||||
return getAccessor(propertyDescriptor, FieldAccessorKind.NORMAL, null, superCallTarget, getterAccessorRequired, setterAccessorRequired);
|
||||
return getAccessor(propertyDescriptor, AccessorKind.NORMAL, null, superCallTarget, getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
|
||||
|
||||
public <D extends CallableMemberDescriptor> D getAccessorForJvmDefaultCompatibility(@NotNull D descriptor) {
|
||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
PropertyDescriptor propertyAccessor = getAccessor(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty(),
|
||||
AccessorKind.JVM_DEFAULT_COMPATIBILITY, null, null,
|
||||
descriptor instanceof PropertyGetterDescriptor,
|
||||
descriptor instanceof PropertySetterDescriptor);
|
||||
return descriptor instanceof PropertyGetterDescriptor ? (D) propertyAccessor.getGetter() : (D) propertyAccessor.getSetter();
|
||||
}
|
||||
return getAccessor(descriptor, AccessorKind.JVM_DEFAULT_COMPATIBILITY, null, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget);
|
||||
return getAccessor(descriptor, AccessorKind.NORMAL, null, superCallTarget);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -430,7 +445,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D getAccessor(
|
||||
@NotNull D possiblySubstitutedDescriptor,
|
||||
@NotNull FieldAccessorKind accessorKind,
|
||||
@NotNull AccessorKind accessorKind,
|
||||
@Nullable KotlinType delegateType,
|
||||
@Nullable ClassDescriptor superCallTarget
|
||||
) {
|
||||
@@ -445,7 +460,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D getAccessor(
|
||||
@NotNull D possiblySubstitutedDescriptor,
|
||||
@NotNull FieldAccessorKind accessorKind,
|
||||
@NotNull AccessorKind accessorKind,
|
||||
@Nullable KotlinType delegateType,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
boolean getterAccessorRequired,
|
||||
@@ -468,7 +483,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
if (accessors.containsKey(key)) {
|
||||
AccessorForCallableDescriptor<?> accessor = accessors.get(key);
|
||||
assert accessorKind == FieldAccessorKind.NORMAL ||
|
||||
assert accessorKind == AccessorKind.NORMAL ||
|
||||
accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context";
|
||||
return (D) accessor;
|
||||
}
|
||||
@@ -476,16 +491,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind);
|
||||
AccessorForCallableDescriptor<?> accessor;
|
||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||
accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix);
|
||||
accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix, accessorKind);
|
||||
}
|
||||
else if (descriptor instanceof ClassConstructorDescriptor) {
|
||||
accessor = new AccessorForConstructorDescriptor((ClassConstructorDescriptor) descriptor, contextDescriptor, superCallTarget);
|
||||
accessor = new AccessorForConstructorDescriptor((ClassConstructorDescriptor) descriptor, contextDescriptor, superCallTarget, accessorKind);
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (accessorKind == FieldAccessorKind.NORMAL) {
|
||||
if (accessorKind == AccessorKind.NORMAL || accessorKind == AccessorKind.JVM_DEFAULT_COMPATIBILITY) {
|
||||
AccessorForPropertyDescriptorFactory factory =
|
||||
new AccessorForPropertyDescriptorFactory(propertyDescriptor, contextDescriptor, superCallTarget, nameSuffix);
|
||||
new AccessorForPropertyDescriptorFactory(propertyDescriptor, contextDescriptor, superCallTarget, nameSuffix, accessorKind);
|
||||
propertyAccessorFactories.put(key, factory);
|
||||
|
||||
// Record worst case accessor for accessor methods generation.
|
||||
@@ -496,8 +511,8 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
accessor = new AccessorForPropertyBackingField(
|
||||
propertyDescriptor, contextDescriptor, delegateType,
|
||||
accessorKind == FieldAccessorKind.IN_CLASS_COMPANION ? null : propertyDescriptor.getExtensionReceiverParameter(),
|
||||
accessorKind == FieldAccessorKind.IN_CLASS_COMPANION ? null : propertyDescriptor.getDispatchReceiverParameter(),
|
||||
accessorKind == AccessorKind.IN_CLASS_COMPANION ? null : propertyDescriptor.getExtensionReceiverParameter(),
|
||||
accessorKind == AccessorKind.IN_CLASS_COMPANION ? null : propertyDescriptor.getDispatchReceiverParameter(),
|
||||
nameSuffix, accessorKind
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.IrExpressionLambda
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
@@ -370,14 +369,7 @@ class MethodInliner(
|
||||
)
|
||||
|
||||
val transformationVisitor = object : MethodVisitor(API, transformedNode) {
|
||||
/*
|
||||
Ignore simple @InlineOnly functions such as 'error()' or 'assert()' without lambda parameters,
|
||||
as we likely to want to have a line number from the call site in a stack trace.
|
||||
*/
|
||||
private val GENERATE_LINE_NUMBERS = GENERATE_SMAP && (inlineOnlySmapSkipper == null || run {
|
||||
val callableDescriptor = inliningContext.root.sourceCompilerForInline.callableDescriptor
|
||||
callableDescriptor != null && callableDescriptor.valueParameters.any { it.type.isFunctionType }
|
||||
})
|
||||
private val GENERATE_DEBUG_INFO = GENERATE_SMAP && inlineOnlySmapSkipper == null
|
||||
|
||||
private val isInliningLambda = nodeRemapper.isInsideInliningLambda
|
||||
|
||||
@@ -409,7 +401,7 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
override fun visitLineNumber(line: Int, start: Label) {
|
||||
if (isInliningLambda || GENERATE_LINE_NUMBERS) {
|
||||
if (isInliningLambda || GENERATE_DEBUG_INFO) {
|
||||
super.visitLineNumber(line, start)
|
||||
}
|
||||
}
|
||||
@@ -437,7 +429,7 @@ class MethodInliner(
|
||||
override fun visitLocalVariable(
|
||||
name: String, desc: String, signature: String?, start: Label, end: Label, index: Int
|
||||
) {
|
||||
if (isInliningLambda || (GENERATE_SMAP && inlineOnlySmapSkipper == null)) {
|
||||
if (isInliningLambda || GENERATE_DEBUG_INFO) {
|
||||
val varSuffix = if (inliningContext.isRoot && !isFakeLocalVariableForInline(name)) INLINE_FUN_VAR_SUFFIX else ""
|
||||
val varName = if (!varSuffix.isEmpty() && name == "this") name + "_" else name
|
||||
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index))
|
||||
|
||||
@@ -48,8 +48,6 @@ interface SourceCompilerForInline {
|
||||
|
||||
val callElement: Any
|
||||
|
||||
val callableDescriptor: CallableDescriptor?
|
||||
|
||||
val lookupLocation: LookupLocation
|
||||
|
||||
val callElementText: String
|
||||
@@ -105,8 +103,6 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
override val lookupLocation = KotlinLookupLocation(callElement)
|
||||
|
||||
override val callableDescriptor: CallableDescriptor?
|
||||
get() = (this.context as? MethodContext)?.functionDescriptor
|
||||
|
||||
override val callElementText by lazy {
|
||||
callElement.text
|
||||
@@ -203,7 +199,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
else -> FunctionGenerationStrategy.FunctionDefault(state, expression as KtDeclarationWithBody)
|
||||
}
|
||||
|
||||
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen)
|
||||
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode)
|
||||
|
||||
if (isLambda) {
|
||||
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.*
|
||||
|
||||
private val EXTERNAL_SOURCES_KINDS = arrayOf(
|
||||
JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL,
|
||||
JvmDeclarationOriginKind.DEFAULT_IMPL_DELEGATION_TO_SUPERINTERFACE_DEFAULT_IMPL,
|
||||
JvmDeclarationOriginKind.DELEGATION,
|
||||
JvmDeclarationOriginKind.BRIDGE
|
||||
)
|
||||
|
||||
@@ -226,6 +226,8 @@ class GenerationState private constructor(
|
||||
JVMConstructorCallNormalizationMode.DEFAULT
|
||||
)
|
||||
|
||||
val jvmDefaultMode = languageVersionSettings.getFlag(AnalysisFlag.jvmDefaultMode)
|
||||
|
||||
init {
|
||||
val disableOptimization = configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false)
|
||||
|
||||
|
||||
@@ -150,6 +150,16 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
};
|
||||
|
||||
public KotlinTypeMapper(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull ClassBuilderMode classBuilderMode,
|
||||
@NotNull IncompatibleClassTracker incompatibleClassTracker,
|
||||
@NotNull String moduleName,
|
||||
boolean isJvm8Target
|
||||
) {
|
||||
this(bindingContext, classBuilderMode, incompatibleClassTracker, moduleName, isJvm8Target, false);
|
||||
}
|
||||
|
||||
public KotlinTypeMapper(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull ClassBuilderMode classBuilderMode,
|
||||
|
||||
@@ -19,19 +19,22 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
enum class FieldAccessorKind(val suffix: String) {
|
||||
enum class AccessorKind(val suffix: String) {
|
||||
NORMAL("p"),
|
||||
IN_CLASS_COMPANION("cp"),
|
||||
FIELD_FROM_LOCAL("lp"),
|
||||
LATEINIT_INTRINSIC("li"),
|
||||
JVM_DEFAULT_COMPATIBILITY("jd")
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.getJvmName() =
|
||||
DescriptorUtils.getJvmName(this) ?: name.asString()
|
||||
DescriptorUtils.getJvmName(this) ?: name.asString()
|
||||
|
||||
fun getAccessorNameSuffix(
|
||||
descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?, accessorKind: FieldAccessorKind
|
||||
descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?, accessorKind: AccessorKind
|
||||
): String {
|
||||
if (accessorKind == AccessorKind.JVM_DEFAULT_COMPATIBILITY) return descriptor.getJvmName() + "$" + AccessorKind.JVM_DEFAULT_COMPATIBILITY.suffix
|
||||
|
||||
val suffix = when (descriptor) {
|
||||
is ConstructorDescriptor ->
|
||||
return "will be ignored"
|
||||
@@ -40,8 +43,7 @@ fun getAccessorNameSuffix(
|
||||
is PropertyDescriptor ->
|
||||
descriptor.getJvmName() + "$" + accessorKind.suffix
|
||||
else ->
|
||||
throw UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor)
|
||||
throw UnsupportedOperationException("Do not know how to create accessor for descriptor $descriptor")
|
||||
}
|
||||
|
||||
return if (superCallDescriptor == null) suffix else "$suffix\$s${superCallDescriptor.name.asString().hashCode()}"
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ dependencies {
|
||||
testCompile(projectTests(":generators:test-generator"))
|
||||
testCompile(project(":compiler:ir.ir2cfg"))
|
||||
testCompile(project(":compiler:ir.tree")) // used for deepCopyWithSymbols call that is removed by proguard from the compiler TODO: make it more straightforward
|
||||
testCompile(project(":kotlin-scripting-compiler"))
|
||||
testCompile(project(":kotlin-scripting-misc"))
|
||||
testCompile(project(":kotlin-script-util"))
|
||||
testCompileOnly(projectRuntimeJar(":kotlin-daemon-client"))
|
||||
testCompileOnly(project(":kotlin-reflect-api"))
|
||||
otherCompilerModules.forEach {
|
||||
|
||||
@@ -25,7 +25,8 @@ import java.util.*
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
companion object {
|
||||
@JvmStatic private val serialVersionUID = 0L
|
||||
@JvmStatic
|
||||
private val serialVersionUID = 0L
|
||||
|
||||
const val PLUGIN_OPTION_FORMAT = "plugin:<pluginId>:<optionName>=<value>"
|
||||
|
||||
@@ -39,9 +40,9 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
|
||||
@GradleOption(DefaultValues.LanguageVersions::class)
|
||||
@Argument(
|
||||
value = "-language-version",
|
||||
valueDescription = "<version>",
|
||||
description = "Provide source compatibility with specified language version"
|
||||
value = "-language-version",
|
||||
valueDescription = "<version>",
|
||||
description = "Provide source compatibility with specified language version"
|
||||
)
|
||||
var languageVersion: String? by FreezableVar(null)
|
||||
|
||||
@@ -50,16 +51,16 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
|
||||
@GradleOption(DefaultValues.LanguageVersions::class)
|
||||
@Argument(
|
||||
value = "-api-version",
|
||||
valueDescription = "<version>",
|
||||
description = "Allow to use declarations only from the specified version of bundled libraries"
|
||||
value = "-api-version",
|
||||
valueDescription = "<version>",
|
||||
description = "Allow to use declarations only from the specified version of bundled libraries"
|
||||
)
|
||||
var apiVersion: String? by FreezableVar(null)
|
||||
|
||||
@Argument(
|
||||
value = "-kotlin-home",
|
||||
valueDescription = "<path>",
|
||||
description = "Path to Kotlin compiler home directory, used for runtime libraries discovery"
|
||||
value = "-kotlin-home",
|
||||
valueDescription = "<path>",
|
||||
description = "Path to Kotlin compiler home directory, used for runtime libraries discovery"
|
||||
)
|
||||
var kotlinHome: String? by FreezableVar(null)
|
||||
|
||||
@@ -72,12 +73,15 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
var noInline: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xskip-metadata-version-check",
|
||||
description = "Load classes with bad metadata version anyway (incl. pre-release classes)"
|
||||
value = "-Xskip-metadata-version-check",
|
||||
description = "Load classes with bad metadata version anyway (incl. pre-release classes)"
|
||||
)
|
||||
var skipMetadataVersionCheck: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(value = "-Xallow-kotlin-package", description = "Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info")
|
||||
@Argument(
|
||||
value = "-Xallow-kotlin-package",
|
||||
description = "Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info"
|
||||
)
|
||||
var allowKotlinPackage: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(value = "-Xreport-output-files", description = "Report source to output files mapping")
|
||||
@@ -93,34 +97,34 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
var noCheckActual: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xintellij-plugin-root",
|
||||
valueDescription = "<path>",
|
||||
description = "Path to the kotlin-compiler.jar or directory where IntelliJ configuration files can be found"
|
||||
value = "-Xintellij-plugin-root",
|
||||
valueDescription = "<path>",
|
||||
description = "Path to the kotlin-compiler.jar or directory where IntelliJ configuration files can be found"
|
||||
)
|
||||
var intellijPluginRoot: String? by FreezableVar(null)
|
||||
|
||||
@Argument(
|
||||
value = "-Xcoroutines",
|
||||
valueDescription = "{enable|warn|error}",
|
||||
description = "Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier"
|
||||
value = "-Xcoroutines",
|
||||
valueDescription = "{enable|warn|error}",
|
||||
description = "Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier"
|
||||
)
|
||||
var coroutinesState: String? by FreezableVar(WARN)
|
||||
|
||||
@Argument(
|
||||
value = "-Xnew-inference",
|
||||
description = "Enable new experimental generic type inference algorithm"
|
||||
value = "-Xnew-inference",
|
||||
description = "Enable new experimental generic type inference algorithm"
|
||||
)
|
||||
var newInference: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xlegacy-smart-cast-after-try",
|
||||
description = "Allow var smart casts despite assignment in try block"
|
||||
value = "-Xlegacy-smart-cast-after-try",
|
||||
description = "Allow var smart casts despite assignment in try block"
|
||||
)
|
||||
var legacySmartCastAfterTry: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xeffect-system",
|
||||
description = "Enable experimental language feature: effect system"
|
||||
value = "-Xeffect-system",
|
||||
description = "Enable experimental language feature: effect system"
|
||||
)
|
||||
var effectSystem: Boolean by FreezableVar(false)
|
||||
|
||||
@@ -131,9 +135,9 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
var readDeserializedContracts: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xexperimental",
|
||||
valueDescription = "<fq.name>",
|
||||
description = "Enable and propagate usages of experimental API for marker annotation with the given fully qualified name"
|
||||
value = "-Xexperimental",
|
||||
valueDescription = "<fq.name>",
|
||||
description = "Enable and propagate usages of experimental API for marker annotation with the given fully qualified name"
|
||||
)
|
||||
var experimental: Array<String>? by FreezableVar(null)
|
||||
|
||||
@@ -160,6 +164,16 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
)
|
||||
var dumpPerf: String? by FreezableVar(null)
|
||||
|
||||
@Argument(
|
||||
value = "-Xprogressive",
|
||||
description = "Enable compiler progressive mode.\n" +
|
||||
"In this mode, deprecations and bug fixes for unstable code take effect immediately,\n" +
|
||||
"instead of going through graceful migration cycle.\n" +
|
||||
"Code, written in progressive mode is backward compatible; however, code written in\n" +
|
||||
"non-progressive mode may cause compilation errors in progressive mode."
|
||||
)
|
||||
var progressiveMode by FreezableVar(false)
|
||||
|
||||
open fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
|
||||
return HashMap<AnalysisFlag<*>, Any>().apply {
|
||||
put(AnalysisFlag.skipMetadataVersionCheck, skipMetadataVersionCheck)
|
||||
@@ -180,7 +194,8 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
when (coroutinesState) {
|
||||
CommonCompilerArguments.ERROR -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED_WITH_ERROR)
|
||||
CommonCompilerArguments.ENABLE -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED)
|
||||
CommonCompilerArguments.WARN -> {}
|
||||
CommonCompilerArguments.WARN -> {
|
||||
}
|
||||
else -> {
|
||||
val message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + coroutinesState
|
||||
collector.report(CompilerMessageSeverity.ERROR, message, null)
|
||||
@@ -207,8 +222,42 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
if (properIeee754Comparisons) {
|
||||
put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (progressiveMode) {
|
||||
LanguageFeature.values().filter { it.kind.enabledInProgressiveMode }.forEach {
|
||||
// Don't overwrite other settings: users may want to turn off some particular
|
||||
// breaking change manually instead of turning off whole progressive mode
|
||||
if (!contains(it)) put(it, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
}
|
||||
|
||||
// Internal arguments should go last, because it may be useful to override
|
||||
// some feature state via -XX (even if some -X flags were passed)
|
||||
if (internalArguments.isNotEmpty()) {
|
||||
configureLanguageFeaturesFromInternalArgs(collector)
|
||||
}
|
||||
}
|
||||
|
||||
private fun HashMap<LanguageFeature, LanguageFeature.State>.configureLanguageFeaturesFromInternalArgs(collector: MessageCollector) {
|
||||
val languageSettingsParser = LanguageSettingsParser()
|
||||
val featuresThatForcePreReleaseBinaries = mutableListOf<LanguageFeature>()
|
||||
|
||||
for (argument in internalArguments) {
|
||||
val (feature, state) = languageSettingsParser.parseInternalArgument(argument, collector) ?: continue
|
||||
put(feature, state)
|
||||
if (state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()) {
|
||||
featuresThatForcePreReleaseBinaries += feature
|
||||
}
|
||||
}
|
||||
|
||||
if (featuresThatForcePreReleaseBinaries.isNotEmpty()) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"Following manually enabled features will force generation of pre-release binaries: ${featuresThatForcePreReleaseBinaries.joinToString()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun configureLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
|
||||
|
||||
// If only "-api-version" is specified, language version is assumed to be the latest stable
|
||||
@@ -232,6 +281,14 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
)
|
||||
}
|
||||
|
||||
if (progressiveMode && languageVersion < LanguageVersion.LATEST_STABLE) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"'-Xprogressive' meaningful only for latest language version (${LanguageVersion.LATEST_STABLE}), while this build uses $languageVersion\n" +
|
||||
"Behaviour of compiler in such mode is undefined; please, consider moving to the latest stable version or turning off progressive mode."
|
||||
)
|
||||
}
|
||||
|
||||
return LanguageVersionSettingsImpl(
|
||||
languageVersion,
|
||||
ApiVersion.createByLanguageVersion(apiVersion),
|
||||
|
||||
@@ -20,12 +20,14 @@ import java.io.Serializable
|
||||
|
||||
abstract class CommonToolArguments : Freezable(), Serializable {
|
||||
companion object {
|
||||
@JvmStatic private val serialVersionUID = 0L
|
||||
@JvmStatic
|
||||
private val serialVersionUID = 0L
|
||||
}
|
||||
|
||||
var freeArgs: List<String> by FreezableVar(emptyList())
|
||||
|
||||
@Transient var errors: ArgumentParseErrors = ArgumentParseErrors()
|
||||
@Transient
|
||||
var errors: ArgumentParseErrors = ArgumentParseErrors()
|
||||
|
||||
@Argument(value = "-help", shortName = "-h", description = "Print a synopsis of standard options")
|
||||
var help: Boolean by FreezableVar(false)
|
||||
@@ -47,4 +49,6 @@ abstract class CommonToolArguments : Freezable(), Serializable {
|
||||
@GradleOption(DefaultValues.BooleanFalseDefault::class)
|
||||
@Argument(value = "-Werror", description = "Report an error if there are any warnings")
|
||||
var allWarningsAsErrors: Boolean by FreezableVar(false)
|
||||
|
||||
var internalArguments: List<String> by FreezableVar(emptyList())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.arguments
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.InternalArgumentParser.Companion.INTERNAL_ARGUMENT_PREFIX
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
|
||||
/**
|
||||
* Arguments that can drastically change compiler behavior,
|
||||
* breaking stability/compatibility.
|
||||
*
|
||||
* Internal arguments are split into 'families', each family
|
||||
* with its own set of arguments, settings and parsing rules
|
||||
*
|
||||
* Internal arguments start with '-XX' prefix, followed by
|
||||
* family name. Everything after that is handled by the corresponding
|
||||
* parser of that particular family.
|
||||
*/
|
||||
interface InternalArgumentParser<A : InternalArgument> {
|
||||
// Should be fast
|
||||
fun canParse(arg: String): Boolean
|
||||
|
||||
fun parseInternalArgument(arg: String, messageCollector: MessageCollector): A?
|
||||
|
||||
companion object {
|
||||
internal const val INTERNAL_ARGUMENT_PREFIX = "-XX"
|
||||
|
||||
internal val PARSERS: List<InternalArgumentParser<*>> = listOf(
|
||||
LanguageSettingsParser()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractInternalArgumentParser<A : InternalArgument>(familyName: String) : InternalArgumentParser<A> {
|
||||
private val wholePrefix: String = INTERNAL_ARGUMENT_PREFIX + familyName
|
||||
|
||||
override fun canParse(arg: String): Boolean = arg.startsWith(wholePrefix)
|
||||
|
||||
override fun parseInternalArgument(arg: String, messageCollector: MessageCollector): A? {
|
||||
if (!arg.startsWith(wholePrefix)) return null
|
||||
|
||||
return parseTail(arg.removePrefix(wholePrefix), arg, messageCollector)
|
||||
}
|
||||
|
||||
abstract fun parseTail(tail: String, wholeArgument: String, messageCollector: MessageCollector): A?
|
||||
}
|
||||
|
||||
|
||||
// Arguments of form '-XXLanguage:+LanguageFeature' or '-XXLanguage:-LanguageFeature', which enable or disable corresponding LanguageFeature.
|
||||
class LanguageSettingsParser : AbstractInternalArgumentParser<ManualLanguageFeatureSetting>("Language") {
|
||||
|
||||
// Expected tail form: ':(+|-)<language feature name>'
|
||||
override fun parseTail(tail: String, wholeArgument: String, messageCollector: MessageCollector): ManualLanguageFeatureSetting? {
|
||||
fun reportAndReturnNull(message: String): Nothing? {
|
||||
messageCollector.report(CompilerMessageSeverity.STRONG_WARNING, message)
|
||||
return null
|
||||
}
|
||||
|
||||
val colon = tail.getOrNull(0) ?: return reportAndReturnNull("Incorrect internal argument syntax, missing colon: $wholeArgument")
|
||||
|
||||
val modificator = tail.getOrNull(1)
|
||||
val languageFeatureState = when (modificator) {
|
||||
'+' -> LanguageFeature.State.ENABLED
|
||||
|
||||
'-' -> LanguageFeature.State.DISABLED
|
||||
|
||||
else -> return reportAndReturnNull("Incorrect internal argument syntax, missing modificator: $wholeArgument")
|
||||
}
|
||||
|
||||
val languageFeatureName = tail.substring(2)
|
||||
if (languageFeatureName.isEmpty()) return reportAndReturnNull("Empty language feature name for internal argument '$wholeArgument'")
|
||||
|
||||
val languageFeature = LanguageFeature.fromString(languageFeatureName)
|
||||
?: return reportAndReturnNull("Unknown language feature '$languageFeatureName' in passed internal argument '$wholeArgument'")
|
||||
|
||||
return ManualLanguageFeatureSetting(languageFeature, languageFeatureState)
|
||||
}
|
||||
}
|
||||
|
||||
interface InternalArgument
|
||||
|
||||
data class ManualLanguageFeatureSetting(val languageFeature: LanguageFeature, val state: LanguageFeature.State) : InternalArgument
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.arguments
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.AnalysisFlag
|
||||
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.*
|
||||
|
||||
class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
companion object {
|
||||
@@ -225,8 +223,17 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var noExceptionOnExplicitEqualsForBoxedNull by FreezableVar(false)
|
||||
|
||||
@Argument(value = "-Xenable-jvm-default", description = "Allow to use '@JvmDefault' for JVM default method support")
|
||||
var enableJvmDefault: Boolean by FreezableVar(false)
|
||||
@Argument(
|
||||
value = "-Xjvm-default",
|
||||
valueDescription = "{disable|enable|compatibility}",
|
||||
description = "Allow to use '@JvmDefault' annotation for JVM default method support.\n" +
|
||||
"-Xjvm-default=disable Prohibit usages of @JvmDefault\n" +
|
||||
"-Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method\n" +
|
||||
" in the interface (annotating an existing method can break binary compatibility)\n" +
|
||||
"-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor\n" +
|
||||
" in the 'DefaultImpls' class in addition to the interface method"
|
||||
)
|
||||
var jvmDefault: String by FreezableVar(JvmDefaultMode.DEFAULT.description)
|
||||
|
||||
@Argument(value = "-Xdisable-default-scripting-plugin", description = "Do not enable scripting plugin by default")
|
||||
var disableDefaultScriptingPlugin: Boolean by FreezableVar(false)
|
||||
@@ -243,7 +250,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
jsr305,
|
||||
supportCompatqualCheckerFrameworkAnnotations
|
||||
)
|
||||
result[AnalysisFlag.enableJvmDefault] = enableJvmDefault
|
||||
JvmDefaultMode.fromStringOrNull(jvmDefault)?.let { result[AnalysisFlag.jvmDefaultMode] = it }
|
||||
?: collector.report(
|
||||
CompilerMessageSeverity.ERROR,
|
||||
"Unknown @JvmDefault mode: $jvmDefault, " +
|
||||
"supported modes: ${JvmDefaultMode.values().map { it.description }}"
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -19,24 +19,23 @@ package org.jetbrains.kotlin.cli.common.arguments
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class Argument(
|
||||
val value: String,
|
||||
val shortName: String = "",
|
||||
val deprecatedName: String = "",
|
||||
val delimiter: String = ",",
|
||||
val valueDescription: String = "",
|
||||
val description: String
|
||||
val value: String,
|
||||
val shortName: String = "",
|
||||
val deprecatedName: String = "",
|
||||
val delimiter: String = ",",
|
||||
val valueDescription: String = "",
|
||||
val description: String
|
||||
)
|
||||
|
||||
val Argument.isAdvanced: Boolean
|
||||
get() = value.startsWith(ADVANCED_ARGUMENT_PREFIX) && value.length > ADVANCED_ARGUMENT_PREFIX.length
|
||||
|
||||
private val ADVANCED_ARGUMENT_PREFIX = "-X"
|
||||
private val FREE_ARGS_DELIMITER = "--"
|
||||
private const val ADVANCED_ARGUMENT_PREFIX = "-X"
|
||||
private const val FREE_ARGS_DELIMITER = "--"
|
||||
|
||||
data class ArgumentParseErrors(
|
||||
val unknownArgs: MutableList<String> = SmartList<String>(),
|
||||
@@ -53,11 +52,18 @@ data class ArgumentParseErrors(
|
||||
// Arguments where [Argument.deprecatedName] was used; the key is the deprecated name, the value is the new name ([Argument.value])
|
||||
val deprecatedArguments: MutableMap<String, String> = mutableMapOf(),
|
||||
|
||||
var argumentWithoutValue: String? = null
|
||||
var argumentWithoutValue: String? = null,
|
||||
|
||||
val argfileErrors: MutableList<String> = SmartList()
|
||||
)
|
||||
|
||||
// Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors].
|
||||
fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, result: A) {
|
||||
val preprocessed = preprocessCommandLineArguments(args, result.errors)
|
||||
parsePreprocessedCommandLineArguments(preprocessed, result)
|
||||
}
|
||||
|
||||
private fun <A : CommonToolArguments> parsePreprocessedCommandLineArguments(args: List<String>, result: A) {
|
||||
data class ArgumentField(val property: KMutableProperty1<A, Any?>, val argument: Argument)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -90,7 +96,7 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
return true
|
||||
}
|
||||
|
||||
if (deprecatedName != null && arg.startsWith(deprecatedName + "=")) {
|
||||
if (deprecatedName != null && arg.startsWith("$deprecatedName=")) {
|
||||
errors.deprecatedArguments[deprecatedName] = argument.value
|
||||
return true
|
||||
}
|
||||
@@ -102,6 +108,7 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
}
|
||||
|
||||
val freeArgs = ArrayList<String>()
|
||||
val internalArguments = ArrayList<String>()
|
||||
|
||||
var i = 0
|
||||
loop@ while (i < args.size) {
|
||||
@@ -116,6 +123,21 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
continue
|
||||
}
|
||||
|
||||
if (arg.startsWith(InternalArgumentParser.INTERNAL_ARGUMENT_PREFIX)) {
|
||||
val matchingParsers = InternalArgumentParser.PARSERS.filter { it.canParse(arg) }
|
||||
assert(matchingParsers.size <= 1) { "Internal error: internal argument $arg can be ambiguously parsed by parsers ${matchingParsers.joinToString()}" }
|
||||
|
||||
val parser = matchingParsers.firstOrNull()
|
||||
|
||||
if (parser == null) {
|
||||
errors.unknownExtraFlags += arg
|
||||
} else {
|
||||
internalArguments.add(arg)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
val argumentField = properties.firstOrNull { it.matches(arg) }
|
||||
if (argumentField == null) {
|
||||
when {
|
||||
@@ -145,14 +167,16 @@ fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, resu
|
||||
}
|
||||
|
||||
if ((argumentField.property.returnType.classifier as? KClass<*>)?.java?.isArray == false
|
||||
&& !visitedArgs.add(argument.value) && value is String && property.get(result) != value) {
|
||||
errors.duplicateArguments.put(argument.value, value)
|
||||
&& !visitedArgs.add(argument.value) && value is String && property.get(result) != value
|
||||
) {
|
||||
errors.duplicateArguments[argument.value] = value
|
||||
}
|
||||
|
||||
updateField(property, result, value, argument.delimiter)
|
||||
}
|
||||
|
||||
result.freeArgs += freeArgs
|
||||
result.internalArguments += internalArguments
|
||||
}
|
||||
|
||||
private fun <A : CommonToolArguments> updateField(property: KMutableProperty1<A, Any?>, result: A, value: Any, delimiter: String) {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.arguments
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.io.Reader
|
||||
|
||||
private const val EXPERIMENTAL_ARGFILE_ARGUMENT = "-Xargfile"
|
||||
|
||||
private const val QUOTATION_MARK = '"'
|
||||
private const val BACKSLASH = '\\'
|
||||
private const val WHITESPACE = ' '
|
||||
private const val NEWLINE = '\n'
|
||||
|
||||
/**
|
||||
* Performs initial preprocessing of arguments, passed to the compiler.
|
||||
* This is done prior to *any* arguments parsing, and result of preprocessing
|
||||
* will be used instead of actual passed arguments.
|
||||
*/
|
||||
internal fun preprocessCommandLineArguments(args: List<String>, errors: ArgumentParseErrors): List<String> =
|
||||
args.flatMap {
|
||||
if (it.isArgumentForArgfile)
|
||||
File(it.argfilePath).expand(errors)
|
||||
else
|
||||
listOf(it)
|
||||
}
|
||||
|
||||
private fun File.expand(errors: ArgumentParseErrors): List<String> {
|
||||
return try {
|
||||
bufferedReader(Charsets.UTF_8).use {
|
||||
generateSequence { it.parseNextArgument() }.toList()
|
||||
}
|
||||
} catch (e: FileNotFoundException) {
|
||||
// Process FNFE separately to render absolutePath in error message
|
||||
errors.argfileErrors += "Argfile not found: $absolutePath"
|
||||
emptyList()
|
||||
} catch (e: IOException) {
|
||||
errors.argfileErrors += "Error while reading argfile: $e"
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun Reader.parseNextArgument(): String? {
|
||||
val sb = StringBuilder()
|
||||
|
||||
var r = nextChar()
|
||||
while (r != null && (r == WHITESPACE || r == NEWLINE)) {
|
||||
r = nextChar()
|
||||
}
|
||||
|
||||
loop@ while (r != null) {
|
||||
when (r) {
|
||||
WHITESPACE, NEWLINE -> break@loop
|
||||
QUOTATION_MARK -> consumeRestOfEscapedSequence(sb)
|
||||
BACKSLASH -> nextChar()?.apply(sb::append)
|
||||
else -> sb.append(r)
|
||||
}
|
||||
|
||||
r = nextChar()
|
||||
}
|
||||
|
||||
return sb.toString().takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
private fun Reader.consumeRestOfEscapedSequence(sb: StringBuilder) {
|
||||
var ch = nextChar()
|
||||
while (ch != null && ch != QUOTATION_MARK) {
|
||||
if (ch == BACKSLASH) nextChar()?.apply(sb::append) else sb.append(ch)
|
||||
ch = nextChar()
|
||||
}
|
||||
}
|
||||
|
||||
private fun Reader.nextChar(): Char? =
|
||||
read().takeUnless { it == -1 }?.toChar()
|
||||
|
||||
private val String.argfilePath: String
|
||||
get() = removePrefix("$EXPERIMENTAL_ARGFILE_ARGUMENT=")
|
||||
|
||||
// Note that currently we use only experimental syntax for passing argfiles
|
||||
// In 1.3 we can support also javac-like syntax `@argfile`
|
||||
private val String.isArgumentForArgfile: Boolean
|
||||
get() = startsWith("$EXPERIMENTAL_ARGFILE_ARGUMENT=")
|
||||
@@ -17,10 +17,7 @@
|
||||
package org.jetbrains.kotlin.cli.common
|
||||
|
||||
import org.fusesource.jansi.AnsiConsole
|
||||
import org.jetbrains.kotlin.cli.common.arguments.ArgumentParseErrors
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.validateArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
|
||||
@@ -38,10 +35,10 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
|
||||
protected fun exec(
|
||||
errStream: PrintStream,
|
||||
services: Services,
|
||||
messageRenderer: MessageRenderer,
|
||||
args: Array<out String>
|
||||
errStream: PrintStream,
|
||||
services: Services,
|
||||
messageRenderer: MessageRenderer,
|
||||
args: Array<out String>
|
||||
): ExitCode {
|
||||
val arguments = createArguments()
|
||||
parseCommandLineArguments(args.asList(), arguments)
|
||||
@@ -67,8 +64,7 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
|
||||
return exec(collector, services, arguments)
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
errStream.print(messageRenderer.renderConclusion())
|
||||
|
||||
if (PlainTextMessageRenderer.COLOR_ENABLED) {
|
||||
@@ -84,12 +80,11 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
|
||||
val fixedMessageCollector = if (arguments.suppressWarnings && !arguments.allWarningsAsErrors) {
|
||||
FilteringMessageCollector(messageCollector, Predicate.isEqual(CompilerMessageSeverity.WARNING))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
messageCollector
|
||||
}
|
||||
|
||||
reportArgumentParseProblems(fixedMessageCollector, arguments.errors)
|
||||
reportArgumentParseProblems(fixedMessageCollector, arguments)
|
||||
return execImpl(fixedMessageCollector, services, arguments)
|
||||
}
|
||||
|
||||
@@ -117,13 +112,16 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportArgumentParseProblems(collector: MessageCollector, errors: ArgumentParseErrors) {
|
||||
private fun reportArgumentParseProblems(collector: MessageCollector, arguments: A) {
|
||||
val errors = arguments.errors
|
||||
for (flag in errors.unknownExtraFlags) {
|
||||
collector.report(STRONG_WARNING, "Flag is not supported by this version of the compiler: $flag")
|
||||
}
|
||||
for (argument in errors.extraArgumentsPassedInObsoleteForm) {
|
||||
collector.report(STRONG_WARNING, "Advanced option value is passed in an obsolete form. Please use the '=' character " +
|
||||
"to specify the value: $argument=...")
|
||||
collector.report(
|
||||
STRONG_WARNING, "Advanced option value is passed in an obsolete form. Please use the '=' character " +
|
||||
"to specify the value: $argument=..."
|
||||
)
|
||||
}
|
||||
for ((key, value) in errors.duplicateArguments) {
|
||||
collector.report(STRONG_WARNING, "Argument $key is passed multiple times. Only the last value will be used: $value")
|
||||
@@ -131,6 +129,20 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
for ((deprecatedName, newName) in errors.deprecatedArguments) {
|
||||
collector.report(STRONG_WARNING, "Argument $deprecatedName is deprecated. Please use $newName instead")
|
||||
}
|
||||
if (arguments.internalArguments.isNotEmpty()) {
|
||||
collector.report(
|
||||
STRONG_WARNING,
|
||||
"ATTENTION!\n" +
|
||||
"This build uses internal compiler arguments:\n" +
|
||||
arguments.internalArguments.joinToString(prefix = "\n", postfix = "\n\n", separator = "\n") +
|
||||
"This mode is strictly prohibited for production use,\n" +
|
||||
"as no stability/compatibility guarantees are given on\n" +
|
||||
"compiler or generated code. Use it at your own risk!\n"
|
||||
)
|
||||
}
|
||||
for (argfileError in errors.argfileErrors) {
|
||||
collector.report(STRONG_WARNING, argfileError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <A : CommonToolArguments> printVersionIfNeeded(messageCollector: MessageCollector, arguments: A) {
|
||||
@@ -166,11 +178,10 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode {
|
||||
try {
|
||||
return compiler.exec(System.err, *args)
|
||||
}
|
||||
catch (e: CompileEnvironmentException) {
|
||||
} catch (e: CompileEnvironmentException) {
|
||||
System.err.println(e.message)
|
||||
return ExitCode.INTERNAL_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.common.script
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.script.findScriptDefinition
|
||||
import org.jetbrains.kotlin.script.*
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
@@ -28,7 +28,7 @@ import kotlin.concurrent.write
|
||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||
|
||||
class CliScriptDependenciesProvider(
|
||||
project: Project,
|
||||
private val project: Project,
|
||||
private val scriptDefinitionProvider: ScriptDefinitionProvider
|
||||
) : ScriptDependenciesProvider {
|
||||
|
||||
@@ -47,9 +47,11 @@ class CliScriptDependenciesProvider(
|
||||
else {
|
||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
||||
if (scriptDef != null) {
|
||||
val deps = scriptContentLoader
|
||||
.loadContentsAndResolveDependencies(scriptDef, file)
|
||||
.dependencies?.adjustByDefinition(scriptDef)
|
||||
val result = scriptContentLoader.loadContentsAndResolveDependencies(scriptDef, file)
|
||||
|
||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
||||
|
||||
val deps = result.dependencies?.adjustByDefinition(scriptDef)
|
||||
|
||||
if (deps != null) {
|
||||
log.info("[kts] new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
|
||||
@@ -218,7 +218,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
override fun getPerformanceManager(): CommonCompilerPerformanceManager = performanceManager
|
||||
|
||||
private fun loadPlugins(paths: KotlinPaths?, arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration): ExitCode {
|
||||
val pluginClasspaths = arguments.pluginClasspaths?.toMutableList() ?: ArrayList()
|
||||
var pluginClasspaths: Iterable<String> = arguments.pluginClasspaths?.asIterable() ?: emptyList()
|
||||
val pluginOptions = arguments.pluginOptions?.toMutableList() ?: ArrayList()
|
||||
|
||||
if (!arguments.disableDefaultScriptingPlugin) {
|
||||
@@ -235,10 +235,12 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
if (!explicitOrLoadedScriptingPlugin) {
|
||||
val libPath = paths?.libPath?.takeIf { it.exists() } ?: File(".")
|
||||
with(PathUtil) {
|
||||
val jars = arrayOf(KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR)
|
||||
.mapNotNull { File(libPath, it).takeIf { it.exists() }?.canonicalPath }
|
||||
if (jars.size == 3) {
|
||||
pluginClasspaths.addAll(jars)
|
||||
val jars = arrayOf(
|
||||
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_JAR,
|
||||
KOTLIN_SCRIPTING_JVM_JAR, KOTLIN_SCRIPTING_MISC_JAR
|
||||
).mapNotNull { File(libPath, it).takeIf { it.exists() }?.canonicalPath }
|
||||
if (jars.size == 4) {
|
||||
pluginClasspaths = jars + pluginClasspaths
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||
}
|
||||
|
||||
private fun serializeClass(classDescriptor: ClassDescriptor) {
|
||||
val classProto = DescriptorSerializer.createTopLevel(extension).classProto(classDescriptor).build()
|
||||
val classProto = DescriptorSerializer.create(classDescriptor, extension).classProto(classDescriptor).build()
|
||||
proto.addClass_(classProto)
|
||||
|
||||
serializeClasses(classDescriptor.unsubstitutedInnerClassesScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS))
|
||||
|
||||
@@ -47,11 +47,13 @@ messages/**)
|
||||
-dontwarn javax.crypto.**
|
||||
-dontwarn java.lang.invoke.MethodHandle
|
||||
-dontwarn org.jline.builtins.Nano$Buffer
|
||||
-dontwarn net.jpountz.lz4.LZ4Factory
|
||||
-dontwarn org.jetbrains.annotations.ReadOnly
|
||||
-dontwarn org.jetbrains.annotations.Mutable
|
||||
-dontwarn com.intellij.util.io.TarUtil
|
||||
|
||||
# Depends on apache batik which has lots of dependencies
|
||||
-dontwarn com.intellij.util.SVGLoader*
|
||||
|
||||
#-libraryjars '<rtjar>'
|
||||
#-libraryjars '<jssejar>'
|
||||
#-libraryjars '<bootstrap.runtime>'
|
||||
@@ -195,6 +197,10 @@ messages/**)
|
||||
*** SKIP_FRAMES;
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.openapi.project.Project {
|
||||
** getBasePath();
|
||||
}
|
||||
|
||||
# for kotlin-android-extensions in maven
|
||||
-keep class com.intellij.openapi.module.ModuleServiceManager { public *; }
|
||||
|
||||
@@ -216,3 +222,5 @@ messages/**)
|
||||
|
||||
# remove when KT-18563 would be fixed
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
-keep class net.jpountz.lz4.* { *; }
|
||||
|
||||
@@ -194,6 +194,10 @@ messages/**)
|
||||
*** SKIP_FRAMES;
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.openapi.project.Project {
|
||||
** getBasePath();
|
||||
}
|
||||
|
||||
# for kotlin-android-extensions in maven
|
||||
-keep class com.intellij.openapi.module.ModuleServiceManager { public *; }
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ messages/**)
|
||||
-dontwarn javax.crypto.**
|
||||
-dontwarn java.lang.invoke.MethodHandle
|
||||
-dontwarn org.jline.builtins.Nano$Buffer
|
||||
-dontwarn net.jpountz.lz4.LZ4Factory
|
||||
-dontwarn org.jetbrains.annotations.ReadOnly
|
||||
-dontwarn org.jetbrains.annotations.Mutable
|
||||
-dontwarn com.intellij.util.io.TarUtil
|
||||
@@ -59,6 +58,12 @@ messages/**)
|
||||
# Depends on apache batick which has lots of dependencies
|
||||
-dontwarn com.intellij.util.SVGLoader*
|
||||
|
||||
-dontwarn org.jdom.xpath.jaxen.*
|
||||
-dontwarn com.intellij.util.io.Decompressor*
|
||||
-dontwarn org.w3c.dom.Location
|
||||
-dontwarn org.w3c.dom.Window
|
||||
|
||||
|
||||
#-libraryjars '<rtjar>'
|
||||
#-libraryjars '<jssejar>'
|
||||
#-libraryjars '<bootstrap.runtime>'
|
||||
@@ -202,6 +207,10 @@ messages/**)
|
||||
*** SKIP_FRAMES;
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.openapi.project.Project {
|
||||
** getBasePath();
|
||||
}
|
||||
|
||||
# for kotlin-android-extensions in maven
|
||||
-keep class com.intellij.openapi.module.ModuleServiceManager { public *; }
|
||||
|
||||
@@ -223,3 +232,5 @@ messages/**)
|
||||
|
||||
# remove when KT-18563 would be fixed
|
||||
-keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; }
|
||||
|
||||
-keep class net.jpountz.lz4.* { *; }
|
||||
|
||||
@@ -198,6 +198,10 @@ messages/**)
|
||||
*** SKIP_FRAMES;
|
||||
}
|
||||
|
||||
-keepclassmembers class com.intellij.openapi.project.Project {
|
||||
** getBasePath();
|
||||
}
|
||||
|
||||
# for kotlin-android-extensions in maven
|
||||
-keep class com.intellij.openapi.module.ModuleServiceManager { public *; }
|
||||
|
||||
|
||||
@@ -60,13 +60,13 @@ class IncrementalCompilationOptions(
|
||||
reportSeverity: Int,
|
||||
/** @See [CompilationResultCategory]] */
|
||||
requestedCompilationResults: Array<Int>,
|
||||
val resultDifferenceFile: File? = null,
|
||||
val friendDifferenceFile: File? = null,
|
||||
val usePreciseJavaTracking: Boolean,
|
||||
/**
|
||||
* Directories that should be cleared when IC decides to rebuild
|
||||
*/
|
||||
val localStateDirs: List<File>
|
||||
val localStateDirs: List<File>,
|
||||
val multiModuleICSettings: MultiModuleICSettings,
|
||||
val modulesInfo: IncrementalModuleInfo
|
||||
) : CompilationOptions(compilerMode, targetPlatform, reportCategories, reportSeverity, requestedCompilationResults) {
|
||||
companion object {
|
||||
const val serialVersionUID: Long = 0
|
||||
@@ -81,14 +81,22 @@ class IncrementalCompilationOptions(
|
||||
"workingDir=$workingDir, " +
|
||||
"customCacheVersionFileName='$customCacheVersionFileName', " +
|
||||
"customCacheVersion=$customCacheVersion, " +
|
||||
"resultDifferenceFile=$resultDifferenceFile, " +
|
||||
"friendDifferenceFile=$friendDifferenceFile, " +
|
||||
"multiModuleICSettings=$multiModuleICSettings, " +
|
||||
"usePreciseJavaTracking=$usePreciseJavaTracking" +
|
||||
"localStateDirs=$localStateDirs" +
|
||||
")"
|
||||
}
|
||||
}
|
||||
|
||||
data class MultiModuleICSettings(
|
||||
val buildHistoryFile: File,
|
||||
val useModuleDetection: Boolean
|
||||
) : Serializable {
|
||||
companion object {
|
||||
const val serialVersionUID: Long = 0
|
||||
}
|
||||
}
|
||||
|
||||
enum class CompilerMode : Serializable {
|
||||
NON_INCREMENTAL_COMPILER,
|
||||
INCREMENTAL_COMPILER,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.common
|
||||
|
||||
import java.io.File
|
||||
import java.rmi.RemoteException
|
||||
|
||||
interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase {
|
||||
@@ -29,14 +28,4 @@ interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase {
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun revert()
|
||||
|
||||
// ChangesRegistry
|
||||
@Throws(RemoteException::class)
|
||||
fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun unknownChanges(timestamp: Long)
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun getChanges(artifact: File, sinceTS: Long): Iterable<SimpleDirtyData>?
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.common
|
||||
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
|
||||
data class IncrementalModuleEntry(
|
||||
private val projectPath: String,
|
||||
val name: String,
|
||||
val buildDir: File,
|
||||
val buildHistoryFile: File
|
||||
) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID = 0L
|
||||
}
|
||||
}
|
||||
|
||||
class IncrementalModuleInfo(
|
||||
val projectRoot: File,
|
||||
val dirToModule: Map<File, IncrementalModuleEntry>,
|
||||
val nameToModules: Map<String, Set<IncrementalModuleEntry>>,
|
||||
val jarToClassListFile: Map<File, File>
|
||||
) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID = 0L
|
||||
}
|
||||
}
|
||||
@@ -41,8 +41,6 @@ import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.daemon.incremental.RemoteAnnotationsFileUpdater
|
||||
import org.jetbrains.kotlin.daemon.incremental.RemoteArtifactChangesProvider
|
||||
import org.jetbrains.kotlin.daemon.incremental.RemoteChangesRegistry
|
||||
import org.jetbrains.kotlin.daemon.report.CompileServicesFacadeMessageCollector
|
||||
import org.jetbrains.kotlin.daemon.report.DaemonMessageReporter
|
||||
import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapter
|
||||
@@ -50,6 +48,8 @@ import org.jetbrains.kotlin.daemon.report.RemoteICReporter
|
||||
import org.jetbrains.kotlin.incremental.*
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryAndroid
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
@@ -517,9 +517,6 @@ class CompileServiceImpl(
|
||||
ChangedFiles.Unknown()
|
||||
}
|
||||
|
||||
val artifactChanges = RemoteArtifactChangesProvider(servicesFacade)
|
||||
val changesRegistry = RemoteChangesRegistry(servicesFacade)
|
||||
|
||||
val workingDir = incrementalCompilationOptions.workingDir
|
||||
val versions = commonCacheVersions(workingDir) +
|
||||
customCacheVersion(incrementalCompilationOptions.customCacheVersion,
|
||||
@@ -527,13 +524,23 @@ class CompileServiceImpl(
|
||||
workingDir,
|
||||
enabled = true)
|
||||
|
||||
val compiler = IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions,
|
||||
reporter, annotationFileUpdater,
|
||||
artifactChanges, changesRegistry,
|
||||
buildHistoryFile = incrementalCompilationOptions.resultDifferenceFile,
|
||||
friendBuildHistoryFile = incrementalCompilationOptions.friendDifferenceFile,
|
||||
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking,
|
||||
localStateDirs = incrementalCompilationOptions.localStateDirs
|
||||
val modulesApiHistory = incrementalCompilationOptions.run {
|
||||
if (!multiModuleICSettings.useModuleDetection) {
|
||||
ModulesApiHistoryJvm(modulesInfo)
|
||||
} else {
|
||||
ModulesApiHistoryAndroid(modulesInfo)
|
||||
}
|
||||
}
|
||||
|
||||
val compiler = IncrementalJvmCompilerRunner(
|
||||
workingDir,
|
||||
javaSourceRoots,
|
||||
versions,
|
||||
reporter, annotationFileUpdater,
|
||||
buildHistoryFile = incrementalCompilationOptions.multiModuleICSettings.buildHistoryFile,
|
||||
localStateDirs = incrementalCompilationOptions.localStateDirs,
|
||||
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking,
|
||||
modulesApiHistory = modulesApiHistory
|
||||
)
|
||||
return compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles)
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
|
||||
import java.io.File
|
||||
|
||||
class RemoteArtifactChangesProvider(private val servicesFacade: IncrementalCompilerServicesFacade) : ArtifactChangesProvider {
|
||||
override fun getChanges(artifact: File, sinceTS: Long): Iterable<DirtyData>? =
|
||||
servicesFacade.getChanges(artifact, sinceTS)?.map { it.toDirtyData() }
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.daemon.incremental
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
|
||||
|
||||
internal class RemoteChangesRegistry(private val servicesFacade: IncrementalCompilerServicesFacade) : ChangesRegistry {
|
||||
override fun unknownChanges(timestamp: Long) {
|
||||
servicesFacade.unknownChanges(timestamp)
|
||||
}
|
||||
|
||||
override fun registerChanges(timestamp: Long, dirtyData: DirtyData) {
|
||||
servicesFacade.registerChanges(timestamp, dirtyData.toSimpleDirtyData())
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class JVMConfigurationKeys {
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> PARAMETERS_METADATA =
|
||||
CompilerConfigurationKey.create("Parameters metadata for java 1.8 reflection");
|
||||
|
||||
|
||||
public static final CompilerConfigurationKey<IncrementalCompilationComponents> INCREMENTAL_COMPILATION_COMPONENTS =
|
||||
CompilerConfigurationKey.create("incremental cache provider");
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.load.java.sam
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.components.SamConversionResolver
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.SamConversionTransformer
|
||||
import org.jetbrains.kotlin.synthetic.hasJavaOriginInHierarchy
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
class JvmSamConversionTransformer(
|
||||
private val samResolver: SamConversionResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) : SamConversionTransformer {
|
||||
|
||||
override fun getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType? =
|
||||
SingleAbstractMethodUtils.getFunctionTypeForSamType(possibleSamType, samResolver)?.unwrap()
|
||||
|
||||
override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean {
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) return true
|
||||
|
||||
val functionDescriptor = candidate.original as? FunctionDescriptor ?: return false
|
||||
if (functionDescriptor is TypeAliasConstructorDescriptor &&
|
||||
functionDescriptor.underlyingConstructorDescriptor is JavaClassConstructorDescriptor) return true
|
||||
|
||||
return functionDescriptor.hasJavaOriginInHierarchy()
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val enableJvmDefault = context.languageVersionSettings.getFlag(AnalysisFlag.enableJvmDefault)
|
||||
val jvmDefaultMode = context.languageVersionSettings.getFlag(AnalysisFlag.jvmDefaultMode)
|
||||
|
||||
descriptor.annotations.findAnnotation(JVM_DEFAULT_FQ_NAME)?.let { annotationDescriptor ->
|
||||
val reportOn = DescriptorToSourceUtils.getSourceFromAnnotation(annotationDescriptor) ?: declaration
|
||||
@@ -31,7 +31,7 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_NOT_IN_INTERFACE.on(reportOn))
|
||||
} else if (jvmTarget == JvmTarget.JVM_1_6) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_JVM6_TARGET.on(reportOn))
|
||||
} else if (!enableJvmDefault) {
|
||||
} else if (!jvmDefaultMode.isEnabled) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_DECLARATION.on(declaration))
|
||||
}
|
||||
return@check
|
||||
@@ -42,7 +42,7 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>().any {
|
||||
it.kind.isReal && it.hasJvmDefaultAnnotation()
|
||||
}
|
||||
if (!hasDeclaredJvmDefaults && !checkJvmDefaultsInHierarchy(descriptor, enableJvmDefault)) {
|
||||
if (!hasDeclaredJvmDefaults && !checkJvmDefaultsInHierarchy(descriptor, jvmDefaultMode.isEnabled)) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_THROUGH_INHERITANCE.on(declaration))
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
|
||||
if (memberDescriptor.overriddenDescriptors.any { it.annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) }) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE.on(declaration))
|
||||
} else if (enableJvmDefault) {
|
||||
} else if (jvmDefaultMode.isEnabled) {
|
||||
descriptor.overriddenDescriptors.flatMap { OverridingUtil.getOverriddenDeclarations(it) }.toSet().let {
|
||||
for (realDescriptor in OverridingUtil.filterOutOverridden(it)) {
|
||||
if (realDescriptor is JavaMethodDescriptor && realDescriptor.modality != Modality.ABSTRACT) {
|
||||
|
||||
@@ -137,9 +137,9 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(JVM_DEFAULT_NOT_IN_INTERFACE,"'@JvmDefault' is only supported on interface members");
|
||||
MAP.put(JVM_DEFAULT_IN_JVM6_TARGET,"'@JvmDefault' is only supported since JVM target 1.8. Recompile with '-jvm-target 1.8'");
|
||||
MAP.put(JVM_DEFAULT_REQUIRED_FOR_OVERRIDE, "'@JvmDefault' is required for an override of a '@JvmDefault' member");
|
||||
MAP.put(JVM_DEFAULT_IN_DECLARATION, "Usage of '@JvmDefault' is only allowed if the flag -Xenable-jvm-default is enabled");
|
||||
MAP.put(JVM_DEFAULT_THROUGH_INHERITANCE, "Inheritance from an interface with '@JvmDefault' members is only allowed if the flag -Xenable-jvm-default is enabled");
|
||||
MAP.put(USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL, "Super calls of '@JvmDefault' members are only allowed if the flag -Xenable-jvm-default is enabled");
|
||||
MAP.put(JVM_DEFAULT_IN_DECLARATION, "Usage of '@JvmDefault' is only allowed with -Xjvm-default option");
|
||||
MAP.put(JVM_DEFAULT_THROUGH_INHERITANCE, "Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option");
|
||||
MAP.put(USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL, "Super calls of '@JvmDefault' members are only allowed with -Xjvm-default option");
|
||||
MAP.put(NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, "Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault");
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
class JvmDefaultSuperCallChecker : CallChecker {
|
||||
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val enableJvmDefault = context.languageVersionSettings.getFlag(AnalysisFlag.enableJvmDefault)
|
||||
if (enableJvmDefault) return
|
||||
val jvmDefaultMode = context.languageVersionSettings.getFlag(AnalysisFlag.jvmDefaultMode)
|
||||
if (jvmDefaultMode.isEnabled) return
|
||||
val superExpression = getSuperCallExpression(resolvedCall.call) ?: return
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
if (!resultingDescriptor.hasJvmDefaultAnnotation()) return
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.jvm.platform
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.load.java.sam.JvmSamConversionTransformer
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConversionResolverImpl
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||
@@ -97,5 +98,6 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
container.useImpl<JvmModuleAccessibilityChecker.ClassifierUsage>()
|
||||
container.useInstance(JvmTypeSpecificityComparator)
|
||||
container.useImpl<JvmDefaultSuperCallChecker>()
|
||||
container.useImpl<JvmSamConversionTransformer>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.synthetic
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -59,6 +60,8 @@ class SamAdapterFunctionsScope(
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val lookupTracker: LookupTracker
|
||||
) : SyntheticScope {
|
||||
private val samViaSyntheticScopeDisabled = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
|
||||
|
||||
private val extensionForFunction =
|
||||
storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function ->
|
||||
extensionForFunctionNotCached(function)
|
||||
@@ -95,6 +98,8 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
|
||||
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
|
||||
var result: SmartList<FunctionDescriptor>? = null
|
||||
for (type in receiverTypes) {
|
||||
for (function in type.memberScope.getContributedFunctions(name, location)) {
|
||||
@@ -134,6 +139,8 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
|
||||
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
|
||||
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
|
||||
type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
.filterIsInstance<FunctionDescriptor>()
|
||||
@@ -148,12 +155,17 @@ class SamAdapterFunctionsScope(
|
||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> = emptyList()
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
|
||||
return getSamFunctions(scope.getContributedFunctions(name, location), location)
|
||||
}
|
||||
|
||||
override fun getSyntheticConstructors(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
val classifier = scope.getContributedClassifier(name, location) ?: return emptyList()
|
||||
recordSamLookupsToClassifier(classifier, location)
|
||||
|
||||
if (samViaSyntheticScopeDisabled) return listOfNotNull(getSamConstructor(classifier))
|
||||
|
||||
return getAllSamConstructors(classifier)
|
||||
}
|
||||
|
||||
@@ -166,16 +178,22 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
|
||||
return getSamFunctions(scope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS), location = null)
|
||||
}
|
||||
|
||||
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> {
|
||||
return scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
|
||||
.filterIsInstance<ClassifierDescriptor>()
|
||||
.flatMap { getAllSamConstructors(it) }
|
||||
val classifiers = scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS).filterIsInstance<ClassifierDescriptor>()
|
||||
|
||||
if (samViaSyntheticScopeDisabled) return classifiers.mapNotNull { getSamConstructor(it) }
|
||||
|
||||
return classifiers.flatMap { getAllSamConstructors(it) }
|
||||
}
|
||||
|
||||
override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor? {
|
||||
if (samViaSyntheticScopeDisabled) return null
|
||||
|
||||
return when (constructor) {
|
||||
is JavaClassConstructorDescriptor -> createJavaSamAdapterConstructor(constructor)
|
||||
is TypeAliasConstructorDescriptor -> {
|
||||
|
||||
@@ -41,7 +41,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
val environment: Map<String, Any?>? = null,
|
||||
val templateClasspath: List<File> = emptyList()
|
||||
) : KotlinScriptDefinition(template) {
|
||||
val scriptFilePattern by lazy {
|
||||
val scriptFilePattern by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
val pattern =
|
||||
takeUnlessError {
|
||||
val ann = template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()
|
||||
@@ -52,7 +52,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
Regex(pattern)
|
||||
}
|
||||
|
||||
override val dependencyResolver: DependenciesResolver by lazy {
|
||||
override val dependencyResolver: DependenciesResolver by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
resolverFromAnnotation(template) ?:
|
||||
resolverFromLegacyAnnotation(template) ?:
|
||||
DependenciesResolver.NoDependencies
|
||||
@@ -99,12 +99,12 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
}
|
||||
}
|
||||
|
||||
private val samWithReceiverAnnotations: List<String>? by lazy {
|
||||
private val samWithReceiverAnnotations: List<String>? by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
takeUnlessError { template.annotations.firstIsInstanceOrNull<kotlin.script.extensions.SamWithReceiverAnnotations>()?.annotations?.toList() }
|
||||
?: takeUnlessError { template.annotations.firstIsInstanceOrNull<org.jetbrains.kotlin.script.SamWithReceiverAnnotations>()?.annotations?.toList() }
|
||||
}
|
||||
|
||||
override val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
|
||||
override val acceptedAnnotations: List<KClass<out Annotation>> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
|
||||
fun sameSignature(left: KFunction<*>, right: KFunction<*>): Boolean =
|
||||
left.name == right.name &&
|
||||
@@ -134,7 +134,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
}
|
||||
}
|
||||
|
||||
override val scriptExpectedLocations: List<ScriptExpectedLocation> by lazy {
|
||||
override val scriptExpectedLocations: List<ScriptExpectedLocation> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
takeUnlessError {
|
||||
template.annotations.firstIsInstanceOrNull<ScriptExpectedLocations>()
|
||||
}?.value?.toList() ?: super.scriptExpectedLocations
|
||||
@@ -153,7 +153,7 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
override val annotationsForSamWithReceivers: List<String>
|
||||
get() = samWithReceiverAnnotations ?: super.annotationsForSamWithReceivers
|
||||
|
||||
override val additionalCompilerArguments: Iterable<String>? by lazy {
|
||||
override val additionalCompilerArguments: Iterable<String>? by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
takeUnlessError {
|
||||
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateAdditionalCompilerArguments>()?.let {
|
||||
val res = it.provider.primaryConstructor?.call(it.arguments.asIterable())
|
||||
|
||||
@@ -58,8 +58,8 @@ class ScriptContentLoader(private val project: Project) {
|
||||
|
||||
class BasicScriptContents(virtualFile: VirtualFile, getAnnotations: () -> Iterable<Annotation>) : ScriptContents {
|
||||
override val file: File = File(virtualFile.path)
|
||||
override val annotations: Iterable<Annotation> by lazy { getAnnotations() }
|
||||
override val text: CharSequence? by lazy { virtualFile.inputStream.reader(charset = virtualFile.charset).readText() }
|
||||
override val annotations: Iterable<Annotation> by lazy(LazyThreadSafetyMode.PUBLICATION) { getAnnotations() }
|
||||
override val text: CharSequence? by lazy(LazyThreadSafetyMode.PUBLICATION) { virtualFile.inputStream.reader(charset = virtualFile.charset).readText() }
|
||||
}
|
||||
|
||||
fun loadContentsAndResolveDependencies(
|
||||
|
||||
@@ -132,6 +132,9 @@ public class CompilerConfiguration {
|
||||
else if (object instanceof Map) {
|
||||
return (T) Collections.unmodifiableMap((Map) object);
|
||||
}
|
||||
else if (object instanceof Set) {
|
||||
return (T) Collections.unmodifiableSet((Set) object);
|
||||
}
|
||||
else if (object instanceof Collection) {
|
||||
return (T) Collections.unmodifiableCollection((Collection) object);
|
||||
}
|
||||
|
||||
@@ -619,6 +619,9 @@ public interface Errors {
|
||||
DiagnosticFactory2.create(ERROR, ACTUAL_DECLARATION_NAME);
|
||||
DiagnosticFactory0<KtNamedDeclaration> ACTUAL_MISSING = DiagnosticFactory0.create(ERROR, ACTUAL_DECLARATION_NAME);
|
||||
|
||||
DiagnosticFactory0<PsiElement> OPTIONAL_EXPECTATION_NOT_ON_EXPECTED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Errors/warnings inside code blocks
|
||||
|
||||
@@ -284,6 +284,9 @@ public class DefaultErrorMessages {
|
||||
NAME, IncompatibleExpectedActualClassScopesRenderer.TEXT);
|
||||
MAP.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'");
|
||||
|
||||
MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class");
|
||||
MAP.put(OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, "Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry");
|
||||
|
||||
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
|
||||
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
|
||||
MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME);
|
||||
|
||||
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker;
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext;
|
||||
import org.jetbrains.kotlin.resolve.checkers.PublishedApiUsageChecker;
|
||||
import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker;
|
||||
import org.jetbrains.kotlin.resolve.checkers.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -275,6 +272,7 @@ public class ModifiersChecker {
|
||||
}
|
||||
OperatorModifierChecker.INSTANCE.check(declaration, descriptor, trace, languageVersionSettings);
|
||||
PublishedApiUsageChecker.INSTANCE.check(declaration, descriptor, trace);
|
||||
OptionalExpectationTargetChecker.INSTANCE.check(declaration, descriptor, trace);
|
||||
}
|
||||
|
||||
public void checkTypeParametersModifiers(@NotNull KtModifierListOwner modifierListOwner) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.SamConversionTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||
@@ -62,6 +63,7 @@ abstract class TargetPlatform(val platformName: String) {
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(SyntheticScopes.Empty)
|
||||
container.useInstance(SamConversionTransformer.Empty)
|
||||
container.useInstance(TypeSpecificityComparator.NONE)
|
||||
}
|
||||
}
|
||||
@@ -100,7 +102,8 @@ private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
)
|
||||
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
||||
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
|
||||
DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage
|
||||
DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage,
|
||||
OptionalExpectationUsageChecker()
|
||||
)
|
||||
private val DEFAULT_ANNOTATION_CHECKERS = listOf<AdditionalAnnotationChecker>(
|
||||
ExperimentalMarkerDeclarationAnnotationChecker
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.SamConversionTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||
@@ -62,6 +63,7 @@ abstract class TargetPlatform(val platformName: String) {
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(SyntheticScopes.Empty)
|
||||
container.useInstance(SamConversionTransformer.Empty)
|
||||
container.useInstance(TypeSpecificityComparator.NONE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,10 +207,14 @@ class KotlinToResolvedCallTransformer(
|
||||
for (valueArgument in resolvedCall.call.valueArguments) {
|
||||
val argumentMapping = resolvedCall.getArgumentMapping(valueArgument!!)
|
||||
val (expectedType, callPosition) = when (argumentMapping) {
|
||||
is ArgumentMatch -> Pair(
|
||||
getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context),
|
||||
CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument)
|
||||
)
|
||||
is ArgumentMatch -> {
|
||||
val expectedType = resolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument)
|
||||
?: getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context)
|
||||
Pair(
|
||||
expectedType,
|
||||
CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument)
|
||||
)
|
||||
}
|
||||
else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown)
|
||||
}
|
||||
val newContext =
|
||||
@@ -513,6 +517,8 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
private var extensionReceiver = resolvedCallAtom.extensionReceiverArgument?.receiver?.receiverValue
|
||||
private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue
|
||||
private var smartCastDispatchReceiverType: KotlinType? = null
|
||||
private var expedtedTypeForSamConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null
|
||||
|
||||
|
||||
override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom
|
||||
|
||||
@@ -601,6 +607,22 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
|
||||
TypeApproximator().approximateToSuperType(substituted, TypeApproximatorConfiguration.CapturedTypesApproximation) ?: substituted
|
||||
}
|
||||
|
||||
calculateExpedtedTypeForSamConvertedArgumentMap(substitutor)
|
||||
}
|
||||
|
||||
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expedtedTypeForSamConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
private fun calculateExpedtedTypeForSamConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
if (resolvedCallAtom.argumentsWithConversion.isEmpty()) return
|
||||
|
||||
expedtedTypeForSamConvertedArgumentMap = hashMapOf()
|
||||
for ((argument, description) in resolvedCallAtom.argumentsWithConversion) {
|
||||
val typeWithFreshVariables = resolvedCallAtom.substitutor.safeSubstitute(description.convertedTypeByCandidateParameter)
|
||||
val expectedType = substitutor?.safeSubstitute(typeWithFreshVariables) ?: typeWithFreshVariables
|
||||
expedtedTypeForSamConvertedArgumentMap!![argument.psiCallArgument.valueArgument] = expectedType
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -41,6 +42,8 @@ import org.jetbrains.kotlin.utils.ifEmpty
|
||||
import java.io.File
|
||||
|
||||
object ExpectedActualDeclarationChecker : DeclarationChecker {
|
||||
internal val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation")
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return
|
||||
|
||||
@@ -67,6 +70,8 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
||||
|
||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, platformModule) ?: return
|
||||
|
||||
if (compatibility.allStrongIncompatibilities() && isOptionalAnnotationClass(descriptor)) return
|
||||
|
||||
val shouldReportError =
|
||||
compatibility.allStrongIncompatibilities() ||
|
||||
Compatible !in compatibility && compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
|
||||
@@ -89,6 +94,10 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean {
|
||||
return descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
}
|
||||
|
||||
private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: Sequence<MemberDescriptor>) {
|
||||
if (this is ExpectActualTracker.DoNothing) return
|
||||
|
||||
|
||||
@@ -265,18 +265,6 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.isUsageAsAnnotationOrImport(): Boolean {
|
||||
val parent = parent
|
||||
|
||||
if (parent is KtUserType) {
|
||||
return parent.parent is KtTypeReference &&
|
||||
parent.parent.parent is KtConstructorCalleeExpression &&
|
||||
parent.parent.parent.parent is KtAnnotationEntry
|
||||
}
|
||||
|
||||
return parent is KtDotQualifiedExpression && parent.parent is KtImportDirective
|
||||
}
|
||||
|
||||
private fun PsiElement.isUsageAsQualifier(): Boolean {
|
||||
if (this is KtSimpleNameExpression) {
|
||||
val qualifier = getTopmostParentQualifiedExpressionForSelector() ?: this
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
|
||||
object OptionalExpectationTargetChecker {
|
||||
fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
if (descriptor is MemberDescriptor && descriptor.isExpect) return
|
||||
|
||||
for (entry in declaration.annotationEntries) {
|
||||
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
if (annotationDescriptor.fqName == ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME) {
|
||||
trace.report(Errors.OPTIONAL_EXPECTATION_NOT_ON_EXPECTED.on(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
|
||||
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
||||
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
|
||||
if (!ExpectedActualDeclarationChecker.isOptionalAnnotationClass(targetDescriptor)) return
|
||||
|
||||
if (!element.isUsageAsAnnotationOrImport()) {
|
||||
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
internal fun PsiElement.isUsageAsAnnotationOrImport(): Boolean {
|
||||
val parent = parent
|
||||
|
||||
if (parent is KtUserType) {
|
||||
return parent.parent is KtTypeReference &&
|
||||
parent.parent.parent is KtConstructorCalleeExpression &&
|
||||
parent.parent.parent.parent is KtAnnotationEntry
|
||||
}
|
||||
|
||||
return parent is KtDotQualifiedExpression && parent.parent is KtImportDirective
|
||||
}
|
||||
@@ -15,6 +15,7 @@ dependencies {
|
||||
compile(project(":compiler:frontend.java"))
|
||||
compile(project(":compiler:cli"))
|
||||
compile(project(":kotlin-build-common"))
|
||||
compile(project(":compiler:daemon-common"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeJars("annotations") }
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ data class BuildDifference(val ts: Long, val isIncremental: Boolean, val dirtyDa
|
||||
data class BuildDiffsStorage(val buildDiffs: List<BuildDifference>) {
|
||||
companion object {
|
||||
fun readFromFile(file: File, reporter: ICReporter?): BuildDiffsStorage? {
|
||||
val diffs = readDiffsFromFile(file, reporter)
|
||||
return diffs?.let { BuildDiffsStorage(it) }
|
||||
}
|
||||
|
||||
fun readDiffsFromFile(file: File, reporter: ICReporter?): MutableList<BuildDifference>? {
|
||||
fun reportFail(reason: String) {
|
||||
reporter?.report { "Could not read diff from file $file: $reason" }
|
||||
}
|
||||
@@ -48,7 +53,7 @@ data class BuildDiffsStorage(val buildDiffs: List<BuildDifference>) {
|
||||
repeat(size) {
|
||||
result.add(input.readBuildDifference())
|
||||
}
|
||||
return BuildDiffsStorage(result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
catch (e: IOException) {
|
||||
|
||||
@@ -23,5 +23,5 @@ internal sealed class ChangesEither {
|
||||
val lookupSymbols: Collection<LookupSymbol> = emptyList(),
|
||||
val fqNames: Collection<FqName> = emptyList()
|
||||
) : ChangesEither()
|
||||
internal class Unknown : ChangesEither()
|
||||
internal class Unknown(val reason: String? = null) : ChangesEither()
|
||||
}
|
||||
@@ -27,8 +27,6 @@ import org.jetbrains.kotlin.compilerRunner.toGeneratedFile
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
|
||||
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
@@ -43,8 +41,6 @@ abstract class IncrementalCompilerRunner<
|
||||
cacheDirName: String,
|
||||
protected val cacheVersions: List<CacheVersion>,
|
||||
protected val reporter: ICReporter,
|
||||
protected val artifactChangesProvider: ArtifactChangesProvider?,
|
||||
protected val changesRegistry: ChangesRegistry?,
|
||||
private val localStateDirs: Collection<File> = emptyList()
|
||||
) {
|
||||
|
||||
@@ -307,16 +303,11 @@ abstract class IncrementalCompilerRunner<
|
||||
|
||||
open fun runWithNoDirtyKotlinSources(caches: CacheManager): Boolean = false
|
||||
|
||||
protected open fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) {
|
||||
if (changesRegistry == null) return
|
||||
|
||||
if (compilationMode is CompilationMode.Incremental) {
|
||||
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
|
||||
}
|
||||
else {
|
||||
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode::class.java}" }
|
||||
changesRegistry.unknownChanges(currentBuildInfo.startTS)
|
||||
}
|
||||
protected open fun processChangesAfterBuild(
|
||||
compilationMode: CompilationMode,
|
||||
currentBuildInfo: BuildInfo,
|
||||
dirtyData: DirtyData
|
||||
) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -67,9 +67,7 @@ class IncrementalJsCompilerRunner(
|
||||
workingDir,
|
||||
"caches-js",
|
||||
cacheVersions,
|
||||
reporter,
|
||||
artifactChangesProvider = null,
|
||||
changesRegistry = null
|
||||
reporter
|
||||
) {
|
||||
override fun isICEnabled(): Boolean =
|
||||
IncrementalCompilation.isEnabled() && IncrementalCompilation.isEnabledForJs()
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
@@ -39,8 +38,9 @@ import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
|
||||
import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory
|
||||
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory
|
||||
import org.jetbrains.kotlin.incremental.util.Either
|
||||
import org.jetbrains.kotlin.load.java.JavaClassesTracker
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
@@ -64,6 +64,7 @@ fun makeIncrementally(
|
||||
val rootsWalk = sourceRoots.asSequence().flatMap { it.walk() }
|
||||
val files = rootsWalk.filter(File::isFile)
|
||||
val sourceFiles = files.filter { it.extension.toLowerCase() in allExtensions }.toList()
|
||||
val buildHistoryFile = File(cachesDir, "build-history.bin")
|
||||
|
||||
withIC {
|
||||
val compiler = IncrementalJvmCompilerRunner(
|
||||
@@ -72,7 +73,9 @@ fun makeIncrementally(
|
||||
versions, reporter,
|
||||
// Use precise setting in case of non-Gradle build
|
||||
usePreciseJavaTracking = true,
|
||||
localStateDirs = emptyList()
|
||||
localStateDirs = emptyList(),
|
||||
buildHistoryFile = buildHistoryFile,
|
||||
modulesApiHistory = EmptyModulesApiHistory
|
||||
)
|
||||
compiler.compile(sourceFiles, args, messageCollector, providedChangedFiles = null)
|
||||
}
|
||||
@@ -101,19 +104,15 @@ class IncrementalJvmCompilerRunner(
|
||||
cacheVersions: List<CacheVersion>,
|
||||
reporter: ICReporter,
|
||||
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
artifactChangesProvider: ArtifactChangesProvider? = null,
|
||||
changesRegistry: ChangesRegistry? = null,
|
||||
private val buildHistoryFile: File? = null,
|
||||
private val friendBuildHistoryFile: File? = null,
|
||||
private val usePreciseJavaTracking: Boolean,
|
||||
localStateDirs: Collection<File>
|
||||
private val buildHistoryFile: File,
|
||||
localStateDirs: Collection<File>,
|
||||
private val modulesApiHistory: ModulesApiHistory
|
||||
) : IncrementalCompilerRunner<K2JVMCompilerArguments, IncrementalJvmCachesManager>(
|
||||
workingDir,
|
||||
"caches-jvm",
|
||||
cacheVersions,
|
||||
reporter,
|
||||
artifactChangesProvider,
|
||||
changesRegistry,
|
||||
localStateDirs = localStateDirs
|
||||
) {
|
||||
override fun isICEnabled(): Boolean =
|
||||
@@ -166,41 +165,18 @@ class IncrementalJvmCompilerRunner(
|
||||
val lastBuildInfo = BuildInfo.read(lastBuildInfoFile) ?: return CompilationMode.Rebuild { "No information on previous build" }
|
||||
reporter.report { "Last Kotlin Build info -- $lastBuildInfo" }
|
||||
|
||||
val changesFromFriend by lazy {
|
||||
val myLastTS = lastBuildInfo.startTS
|
||||
val storage = friendBuildHistoryFile?.let { BuildDiffsStorage.readFromFile(it, reporter) } ?: return@lazy ChangesEither.Unknown()
|
||||
val classpathChanges = getClasspathChanges(args.classpathAsList, changedFiles, lastBuildInfo)
|
||||
|
||||
val (prevDiffs, newDiffs) = storage.buildDiffs.partition { it.ts < myLastTS }
|
||||
if (prevDiffs.isEmpty()) return@lazy ChangesEither.Unknown()
|
||||
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
val dirtyClassesFqNames = HashSet<FqName>()
|
||||
for ((_, isIncremental, dirtyData) in newDiffs) {
|
||||
if (!isIncremental) return@lazy ChangesEither.Unknown()
|
||||
|
||||
dirtyLookupSymbols.addAll(dirtyData.dirtyLookupSymbols)
|
||||
dirtyClassesFqNames.addAll(dirtyData.dirtyClassesFqNames)
|
||||
@Suppress("UNUSED_VARIABLE") // for sealed when
|
||||
val unused = when (classpathChanges) {
|
||||
is ChangesEither.Unknown -> return CompilationMode.Rebuild {
|
||||
// todo: we can recompile all files incrementally (not cleaning caches), so rebuild won't propagate
|
||||
"Could not get classpath's changes${classpathChanges.reason?.let { ": $it" }}"
|
||||
}
|
||||
is ChangesEither.Known -> {
|
||||
markDirtyBy(classpathChanges.lookupSymbols)
|
||||
markDirtyBy(classpathChanges.fqNames)
|
||||
}
|
||||
|
||||
markDirtyBy(dirtyLookupSymbols)
|
||||
markDirtyBy(dirtyClassesFqNames)
|
||||
ChangesEither.Known(dirtyLookupSymbols, dirtyClassesFqNames)
|
||||
}
|
||||
val friendDirs = args.friendPaths?.map { File(it) } ?: emptyList()
|
||||
for (file in changedFiles.removed.asSequence() + changedFiles.modified.asSequence()) {
|
||||
if (!file.isClassFile()) continue
|
||||
|
||||
val isFriendClassFile = friendDirs.any { FileUtil.isAncestor(it, file, false) }
|
||||
if (isFriendClassFile && changesFromFriend is ChangesEither.Known) continue
|
||||
|
||||
return CompilationMode.Rebuild { "Cannot get changes from modified or removed class file: ${reporter.pathsAsString(file)}" }
|
||||
}
|
||||
|
||||
val classpathSet = args.classpathAsList.toHashSet()
|
||||
val modifiedClasspathEntries = changedFiles.modified.filter { it in classpathSet }
|
||||
val classpathChanges = getClasspathChanges(modifiedClasspathEntries, lastBuildInfo)
|
||||
if (classpathChanges !is ChangesEither.Known) {
|
||||
return CompilationMode.Rebuild { "could not get changes from modified classpath entries: ${reporter.pathsAsString(modifiedClasspathEntries)}" }
|
||||
}
|
||||
|
||||
if (!usePreciseJavaTracking) {
|
||||
@@ -221,8 +197,6 @@ class IncrementalJvmCompilerRunner(
|
||||
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
|
||||
|
||||
markDirtyBy(androidLayoutChanges)
|
||||
markDirtyBy(classpathChanges.lookupSymbols)
|
||||
markDirtyBy(classpathChanges.fqNames)
|
||||
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
|
||||
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
|
||||
|
||||
@@ -285,33 +259,51 @@ class IncrementalJvmCompilerRunner(
|
||||
}
|
||||
|
||||
private fun getClasspathChanges(
|
||||
modifiedClasspath: List<File>,
|
||||
lastBuildInfo: BuildInfo?
|
||||
classpath: List<File>,
|
||||
changedFiles: ChangedFiles.Known,
|
||||
lastBuildInfo: BuildInfo
|
||||
): ChangesEither {
|
||||
if (modifiedClasspath.isEmpty()) {
|
||||
reporter.report {"No classpath changes"}
|
||||
return ChangesEither.Known()
|
||||
val classpathSet = HashSet<File>()
|
||||
for (file in classpath) {
|
||||
when {
|
||||
file.isFile -> classpathSet.add(file)
|
||||
file.isDirectory -> file.walk().filterTo(classpathSet) { it.isFile }
|
||||
}
|
||||
}
|
||||
|
||||
val lastBuildTS = lastBuildInfo?.startTS
|
||||
if (lastBuildTS == null) {
|
||||
reporter.report {"Could not determine last build timestamp"}
|
||||
return ChangesEither.Unknown()
|
||||
}
|
||||
val modifiedClasspath = changedFiles.modified.filterTo(HashSet()) { it in classpathSet }
|
||||
val removedClasspath = changedFiles.removed.filterTo(HashSet()) { it in classpathSet }
|
||||
|
||||
// todo: removed classes could be processed normally
|
||||
if (removedClasspath.isNotEmpty()) return ChangesEither.Unknown("Some files are removed from classpath $removedClasspath")
|
||||
|
||||
if (modifiedClasspath.isEmpty()) return ChangesEither.Known()
|
||||
|
||||
val lastBuildTS = lastBuildInfo.startTS
|
||||
|
||||
val symbols = HashSet<LookupSymbol>()
|
||||
val fqNames = HashSet<FqName>()
|
||||
for (file in modifiedClasspath) {
|
||||
val diffs = artifactChangesProvider?.getChanges(file, lastBuildTS)
|
||||
|
||||
if (diffs == null) {
|
||||
reporter.report {"Could not get changes for file: $file"}
|
||||
return ChangesEither.Unknown()
|
||||
val historyFilesEither = modulesApiHistory.historyFilesForChangedFiles(modifiedClasspath)
|
||||
val historyFiles = when (historyFilesEither) {
|
||||
is Either.Success<Set<File>> -> historyFilesEither.value
|
||||
is Either.Error -> return ChangesEither.Unknown(historyFilesEither.reason)
|
||||
}
|
||||
|
||||
for (historyFile in historyFiles) {
|
||||
val allBuilds = BuildDiffsStorage.readDiffsFromFile(historyFile, reporter = reporter)
|
||||
?: return ChangesEither.Unknown("Could not read diffs from $historyFile")
|
||||
val (knownBuilds, newBuilds) = allBuilds.partition { it.ts <= lastBuildTS }
|
||||
if (knownBuilds.isEmpty()) {
|
||||
return ChangesEither.Unknown("No previously known builds for $historyFile")
|
||||
}
|
||||
|
||||
diffs.forEach {
|
||||
symbols.addAll(it.dirtyLookupSymbols)
|
||||
fqNames.addAll(it.dirtyClassesFqNames)
|
||||
for (buildDiff in newBuilds) {
|
||||
if (!buildDiff.isIncremental) return ChangesEither.Unknown("Non-incremental build from dependency $historyFile")
|
||||
|
||||
val dirtyData = buildDiff.dirtyData
|
||||
symbols.addAll(dirtyData.dirtyLookupSymbols)
|
||||
fqNames.addAll(dirtyData.dirtyClassesFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,16 +392,15 @@ class IncrementalJvmCompilerRunner(
|
||||
override fun additionalDirtyLookupSymbols(): Iterable<LookupSymbol> =
|
||||
javaFilesProcessor?.allChangedSymbols ?: emptyList()
|
||||
|
||||
override fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) {
|
||||
super.processChangesAfterBuild(compilationMode, currentBuildInfo, dirtyData)
|
||||
|
||||
if (buildHistoryFile == null) return
|
||||
|
||||
override fun processChangesAfterBuild(
|
||||
compilationMode: CompilationMode,
|
||||
currentBuildInfo: BuildInfo,
|
||||
dirtyData: DirtyData
|
||||
) {
|
||||
val prevDiffs = BuildDiffsStorage.readFromFile(buildHistoryFile, reporter)?.buildDiffs ?: emptyList()
|
||||
val newDiff = if (compilationMode is CompilationMode.Incremental) {
|
||||
BuildDifference(currentBuildInfo.startTS, true, dirtyData)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val emptyDirtyData = DirtyData()
|
||||
BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData)
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.multiproject
|
||||
|
||||
import org.jetbrains.kotlin.incremental.DirtyData
|
||||
|
||||
interface ChangesRegistry {
|
||||
fun registerChanges(timestamp: Long, dirtyData: DirtyData)
|
||||
fun unknownChanges(timestamp: Long)
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.multiproject
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalModuleEntry
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalModuleInfo
|
||||
import org.jetbrains.kotlin.incremental.util.Either
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
interface ModulesApiHistory {
|
||||
fun historyFilesForChangedFiles(changedFiles: Set<File>): Either<Set<File>>
|
||||
}
|
||||
|
||||
object EmptyModulesApiHistory : ModulesApiHistory {
|
||||
override fun historyFilesForChangedFiles(changedFiles: Set<File>): Either<Set<File>> =
|
||||
Either.Error("Multi-module IC is not configured")
|
||||
}
|
||||
|
||||
open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo) : ModulesApiHistory {
|
||||
protected val projectRootPath: Path = Paths.get(modulesInfo.projectRoot.absolutePath)
|
||||
private val dirToHistoryFileCache = HashMap<File, Set<File>>()
|
||||
|
||||
override fun historyFilesForChangedFiles(changedFiles: Set<File>): Either<Set<File>> {
|
||||
val result = HashSet<File>()
|
||||
val jarFiles = ArrayList<File>()
|
||||
val classFiles = ArrayList<File>()
|
||||
|
||||
for (file in changedFiles) {
|
||||
val extension = file.extension
|
||||
|
||||
when {
|
||||
extension.equals("class", ignoreCase = true) -> {
|
||||
classFiles.add(file)
|
||||
}
|
||||
extension.equals("jar", ignoreCase = true) -> {
|
||||
jarFiles.add(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (jar in jarFiles) {
|
||||
val historyEither = getBuildHistoryFilesForJar(jar)
|
||||
when (historyEither) {
|
||||
is Either.Success<Set<File>> -> result.addAll(historyEither.value)
|
||||
is Either.Error -> return historyEither
|
||||
}
|
||||
}
|
||||
|
||||
val classFileDirs = classFiles.groupBy { it.parentFile }
|
||||
for ((dir, files) in classFileDirs) {
|
||||
val historyEither = getBuildHistoryForDir(dir)
|
||||
when (historyEither) {
|
||||
is Either.Success<Set<File>> -> result.addAll(historyEither.value)
|
||||
is Either.Error -> return historyEither
|
||||
}
|
||||
}
|
||||
|
||||
return Either.Success(result)
|
||||
}
|
||||
|
||||
protected open fun getBuildHistoryForDir(file: File): Either<Set<File>> {
|
||||
val history = dirToHistoryFileCache.getOrPut(file) {
|
||||
val module = modulesInfo.dirToModule[file]
|
||||
val parent = file.parentFile
|
||||
|
||||
when {
|
||||
module != null ->
|
||||
setOf(module.buildHistoryFile)
|
||||
parent != null && projectRootPath.isParentOf(parent) -> {
|
||||
val parentHistory = getBuildHistoryForDir(parent)
|
||||
when (parentHistory) {
|
||||
is Either.Success<Set<File>> -> parentHistory.value
|
||||
is Either.Error -> return parentHistory
|
||||
}
|
||||
}
|
||||
else ->
|
||||
return Either.Error("Unable to get build history for $file")
|
||||
}
|
||||
}
|
||||
return Either.Success(history)
|
||||
}
|
||||
|
||||
protected open fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>> {
|
||||
val classListFile = modulesInfo.jarToClassListFile[jar] ?: return Either.Error("Unknown jar: $jar")
|
||||
if (!classListFile.isFile) return Either.Error("Class list file does not exist $classListFile")
|
||||
|
||||
val classFiles = try {
|
||||
classListFile.readText().split(File.pathSeparator).map(::File)
|
||||
} catch (t: Throwable) {
|
||||
return Either.Error("Could not read class list for $jar from $classListFile: $t")
|
||||
}
|
||||
|
||||
val classFileDirs = classFiles.groupBy { it.parentFile }
|
||||
val result = HashSet<File>()
|
||||
for ((dir, files) in classFileDirs) {
|
||||
val historyEither = getBuildHistoryForDir(dir)
|
||||
when (historyEither) {
|
||||
is Either.Success<Set<File>> -> result.addAll(historyEither.value)
|
||||
is Either.Error -> return historyEither
|
||||
}
|
||||
}
|
||||
return Either.Success(result)
|
||||
}
|
||||
}
|
||||
|
||||
class ModulesApiHistoryAndroid(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryJvm(modulesInfo) {
|
||||
private val delegate = ModulesApiHistoryJvm(modulesInfo)
|
||||
|
||||
override fun historyFilesForChangedFiles(changedFiles: Set<File>): Either<Set<File>> {
|
||||
val historyFromDelegate = delegate.historyFilesForChangedFiles(changedFiles)
|
||||
if (historyFromDelegate is Either.Success<Set<File>>) return historyFromDelegate
|
||||
|
||||
return super.historyFilesForChangedFiles(changedFiles)
|
||||
}
|
||||
|
||||
override fun getBuildHistoryFilesForJar(jar: File): Either<Set<File>> {
|
||||
// Module detection is expensive, so we don't don it for jars outside of project dir
|
||||
if (!projectRootPath.isParentOf(jar)) return Either.Error("Non-project jar is modified $jar")
|
||||
|
||||
val jarPath = Paths.get(jar.absolutePath)
|
||||
return getHistoryForModuleNames(jarPath, getPossibleModuleNamesFromJar(jarPath))
|
||||
}
|
||||
|
||||
override fun getBuildHistoryForDir(file: File): Either<Set<File>> {
|
||||
if (!projectRootPath.isParentOf(file)) return Either.Error("Non-project file while looking for history $file")
|
||||
|
||||
// check both meta-inf and META-INF directories
|
||||
val moduleNames =
|
||||
getPossibleModuleNamesForDir(file.resolve("meta-inf")) + getPossibleModuleNamesForDir(file.resolve("META-INF"))
|
||||
if (moduleNames.isEmpty()) {
|
||||
return if (file.parentFile == null) {
|
||||
Either.Error("Unable to find history for $file")
|
||||
} else {
|
||||
getBuildHistoryForDir(file.parentFile)
|
||||
}
|
||||
}
|
||||
|
||||
return getHistoryForModuleNames(file.toPath(), moduleNames)
|
||||
}
|
||||
|
||||
private fun getPossibleModuleNamesFromJar(path: Path): Collection<String> {
|
||||
val result = HashSet<String>()
|
||||
|
||||
try {
|
||||
ZipFile(path.toFile()).use { zip ->
|
||||
val entries = zip.entries()
|
||||
while (entries.hasMoreElements()) {
|
||||
val entry = entries.nextElement()
|
||||
val name = entry.name
|
||||
if (name.endsWith(".kotlin_module", ignoreCase = true)) {
|
||||
result.add(File(name).nameWithoutExtension)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getPossibleModuleNamesForDir(path: File): List<String> {
|
||||
if (!path.isDirectory) return listOf()
|
||||
|
||||
return path.listFiles().filter { it.name.endsWith(".kotlin_module", ignoreCase = true) }.map { it.nameWithoutExtension }
|
||||
}
|
||||
|
||||
private fun getHistoryForModuleNames(path: Path, moduleNames: Iterable<String>): Either<Set<File>> {
|
||||
val possibleModules =
|
||||
moduleNames.flatMapTo(HashSet<IncrementalModuleEntry>()) { modulesInfo.nameToModules[it] ?: emptySet() }
|
||||
val modules = possibleModules.filter { Paths.get(it.buildDir.absolutePath).isParentOf(path) }
|
||||
if (modules.isEmpty()) return Either.Error("Unknown module for $path (candidates: ${possibleModules.joinToString()})")
|
||||
|
||||
val result = modules.mapTo(HashSet()) { it.buildHistoryFile }
|
||||
return Either.Success(result)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Path.isParentOf(path: Path) = path.startsWith(this)
|
||||
private fun Path.isParentOf(file: File) = this.isParentOf(Paths.get(file.absolutePath))
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.util
|
||||
|
||||
sealed class Either<out T> {
|
||||
class Success<T>(val value: T) : Either<T>()
|
||||
class Error(val reason: String) : Either<Nothing>()
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.multiproject
|
||||
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalModuleEntry
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalModuleInfo
|
||||
import org.jetbrains.kotlin.incremental.util.Either
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import java.io.File
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ModulesApiHistoryAndroidTest {
|
||||
@JvmField
|
||||
@Rule
|
||||
val tmpFolder = TemporaryFolder()
|
||||
|
||||
private lateinit var appRoot: File
|
||||
private lateinit var appKotlinDestination: File
|
||||
private lateinit var appHistory: File
|
||||
private lateinit var libRoot: File
|
||||
private lateinit var libKotlinDestination: File
|
||||
private lateinit var libHistory: File
|
||||
|
||||
private lateinit var androidHistory: ModulesApiHistoryAndroid
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
val projectRoot = tmpFolder.newFolder()
|
||||
|
||||
appRoot = projectRoot.resolve("app")
|
||||
appHistory = appRoot.resolve("build/tmp/kotlin/app_history.bin")
|
||||
appKotlinDestination = appRoot.resolve("build/tmp/kotlin-classes").apply { mkdirs() }
|
||||
val appEntry = IncrementalModuleEntry(":app", "app", appRoot.resolve("build"), appHistory)
|
||||
appRoot.resolve("build/intermediates/classes/meta-inf/").apply {
|
||||
mkdirs()
|
||||
resolve("app.kotlin_module").createNewFile()
|
||||
}
|
||||
|
||||
libRoot = projectRoot.resolve("lib")
|
||||
libHistory = libRoot.resolve("lib/build/tmp/kotlin/lib_history.bin")
|
||||
libKotlinDestination = libRoot.resolve("build/tmp/kotlin-classes").apply { mkdirs() }
|
||||
val libEntry = IncrementalModuleEntry(":lib", "lib", libRoot.resolve("build"), libHistory)
|
||||
libRoot.resolve("build/intermediates/classes/meta-inf/").apply {
|
||||
mkdirs()
|
||||
resolve("lib.kotlin_module").createNewFile()
|
||||
}
|
||||
|
||||
val info = IncrementalModuleInfo(
|
||||
projectRoot = projectRoot,
|
||||
dirToModule = mapOf(appKotlinDestination to appEntry, libKotlinDestination to libEntry),
|
||||
nameToModules = mapOf("app" to setOf(appEntry), "lib" to setOf(libEntry)),
|
||||
jarToClassListFile = mapOf()
|
||||
)
|
||||
|
||||
androidHistory = ModulesApiHistoryAndroid(info)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClassChangeInAppTopLevel() {
|
||||
val changed = appRoot.resolve("build/intermediates/classes/Changed.class").let {
|
||||
it.mkdirs()
|
||||
it
|
||||
}
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(setOf(changed))
|
||||
changedFiles as Either.Success<Set<File>>
|
||||
assertEquals(setOf(appHistory), changedFiles.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClassChangeInAppInPackage() {
|
||||
val changed = appRoot.resolve("build/intermediates/classes/com/exampleChanged.class").let {
|
||||
it.mkdirs()
|
||||
it
|
||||
}
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(setOf(changed))
|
||||
changedFiles as Either.Success<Set<File>>
|
||||
assertEquals(setOf(appHistory), changedFiles.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClassMultipleChanges() {
|
||||
|
||||
val classesRoot = appRoot.resolve("build/intermediates/classes/com/example/")
|
||||
classesRoot.mkdirs()
|
||||
val changed = 1.until(10).map { classesRoot.resolve("MyClass_$it.class") }.toSet()
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(changed)
|
||||
changedFiles as Either.Success<Set<File>>
|
||||
assertEquals(setOf(appHistory), changedFiles.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClassChangeInAppOutsideClasses() {
|
||||
val changed = appRoot.resolve("build/Changed.class").let {
|
||||
it.mkdirs()
|
||||
it
|
||||
}
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(setOf(changed))
|
||||
assertTrue(changedFiles is Either.Error, "Fetching history should fail for file outside classes dir.")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClassChangeInAppAndLib() {
|
||||
val changedApp = appRoot.resolve("build/intermediates/classes/com/exampleChanged.class").let {
|
||||
it.mkdirs()
|
||||
it
|
||||
}
|
||||
val changedLib = libRoot.resolve("build/intermediates/classes/com/exampleChanged.class").let {
|
||||
it.mkdirs()
|
||||
it
|
||||
}
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(setOf(changedApp, changedLib))
|
||||
changedFiles as Either.Success<Set<File>>
|
||||
assertEquals(setOf(appHistory, libHistory), changedFiles.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJarChangeInApp() {
|
||||
val jarFile = appRoot.resolve("build/intermediates/classes.jar")
|
||||
jarFile.parentFile.mkdirs()
|
||||
|
||||
ZipOutputStream(jarFile.outputStream()).use {
|
||||
it.putNextEntry(ZipEntry("meta-inf/app.kotlin_module"))
|
||||
it.closeEntry()
|
||||
}
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(setOf(jarFile))
|
||||
changedFiles as Either.Success<Set<File>>
|
||||
assertEquals(setOf(appHistory), changedFiles.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJarChangesInAppAndLib() {
|
||||
val appJar = appRoot.resolve("build/intermediates/classes.jar")
|
||||
appJar.parentFile.mkdirs()
|
||||
ZipOutputStream(appJar.outputStream()).use {
|
||||
it.putNextEntry(ZipEntry("meta-inf/app.kotlin_module"))
|
||||
it.closeEntry()
|
||||
}
|
||||
|
||||
val libJar = libRoot.resolve("build/intermediates/classes.jar")
|
||||
libJar.parentFile.mkdirs()
|
||||
ZipOutputStream(libJar.outputStream()).use {
|
||||
it.putNextEntry(ZipEntry("META-INF/lib.kotlin_module"))
|
||||
it.closeEntry()
|
||||
}
|
||||
|
||||
val changedFiles = androidHistory.historyFilesForChangedFiles(setOf(appJar, libJar))
|
||||
changedFiles as Either.Success<Set<File>>
|
||||
assertEquals(setOf(appHistory, libHistory), changedFiles.value)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.SourceInfo
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
@@ -54,9 +53,6 @@ class IrSourceCompilerForInline(
|
||||
override val callElementText: String
|
||||
get() = callElement.toString()
|
||||
|
||||
override val callableDescriptor: CallableDescriptor
|
||||
get() = callElement.descriptor
|
||||
|
||||
override val callsiteFile: PsiFile?
|
||||
get() = TODO("not implemented")
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil
|
||||
import com.intellij.psi.scope.PsiScopeProcessor
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.stubs.IStubElementType
|
||||
@@ -34,6 +35,7 @@ import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
import com.intellij.psi.util.PsiUtilCore
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.annotations.NonNls
|
||||
@@ -345,34 +347,23 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
return null
|
||||
}
|
||||
|
||||
if (classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral()) {
|
||||
if (classOrObject.containingFile.virtualFile == null) return null
|
||||
return when {
|
||||
classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral() ->
|
||||
KtLightClassForAnonymousDeclaration(classOrObject)
|
||||
|
||||
return KtLightClassForAnonymousDeclaration(classOrObject)
|
||||
classOrObject.isLocal ->
|
||||
KtLightClassForLocalDeclaration(classOrObject)
|
||||
|
||||
else ->
|
||||
KtLightClassImpl(classOrObject)
|
||||
}
|
||||
|
||||
if (isEnumEntryWithoutBody(classOrObject)) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (classOrObject.isLocal) {
|
||||
if (classOrObject.containingFile.virtualFile == null) return null
|
||||
|
||||
return KtLightClassForLocalDeclaration(classOrObject)
|
||||
}
|
||||
|
||||
|
||||
return KtLightClassImpl(classOrObject)
|
||||
}
|
||||
|
||||
private fun isEnumEntryWithoutBody(classOrObject: KtClassOrObject): Boolean {
|
||||
if (classOrObject !is KtEnumEntry) {
|
||||
return false
|
||||
}
|
||||
return classOrObject.getBody()?.declarations?.isEmpty() ?: true
|
||||
}
|
||||
|
||||
fun getLightClassDataHolder(classOrObject: KtClassOrObject): LightClassDataHolder.ForClass {
|
||||
if (classOrObject.shouldNotBeVisibleAsLightClass()) {
|
||||
return InvalidLightClassDataHolder
|
||||
}
|
||||
|
||||
return classOrObject.containingKtFile.script?.let { KtLightClassForScript.getLightClassCachedValue(it).value } ?:
|
||||
getLightClassCachedValue(classOrObject).value
|
||||
}
|
||||
@@ -516,5 +507,44 @@ fun KtClassOrObject.defaultJavaAncestorQualifiedName(): String? {
|
||||
}
|
||||
}
|
||||
|
||||
fun KtClassOrObject.shouldNotBeVisibleAsLightClass() =
|
||||
parentsWithSelf.filterIsInstance<KtClassOrObject>().any { it.hasExpectModifier() }
|
||||
fun KtClassOrObject.shouldNotBeVisibleAsLightClass(): Boolean {
|
||||
if (parentsWithSelf.filterIsInstance<KtClassOrObject>().any { it.hasExpectModifier() }) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (isLocal) {
|
||||
if (containingFile.virtualFile == null) return true
|
||||
if (hasParseErrorsAround(this) || PsiUtilCore.hasErrorElementChild(this)) return true
|
||||
}
|
||||
|
||||
if (isEnumEntryWithoutBody(this)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isEnumEntryWithoutBody(classOrObject: KtClassOrObject): Boolean {
|
||||
if (classOrObject !is KtEnumEntry) {
|
||||
return false
|
||||
}
|
||||
return classOrObject.getBody()?.declarations?.isEmpty() ?: true
|
||||
}
|
||||
|
||||
private fun hasParseErrorsAround(psi: PsiElement): Boolean {
|
||||
val node = psi.node ?: return false
|
||||
|
||||
TreeUtil.nextLeaf(node)?.let { nextLeaf ->
|
||||
if (nextLeaf.elementType == TokenType.ERROR_ELEMENT || nextLeaf.treePrev?.elementType == TokenType.ERROR_ELEMENT) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
TreeUtil.prevLeaf(node)?.let { prevLeaf ->
|
||||
if (prevLeaf.elementType == TokenType.ERROR_ELEMENT || prevLeaf.treeNext?.elementType == TokenType.ERROR_ELEMENT) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.annotations.JVM_DEFAULT_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
|
||||
abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(protected val owner: T)
|
||||
@@ -138,9 +139,18 @@ private fun getAnnotationDescriptors(declaration: KtDeclaration, annotatedLightE
|
||||
else -> descriptor
|
||||
} ?: return emptyList()
|
||||
|
||||
return annotatedDescriptor.annotations.getAllAnnotations()
|
||||
.filter { it.matches(annotatedLightElement) }
|
||||
.map { it.annotation }
|
||||
val annotations = annotatedDescriptor.annotations.getAllAnnotations()
|
||||
.filter { it.matches(annotatedLightElement) }
|
||||
.map { it.annotation }
|
||||
|
||||
if (descriptor is PropertyDescriptor) {
|
||||
val jvmDefault = descriptor.annotations.findAnnotation(JVM_DEFAULT_FQ_NAME)
|
||||
if (jvmDefault != null) {
|
||||
return annotations + jvmDefault
|
||||
}
|
||||
}
|
||||
return annotations
|
||||
|
||||
}
|
||||
|
||||
private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
|
||||
|
||||
@@ -266,10 +266,14 @@ public class Preloader {
|
||||
}
|
||||
}
|
||||
|
||||
private static class PreloaderException extends RuntimeException {
|
||||
public static class PreloaderException extends RuntimeException {
|
||||
public PreloaderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PreloaderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Handler extends ClassHandler {
|
||||
|
||||
@@ -99,7 +99,7 @@ abstract class KtCodeFragment(
|
||||
override fun clone(): KtCodeFragment {
|
||||
val clone = cloneImpl(calcTreeElement().clone() as FileElement) as KtCodeFragment
|
||||
clone.isPhysical = false
|
||||
clone.originalFile = this
|
||||
clone.myOriginalFile = this
|
||||
clone.imports = imports
|
||||
clone.viewProvider =
|
||||
SingleRootFileViewProvider(PsiManager.getInstance(_project), LightVirtualFile(name, KotlinFileType.INSTANCE, text), false)
|
||||
|
||||
203
compiler/psi/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt.182
Normal file
203
compiler/psi/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt.182
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.psi
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiManagerEx
|
||||
import com.intellij.psi.impl.source.tree.FileElement
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
abstract class KtCodeFragment(
|
||||
private val _project: Project,
|
||||
name: String,
|
||||
text: CharSequence,
|
||||
imports: String?, // Should be separated by JetCodeFragment.IMPORT_SEPARATOR
|
||||
elementType: IElementType,
|
||||
private val context: PsiElement?
|
||||
) : KtFile(
|
||||
(PsiManager.getInstance(_project) as PsiManagerEx).fileManager.createFileViewProvider(
|
||||
LightVirtualFile(
|
||||
name,
|
||||
KotlinFileType.INSTANCE,
|
||||
text
|
||||
), true
|
||||
), false
|
||||
), JavaCodeFragment {
|
||||
|
||||
private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider
|
||||
private var imports = LinkedHashSet<String>()
|
||||
|
||||
private val fakeContextForJavaFile: PsiElement? by lazy {
|
||||
this.getCopyableUserData(FAKE_CONTEXT_FOR_JAVA_FILE)?.invoke()
|
||||
}
|
||||
|
||||
init {
|
||||
getViewProvider().forceCachedPsi(this)
|
||||
init(TokenType.CODE_FRAGMENT, elementType)
|
||||
if (context != null) {
|
||||
initImports(imports)
|
||||
}
|
||||
}
|
||||
|
||||
override final fun init(elementType: IElementType, contentElementType: IElementType?) {
|
||||
super.init(elementType, contentElementType)
|
||||
}
|
||||
|
||||
private var resolveScope: GlobalSearchScope? = null
|
||||
private var thisType: PsiType? = null
|
||||
private var superType: PsiType? = null
|
||||
private var exceptionHandler: JavaCodeFragment.ExceptionHandler? = null
|
||||
private var isPhysical = true
|
||||
|
||||
abstract fun getContentElement(): KtElement?
|
||||
|
||||
override fun forceResolveScope(scope: GlobalSearchScope?) {
|
||||
resolveScope = scope
|
||||
}
|
||||
|
||||
override fun getForcedResolveScope() = resolveScope
|
||||
|
||||
override fun isPhysical() = isPhysical
|
||||
|
||||
override fun isValid() = true
|
||||
|
||||
override fun getContext(): PsiElement? {
|
||||
if (fakeContextForJavaFile != null) return fakeContextForJavaFile
|
||||
if (context !is KtElement) {
|
||||
LOG.warn("CodeFragment with non-kotlin context should have fakeContextForJavaFile set: \noriginalContext = ${context?.getElementTextWithContext()}")
|
||||
return null
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
override fun getResolveScope() = context?.resolveScope ?: super.getResolveScope()
|
||||
|
||||
override fun clone(): KtCodeFragment {
|
||||
val clone = cloneImpl(calcTreeElement().clone() as FileElement) as KtCodeFragment
|
||||
clone.isPhysical = false
|
||||
clone.myOriginalFile = this
|
||||
clone.imports = imports
|
||||
clone.viewProvider =
|
||||
SingleRootFileViewProvider(PsiManager.getInstance(_project), LightVirtualFile(name, KotlinFileType.INSTANCE, text), false)
|
||||
clone.viewProvider.forceCachedPsi(clone)
|
||||
return clone
|
||||
}
|
||||
|
||||
final override fun getViewProvider() = viewProvider
|
||||
|
||||
override fun getThisType() = thisType
|
||||
|
||||
override fun setThisType(psiType: PsiType?) {
|
||||
thisType = psiType
|
||||
}
|
||||
|
||||
override fun getSuperType() = superType
|
||||
|
||||
override fun setSuperType(superType: PsiType?) {
|
||||
this.superType = superType
|
||||
}
|
||||
|
||||
override fun importsToString(): String {
|
||||
return imports.joinToString(IMPORT_SEPARATOR)
|
||||
}
|
||||
|
||||
override fun addImportsFromString(imports: String?) {
|
||||
if (imports == null || imports.isEmpty()) return
|
||||
|
||||
imports.split(IMPORT_SEPARATOR).forEach {
|
||||
addImport(it)
|
||||
}
|
||||
|
||||
// we need this code to force re-highlighting, otherwise it does not work by some reason
|
||||
val tempElement = KtPsiFactory(project).createColon()
|
||||
add(tempElement).delete()
|
||||
}
|
||||
|
||||
fun addImport(import: String) {
|
||||
val contextFile = getContextContainingFile()
|
||||
if (contextFile != null) {
|
||||
if (contextFile.importDirectives.find { it.text == import } == null) {
|
||||
imports.add(import)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun importsAsImportList(): KtImportList? {
|
||||
if (!imports.isEmpty() && context != null) {
|
||||
return KtPsiFactory(this).createAnalyzableFile("imports_for_codeFragment.kt", imports.joinToString("\n"), context).importList
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override val importDirectives: List<KtImportDirective>
|
||||
get() = importsAsImportList()?.imports ?: emptyList()
|
||||
|
||||
override fun setVisibilityChecker(checker: JavaCodeFragment.VisibilityChecker?) {}
|
||||
|
||||
override fun getVisibilityChecker() = JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE
|
||||
|
||||
override fun setExceptionHandler(checker: JavaCodeFragment.ExceptionHandler?) {
|
||||
exceptionHandler = checker
|
||||
}
|
||||
|
||||
override fun getExceptionHandler() = exceptionHandler
|
||||
|
||||
override fun importClass(aClass: PsiClass): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun getContextContainingFile(): KtFile? {
|
||||
return getOriginalContext()?.containingKtFile
|
||||
}
|
||||
|
||||
fun getOriginalContext(): KtElement? {
|
||||
val contextElement = getContext() as? KtElement
|
||||
val contextFile = contextElement?.containingKtFile
|
||||
if (contextFile is KtCodeFragment) {
|
||||
return contextFile.getOriginalContext()
|
||||
}
|
||||
return contextElement
|
||||
}
|
||||
|
||||
private fun initImports(imports: String?) {
|
||||
if (imports != null && !imports.isEmpty()) {
|
||||
|
||||
val importsWithPrefix = imports.split(IMPORT_SEPARATOR).map { it.takeIf { it.startsWith("import ") } ?: "import ${it.trim()}" }
|
||||
importsWithPrefix.forEach {
|
||||
addImport(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val IMPORT_SEPARATOR: String = ","
|
||||
val RUNTIME_TYPE_EVALUATOR: Key<Function1<KtExpression, KotlinType?>> = Key.create("RUNTIME_TYPE_EVALUATOR")
|
||||
val FAKE_CONTEXT_FOR_JAVA_FILE: Key<Function0<KtElement>> = Key.create("FAKE_CONTEXT_FOR_JAVA_FILE")
|
||||
|
||||
private val LOG = Logger.getInstance(KtCodeFragment::class.java)
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,9 @@ object KotlinStubVersions {
|
||||
|
||||
// BuiltIn stub version should be increased if changes are made to builtIn stub building subsystem (org.jetbrains.kotlin.idea.decompiler.builtIns)
|
||||
// Increasing this version will lead to reindexing of all builtIn files (see KotlinBuiltInFileType).
|
||||
const val BUILTIN_STUB_VERSION = BINARY_STUB_VERSION + 1
|
||||
const val BUILTIN_STUB_VERSION = BINARY_STUB_VERSION + 2
|
||||
|
||||
// JS stub version should be increased if changes are made to js stub building subsystem (org.jetbrains.kotlin.idea.decompiler.js)
|
||||
// Increasing this version will lead to reindexing of js binary files (see KotlinJavaScriptMetaFileType).
|
||||
const val JS_STUB_VERSION = BINARY_STUB_VERSION + 1
|
||||
const val JS_STUB_VERSION = BINARY_STUB_VERSION + 2
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user