mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-18 00:21:29 +00:00
Compare commits
194 Commits
rr/mitropo
...
1.2.40
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a2fc547f3 | ||
|
|
364c8af076 | ||
|
|
7b2b1f9f7d | ||
|
|
3d3be3dc78 | ||
|
|
8209a50764 | ||
|
|
d4f25e1043 | ||
|
|
73b9685f38 | ||
|
|
fdfe801c92 | ||
|
|
8b446a1649 | ||
|
|
6037b04f89 | ||
|
|
80fd1ac8ab | ||
|
|
c4ce4ac450 | ||
|
|
5184edea5f | ||
|
|
66be4ccb5e | ||
|
|
1227ade91e | ||
|
|
8f30017405 | ||
|
|
883a7fd2dc | ||
|
|
f1e395c1d9 | ||
|
|
b0d09109c4 | ||
|
|
94532db659 | ||
|
|
4e0af21df4 | ||
|
|
39809cedba | ||
|
|
625bfd8adb | ||
|
|
d3017a8071 | ||
|
|
b45a5a8ca7 | ||
|
|
fd97d56bc4 | ||
|
|
3801410d1c | ||
|
|
916c5e2260 | ||
|
|
23708991fe | ||
|
|
26c8f32390 | ||
|
|
e3d5021799 | ||
|
|
e5d903bc20 | ||
|
|
42950a9993 | ||
|
|
d69c627205 | ||
|
|
54f03aeaf9 | ||
|
|
8e8882065c | ||
|
|
fbb2ae4ef1 | ||
|
|
2283366076 | ||
|
|
7f8efc6dab | ||
|
|
da097a312b | ||
|
|
b3399a6529 | ||
|
|
da4d4153de | ||
|
|
73676d7a9e | ||
|
|
ff3da15cde | ||
|
|
696bff31f4 | ||
|
|
a8b561be15 | ||
|
|
3e8dab05f7 | ||
|
|
d67201aae2 | ||
|
|
01fc60fab3 | ||
|
|
48140586b9 | ||
|
|
8e66f6af9b | ||
|
|
686e8bc06a | ||
|
|
3cab8b4f41 | ||
|
|
18310d9b4c | ||
|
|
b393d78520 | ||
|
|
720bba5bba | ||
|
|
3d72966469 | ||
|
|
458bd709c9 | ||
|
|
5cd044691b | ||
|
|
1776dc6de2 | ||
|
|
b538e01889 | ||
|
|
2cd5bd4d83 | ||
|
|
db722b468f | ||
|
|
ba4858dde9 | ||
|
|
8037619a51 | ||
|
|
522be915c5 | ||
|
|
e7b8279dcd | ||
|
|
7a1aa8ac81 | ||
|
|
9e88b3d691 | ||
|
|
6e903333a6 | ||
|
|
a51181b009 | ||
|
|
69c635e7c3 | ||
|
|
5ba37fdff7 | ||
|
|
4a0037850b | ||
|
|
3bbffa38ab | ||
|
|
75b3a662f3 | ||
|
|
a28a0beaea | ||
|
|
33577b4078 | ||
|
|
4664f7c55d | ||
|
|
995156b801 | ||
|
|
38a8959356 | ||
|
|
b0da004779 | ||
|
|
df6ed491f5 | ||
|
|
02f4a02fbe | ||
|
|
6c0afb25fb | ||
|
|
075533595e | ||
|
|
65365ac88b | ||
|
|
be9614793b | ||
|
|
6ea5b79223 | ||
|
|
584bf7d70d | ||
|
|
e69f45b895 | ||
|
|
91882262fc | ||
|
|
b422471683 | ||
|
|
46eb8854c2 | ||
|
|
b4f90a90d9 | ||
|
|
a92bd947af | ||
|
|
76365e01eb | ||
|
|
eee3dcc9e1 | ||
|
|
a573b748a3 | ||
|
|
59ec96e02b | ||
|
|
5d236f7f85 | ||
|
|
1e30cd822c | ||
|
|
ceadec3c1b | ||
|
|
39d89fba95 | ||
|
|
5a72c8272e | ||
|
|
30beab4376 | ||
|
|
4394fe26ce | ||
|
|
aa75d887dc | ||
|
|
642611c43c | ||
|
|
431504234d | ||
|
|
cfd92593c6 | ||
|
|
2835f497b8 | ||
|
|
129f6bebd9 | ||
|
|
d5aa7f227f | ||
|
|
5692c1b086 | ||
|
|
ffe7a58bf9 | ||
|
|
82d8a3610a | ||
|
|
4ec406fa6f | ||
|
|
80086c46e4 | ||
|
|
1e07f9aafa | ||
|
|
7bcb11c94a | ||
|
|
279befb46b | ||
|
|
545430ce98 | ||
|
|
6d59778970 | ||
|
|
c52d6ad98f | ||
|
|
6000827eca | ||
|
|
675c1df26c | ||
|
|
2a859144d1 | ||
|
|
420b313920 | ||
|
|
e889c69226 | ||
|
|
a14b079c8f | ||
|
|
e671879954 | ||
|
|
8e04ecfd74 | ||
|
|
903c3a7b57 | ||
|
|
686b8e85ee | ||
|
|
86c27ef944 | ||
|
|
cedeb86303 | ||
|
|
2afdb5a773 | ||
|
|
01161b2dcb | ||
|
|
09ac5ac1bb | ||
|
|
b542cc680b | ||
|
|
e76ae20190 | ||
|
|
c8ab37e8ea | ||
|
|
c8b68d6ad1 | ||
|
|
06c3d7888f | ||
|
|
21f26de894 | ||
|
|
1c5f1e152a | ||
|
|
e8a5f068fa | ||
|
|
71bc8633c8 | ||
|
|
7d0087c55e | ||
|
|
6d29519dc3 | ||
|
|
5fffc1b268 | ||
|
|
a0838fde35 | ||
|
|
957f9c2a21 | ||
|
|
84cbada35b | ||
|
|
fed1c0e476 | ||
|
|
bbf5e08990 | ||
|
|
6054645508 | ||
|
|
ba33de6665 | ||
|
|
1264c4c048 | ||
|
|
aaf56ddbbc | ||
|
|
6a2b9c33fc | ||
|
|
6fd4b0d4ab | ||
|
|
44ab7c49af | ||
|
|
f0433b7ec1 | ||
|
|
a96e61c96c | ||
|
|
73e255c97c | ||
|
|
3559ed669d | ||
|
|
089a7eed11 | ||
|
|
fdb7995a3f | ||
|
|
fb8759dc8c | ||
|
|
dad2274ff1 | ||
|
|
e1e139fb02 | ||
|
|
1b699c5039 | ||
|
|
fda9d5d5bb | ||
|
|
bf5e67cad3 | ||
|
|
4def41144b | ||
|
|
d9191a0ace | ||
|
|
4092608ff6 | ||
|
|
f711fc8406 | ||
|
|
355a0f8859 | ||
|
|
eb01d9aaaf | ||
|
|
3cbd842b8b | ||
|
|
f960ca38eb | ||
|
|
dff4cfd1fc | ||
|
|
1a2f4223c3 | ||
|
|
7c8dcdee62 | ||
|
|
b3af085cfd | ||
|
|
4844176f49 | ||
|
|
0bcb6851e9 | ||
|
|
4645884785 | ||
|
|
576974f7ad | ||
|
|
923716e38f | ||
|
|
41dc8b6263 |
2
.idea/runConfigurations/Generate_All_Tests.xml
generated
2
.idea/runConfigurations/Generate_All_Tests.xml
generated
@@ -4,7 +4,7 @@
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="-x :ultimate:generateTests" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
|
||||
238
ChangeLog.md
238
ChangeLog.md
@@ -1,5 +1,243 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 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
|
||||
|
||||
@@ -29,15 +29,16 @@ Welcome to [Kotlin](https://kotlinlang.org/)! Some handy links:
|
||||
|
||||
In order to build Kotlin distribution you need to have:
|
||||
|
||||
- JDK 1.6, 1.7 and 1.8
|
||||
- JDK 1.6, 1.7, 1.8 and 9
|
||||
- Setup environment variables as following:
|
||||
|
||||
JAVA_HOME="path to JDK 1.8"
|
||||
JDK_16="path to JDK 1.6"
|
||||
JDK_17="path to JDK 1.7"
|
||||
JDK_18="path to JDK 1.8"
|
||||
JDK_9="path to JDK 9"
|
||||
|
||||
For local development, if you're not working on bytecode generation or the standard library, it's OK to have only JDK 8 installed, and to point all of the environment variables mentioned above to your JDK 8 installation.
|
||||
For local development, if you're not working on bytecode generation or the standard library, it's OK to have only JDK 1.8 and JDK 9 installed, and to point JDK_16 and JDK_17 environment variables to your JDK 1.8 installation.
|
||||
|
||||
You also can use [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties) to setup JDK_* variables.
|
||||
|
||||
|
||||
@@ -54,13 +54,16 @@ abstract class IncrementalCacheCommon<ClassName>(workingDir: File) : BasicMapsOw
|
||||
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
||||
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
||||
|
||||
fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName> =
|
||||
files.flatMapTo(HashSet()) { sourceToClassesMap.getFqNames(it) }
|
||||
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
|
||||
fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
open fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
open fun markDirty(removedAndCompiledSources: Collection<File>) {
|
||||
for (sourceFile in removedAndCompiledSources) {
|
||||
val classes = sourceToClassesMap[sourceFile]
|
||||
classes.forEach {
|
||||
|
||||
@@ -60,7 +60,7 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon<FqName>(
|
||||
headerFile.writeBytes(value)
|
||||
}
|
||||
|
||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
||||
override fun markDirty(removedAndCompiledSources: Collection<File>) {
|
||||
super.markDirty(removedAndCompiledSources)
|
||||
dirtySources.addAll(removedAndCompiledSources)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,9 @@ open class IncrementalJvmCache(
|
||||
fun classesBySources(sources: Iterable<File>): Iterable<JvmClassName> =
|
||||
sources.flatMap { sourceToClassesMap[it] }
|
||||
|
||||
fun sourceInCache(file: File): Boolean =
|
||||
sourceToClassesMap.contains(file)
|
||||
|
||||
fun sourcesByInternalName(internalName: String): Collection<File> =
|
||||
internalNameToSource[internalName]
|
||||
|
||||
|
||||
@@ -22,20 +22,27 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
internal interface NameTransformer<Name> {
|
||||
fun asString(name: Name): String
|
||||
fun asName(string: String): Name
|
||||
fun asFqName(string: String): FqName
|
||||
}
|
||||
|
||||
internal object FqNameTransformer : NameTransformer<FqName> {
|
||||
override fun asString(name: FqName): String =
|
||||
name.asString()
|
||||
name.asString()
|
||||
|
||||
override fun asName(string: String): FqName =
|
||||
FqName(string)
|
||||
FqName(string)
|
||||
|
||||
override fun asFqName(string: String): FqName =
|
||||
asName(string)
|
||||
}
|
||||
|
||||
internal object JvmClassNameTransformer : NameTransformer<JvmClassName> {
|
||||
override fun asString(name: JvmClassName): String =
|
||||
name.internalName
|
||||
name.internalName
|
||||
|
||||
override fun asName(string: String): JvmClassName =
|
||||
JvmClassName.byInternalName(string)
|
||||
JvmClassName.byInternalName(string)
|
||||
|
||||
override fun asFqName(string: String): FqName =
|
||||
asName(string).fqNameForClassNameWithoutDollars
|
||||
}
|
||||
@@ -42,6 +42,9 @@ internal abstract class AbstractSourceToOutputMap<Name>(
|
||||
operator fun get(sourceFile: File): Collection<Name> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asName)
|
||||
|
||||
fun getFqNames(sourceFile: File): Collection<FqName> =
|
||||
storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asFqName)
|
||||
|
||||
override fun dumpValue(value: Collection<String>) =
|
||||
value.dumpCollection()
|
||||
|
||||
|
||||
@@ -20,9 +20,13 @@ import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.metadata.DebugProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.js.DebugJsProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistry
|
||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor
|
||||
@@ -34,6 +38,8 @@ import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
import java.util.zip.GZIPInputStream
|
||||
import kotlin.comparisons.compareBy
|
||||
|
||||
// Set this to true if you want to dump all bytecode (test will fail in this case)
|
||||
private val DUMP_ALL = System.getProperty("comparison.dump.all") == "true"
|
||||
@@ -162,6 +168,24 @@ private fun classFileToString(classFile: File): String {
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
private fun metaJsToString(metaJsFile: File): String {
|
||||
val out = StringWriter()
|
||||
|
||||
val metadataList = arrayListOf<KotlinJavascriptMetadata>()
|
||||
KotlinJavascriptMetadataUtils.parseMetadata(metaJsFile.readText(), metadataList)
|
||||
|
||||
for (metadata in metadataList) {
|
||||
val (header, content) = GZIPInputStream(ByteArrayInputStream(metadata.body)).use { stream ->
|
||||
DebugJsProtoBuf.Header.parseDelimitedFrom(stream, JsSerializerProtocol.extensionRegistry) to
|
||||
DebugJsProtoBuf.Library.parseFrom(stream, JsSerializerProtocol.extensionRegistry)
|
||||
}
|
||||
out.write("\n------ header -----\n$header")
|
||||
out.write("\n------ library -----\n$content")
|
||||
}
|
||||
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
private fun getExtensionRegistry(): ExtensionRegistry {
|
||||
val registry = ExtensionRegistry.newInstance()!!
|
||||
DebugJvmProtoBuf.registerAllExtensions(registry)
|
||||
@@ -173,6 +197,9 @@ private fun fileToStringRepresentation(file: File): String {
|
||||
file.name.endsWith(".class") -> {
|
||||
classFileToString(file)
|
||||
}
|
||||
file.name.endsWith(KotlinJavascriptMetadataUtils.META_JS_SUFFIX) -> {
|
||||
metaJsToString(file)
|
||||
}
|
||||
else -> {
|
||||
file.readText()
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ Properties().apply {
|
||||
extra["JDK_16"] = jdkPath("1.6")
|
||||
extra["JDK_17"] = jdkPath("1.7")
|
||||
extra["JDK_18"] = jdkPath("1.8")
|
||||
extra["JDK_9"] = jdkPathIfFound("9")
|
||||
extra["JDK_9"] = jdkPath("9")
|
||||
extra["JDK_10"] = jdkPathIfFound("10")
|
||||
|
||||
rootProject.apply {
|
||||
@@ -595,10 +595,12 @@ fun jdkPath(version: String): String = jdkPathIfFound(version)
|
||||
|
||||
fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
|
||||
tasks.withType<JavaCompile> {
|
||||
options.isFork = true
|
||||
options.forkOptions.javaHome = file(javaHome)
|
||||
options.compilerArgs.add("-proc:none")
|
||||
options.encoding = "UTF-8"
|
||||
if (name != "compileJava9Java") {
|
||||
options.isFork = true
|
||||
options.forkOptions.javaHome = file(javaHome)
|
||||
options.compilerArgs.add("-proc:none")
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
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.1"
|
||||
extra["versions.shadow"] = "2.0.2"
|
||||
extra["versions.intellij-plugin"] = "0.3.0-SNAPSHOT"
|
||||
extra["versions.native-platform"] = "0.14"
|
||||
|
||||
|
||||
@@ -123,6 +123,9 @@ fun removePathPrefix(path: String): String {
|
||||
val unzipIntellijSdk by tasks.creating {
|
||||
configureExtractFromConfigurationTask(intellij, pathRemap = { removePathPrefix(it) }) {
|
||||
zipTree(it.singleFile).matching {
|
||||
if (OperatingSystem.current().isMacOsX && androidStudioRelease != null) {
|
||||
exclude("Android Studio*.app/Contents/plugins/Kotlin/**")
|
||||
}
|
||||
exclude("plugins/Kotlin/**")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,10 @@ fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File,
|
||||
"-Didea.additional.classpath=../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar"
|
||||
)
|
||||
|
||||
if (rootProject.findProperty("versions.androidStudioRelease") != null) {
|
||||
jvmArgs("-Didea.platform.prefix=AndroidStudio")
|
||||
}
|
||||
|
||||
if (project.hasProperty("noPCE")) {
|
||||
jvmArgs("-Didea.ProcessCanceledException=disabled")
|
||||
}
|
||||
|
||||
@@ -149,7 +149,9 @@ fun MutableCollection<JdkId>.discoverJdksOnUnix(project: Project) {
|
||||
|
||||
private val windowsConventionalJdkRegistryPaths = listOf(
|
||||
"SOFTWARE\\JavaSoft\\Java Development Kit",
|
||||
"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit")
|
||||
"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit",
|
||||
"SOFTWARE\\JavaSoft\\JDK",
|
||||
"SOFTWARE\\Wow6432Node\\JavaSoft\\JDK")
|
||||
|
||||
fun MutableCollection<JdkId>.discoverJdksOnWindows(project: Project) {
|
||||
val registry = Native.get(WindowsRegistry::class.java)
|
||||
|
||||
@@ -70,6 +70,8 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
if (project == project.rootProject) {
|
||||
project.tasks.create("pill") {
|
||||
doLast { pill(project) }
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
|
||||
project.tasks.create("unpill") {
|
||||
@@ -188,17 +190,32 @@ class JpsCompatiblePlugin : Plugin<Project> {
|
||||
junitConfiguration.apply {
|
||||
getOrCreateChild("option", "name" to "WORKING_DIRECTORY").setAttribute("value", "file://\$PROJECT_DIR\$")
|
||||
getOrCreateChild("option", "name" to "VM_PARAMETERS").also { vmParams ->
|
||||
val ideaHomePathOptionKey = "-Didea.home.path="
|
||||
val ideaHomePathOption = ideaHomePathOptionKey + platformDirProjectRelative
|
||||
|
||||
val existingOptions = vmParams.getAttributeValue("value", "")
|
||||
var options = vmParams.getAttributeValue("value", "")
|
||||
.split(' ')
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() && !it.startsWith(ideaHomePathOptionKey) }
|
||||
.filter { it.isNotEmpty() }
|
||||
|
||||
val newOptions = existingOptions.joinToString(" ") + " " + ideaHomePathOption
|
||||
fun addOrReplaceOptionValue(name: String, value: Any) {
|
||||
options = options.filter { !it.startsWith("-D$name=") } + listOf("-D$name=$value")
|
||||
}
|
||||
|
||||
vmParams.setAttribute("value", newOptions)
|
||||
val robolectricClasspath = project.rootProject
|
||||
.project(":plugins:android-extensions-compiler")
|
||||
.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))
|
||||
|
||||
vmParams.setAttribute("value", options.joinToString(" "))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,17 @@ private inline fun String.isFirstChar(f: (Char) -> Boolean) = isNotEmpty() && f(
|
||||
inline fun <reified T : Task> Project.getOrCreateTask(taskName: String, body: T.() -> Unit): T =
|
||||
(tasks.findByName(taskName)?.let { it as T } ?: task<T>(taskName)).apply { body() }
|
||||
|
||||
private fun Test.useAndroidConfiguration(systemPropertyName: String, configName: String) {
|
||||
object TaskUtils {
|
||||
fun useAndroidSdk(task: Task) {
|
||||
task.useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidSdk")
|
||||
}
|
||||
|
||||
fun useAndroidJar(task: Task) {
|
||||
task.useAndroidConfiguration(systemPropertyName = "android.jar", configName = "androidJar")
|
||||
}
|
||||
}
|
||||
|
||||
private fun Task.useAndroidConfiguration(systemPropertyName: String, configName: String) {
|
||||
val configuration = with(project) {
|
||||
configurations.getOrCreate(configName)
|
||||
.also {
|
||||
@@ -95,15 +105,18 @@ private fun Test.useAndroidConfiguration(systemPropertyName: String, configName:
|
||||
}
|
||||
|
||||
dependsOn(configuration)
|
||||
doFirst {
|
||||
systemProperty(systemPropertyName, configuration.singleFile.canonicalPath)
|
||||
|
||||
if (this is Test) {
|
||||
doFirst {
|
||||
systemProperty(systemPropertyName, configuration.singleFile.canonicalPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.useAndroidSdk() {
|
||||
useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidSdk")
|
||||
fun Task.useAndroidSdk() {
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
}
|
||||
|
||||
fun Test.useAndroidJar() {
|
||||
useAndroidConfiguration(systemPropertyName = "android.jar", configName = "androidJar")
|
||||
fun Task.useAndroidJar() {
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
@@ -17,20 +17,18 @@
|
||||
package org.jetbrains.kotlin.backend.common.bridges
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
||||
|
||||
fun <Signature> generateBridgesForFunctionDescriptor(
|
||||
descriptor: FunctionDescriptor,
|
||||
signature: (FunctionDescriptor) -> Signature,
|
||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
||||
descriptor: FunctionDescriptor,
|
||||
signature: (FunctionDescriptor) -> Signature,
|
||||
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||
): Set<Bridge<Signature>> {
|
||||
return generateBridges(DescriptorBasedFunctionHandle(descriptor, isBodyOwner), { signature(it.descriptor) })
|
||||
return generateBridges(DescriptorBasedFunctionHandle(descriptor, areDeclarationAndDefinitionSame), { signature(it.descriptor) })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,26 +49,28 @@ fun <Signature> generateBridgesForFunctionDescriptor(
|
||||
* eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated.
|
||||
*/
|
||||
class DescriptorBasedFunctionHandle(
|
||||
val descriptor: FunctionDescriptor,
|
||||
/*
|
||||
To generate proper bridges for non-abstract function
|
||||
we should know if the function declaration and its definition in the target platform are the same or not.
|
||||
For JS and JVM8 they are placed in interface classes and we need generate bridge for such function ('isAbstract' will return false).
|
||||
For JVM6 target function body generated in separate place (DefaultImpl) and method in interface is abstract
|
||||
For JVM6 target function body is generated in a separate place (DefaultImpls) and
|
||||
the method in the interface is abstract so we must not generate bridges for such cases.
|
||||
*/
|
||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
||||
val descriptor: FunctionDescriptor,
|
||||
/*
|
||||
To generate proper bridges for non-abstract function
|
||||
we should know if the function declaration and its definition in the target platform are the same or not.
|
||||
For JS and @JvmDefault JVM members they are placed in interface classes and
|
||||
we need generate bridge for such function ('isAbstract' will return false).
|
||||
For non-@JvmDefault function, its body is generated in a separate place (DefaultImpls) and
|
||||
the method in the interface is abstract so we must not generate bridges for such cases.
|
||||
*/
|
||||
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||
) : FunctionHandle {
|
||||
private val overridden = descriptor.overriddenDescriptors.map { DescriptorBasedFunctionHandle(it.original, isBodyOwner) }
|
||||
private val overridden = descriptor.overriddenDescriptors.map {
|
||||
DescriptorBasedFunctionHandle(
|
||||
it.original,
|
||||
areDeclarationAndDefinitionSame
|
||||
)
|
||||
}
|
||||
|
||||
override val isDeclaration: Boolean =
|
||||
descriptor.kind.isReal ||
|
||||
findInterfaceImplementation(descriptor) != null
|
||||
override val isDeclaration: Boolean = descriptor.kind.isReal || findInterfaceImplementation(descriptor) != null
|
||||
|
||||
override val isAbstract: Boolean =
|
||||
descriptor.modality == Modality.ABSTRACT ||
|
||||
isBodyOwner(descriptor.containingDeclaration)
|
||||
descriptor.modality == Modality.ABSTRACT || !areDeclarationAndDefinitionSame(descriptor)
|
||||
|
||||
override val isInterfaceDeclaration: Boolean
|
||||
get() = DescriptorUtils.isInterface(descriptor.containingDeclaration)
|
||||
|
||||
@@ -58,6 +58,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAn
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -180,9 +181,9 @@ public class AsmUtil {
|
||||
return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes));
|
||||
}
|
||||
|
||||
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind, GenerationState state) {
|
||||
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
return (functionDescriptor.getModality() == Modality.ABSTRACT ||
|
||||
(isJvmInterface(functionDescriptor.getContainingDeclaration()) && !state.isJvm8TargetWithDefaults()))
|
||||
(isJvmInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor)))
|
||||
&& !isStaticMethod(kind, functionDescriptor);
|
||||
}
|
||||
|
||||
@@ -226,7 +227,7 @@ public class AsmUtil {
|
||||
flags |= ACC_STATIC;
|
||||
}
|
||||
|
||||
if (isAbstractMethod(functionDescriptor, kind, state)) {
|
||||
if (isAbstractMethod(functionDescriptor, kind)) {
|
||||
flags |= ACC_ABSTRACT;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,27 +19,28 @@ import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.util.Printer
|
||||
|
||||
class CallableMethod(
|
||||
override val owner: Type,
|
||||
private val defaultImplOwner: Type?,
|
||||
private val defaultMethodDesc: String,
|
||||
private val signature: JvmMethodSignature,
|
||||
private val invokeOpcode: Int,
|
||||
override val dispatchReceiverType: Type?,
|
||||
override val dispatchReceiverKotlinType: KotlinType?,
|
||||
override val extensionReceiverType: Type?,
|
||||
override val extensionReceiverKotlinType: KotlinType?,
|
||||
override val generateCalleeType: Type?,
|
||||
override val returnKotlinType: KotlinType?,
|
||||
private val isInterfaceMethod: Boolean = Opcodes.INVOKEINTERFACE == invokeOpcode
|
||||
override val owner: Type,
|
||||
private val defaultImplOwner: Type?,
|
||||
private val defaultMethodDesc: String,
|
||||
private val signature: JvmMethodSignature,
|
||||
private val invokeOpcode: Int,
|
||||
override val dispatchReceiverType: Type?,
|
||||
override val dispatchReceiverKotlinType: KotlinType?,
|
||||
override val extensionReceiverType: Type?,
|
||||
override val extensionReceiverKotlinType: KotlinType?,
|
||||
override val generateCalleeType: Type?,
|
||||
override val returnKotlinType: KotlinType?,
|
||||
private val isInterfaceMethod: Boolean = Opcodes.INVOKEINTERFACE == invokeOpcode,
|
||||
private val isDefaultMethodInInterface: Boolean = false
|
||||
) : Callable {
|
||||
fun getValueParameters(): List<JvmMethodParameterSignature> =
|
||||
signature.valueParameters
|
||||
signature.valueParameters
|
||||
|
||||
override val valueParameterTypes: List<Type>
|
||||
get() = signature.valueParameters.filter { it.kind == JvmMethodParameterKind.VALUE }.map { it.asmType }
|
||||
|
||||
fun getAsmMethod(): Method =
|
||||
signature.asmMethod
|
||||
signature.asmMethod
|
||||
|
||||
override val parameterTypes: Array<Type>
|
||||
get() = getAsmMethod().argumentTypes
|
||||
@@ -47,11 +48,11 @@ class CallableMethod(
|
||||
|
||||
override fun genInvokeInstruction(v: InstructionAdapter) {
|
||||
v.visitMethodInsn(
|
||||
invokeOpcode,
|
||||
owner.internalName,
|
||||
getAsmMethod().name,
|
||||
getAsmMethod().descriptor,
|
||||
isInterfaceMethod
|
||||
invokeOpcode,
|
||||
owner.internalName,
|
||||
getAsmMethod().name,
|
||||
getAsmMethod().descriptor,
|
||||
isInterfaceMethod
|
||||
)
|
||||
}
|
||||
|
||||
@@ -64,10 +65,11 @@ class CallableMethod(
|
||||
|
||||
if ("<init>" == method.name) {
|
||||
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.internalName, "<init>", defaultMethodDesc, false)
|
||||
}
|
||||
else {
|
||||
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.internalName,
|
||||
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
|
||||
} else {
|
||||
v.visitMethodInsn(
|
||||
INVOKESTATIC, defaultImplOwner.internalName,
|
||||
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, isDefaultMethodInInterface
|
||||
)
|
||||
|
||||
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
|
||||
}
|
||||
@@ -77,8 +79,8 @@ class CallableMethod(
|
||||
get() = signature.returnType
|
||||
|
||||
override fun isStaticCall(): Boolean =
|
||||
invokeOpcode == INVOKESTATIC
|
||||
invokeOpcode == INVOKESTATIC
|
||||
|
||||
override fun toString(): String =
|
||||
"${Printer.OPCODES[invokeOpcode]} $owner.$signature"
|
||||
"${Printer.OPCODES[invokeOpcode]} $owner.$signature"
|
||||
}
|
||||
|
||||
@@ -1488,6 +1488,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
if (tryCatchBlockEnd != null) {
|
||||
if (finallyBlockStackElement != null) {
|
||||
markLineNumber(finallyBlockStackElement.expression, true);
|
||||
}
|
||||
|
||||
v.goTo(tryCatchBlockEnd);
|
||||
}
|
||||
|
||||
@@ -2416,7 +2420,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
) {
|
||||
boolean isSafeCallOrOnStack = receiver instanceof StackValue.SafeCall || receiver instanceof StackValue.OnStack;
|
||||
|
||||
if (isSuspendCall && !isSafeCallOrOnStack) {
|
||||
if (isSuspendCall && !isSafeCallOrOnStack && !tailRecursionCodegen.isTailRecursion(resolvedCall)) {
|
||||
// Inline markers are used to spill the stack before coroutine suspension
|
||||
addInlineMarker(v, true);
|
||||
}
|
||||
|
||||
@@ -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.JvmTarget;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
@@ -66,7 +67,6 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
||||
import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable;
|
||||
@@ -74,6 +74,7 @@ import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarg
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -86,10 +87,12 @@ public class FunctionCodegen {
|
||||
private final ClassBuilder v;
|
||||
private final MemberCodegen<?> memberCodegen;
|
||||
|
||||
private final Function1<DeclarationDescriptor, Boolean> IS_PURE_INTERFACE_CHECKER = new Function1<DeclarationDescriptor, Boolean>() {
|
||||
private final Function1<CallableMemberDescriptor, Boolean> DECLARATION_AND_DEFINITION_CHECKER = new Function1<CallableMemberDescriptor, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(DeclarationDescriptor descriptor) {
|
||||
return JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state);
|
||||
public Boolean invoke(CallableMemberDescriptor descriptor) {
|
||||
return !isInterface(descriptor.getContainingDeclaration()) ||
|
||||
(state.getTarget() != JvmTarget.JVM_1_6 &&
|
||||
hasJvmDefaultAnnotation(descriptor));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -173,11 +176,7 @@ public class FunctionCodegen {
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
if (isInterface(containingDeclaration) &&
|
||||
functionDescriptor.getVisibility() == Visibilities.PRIVATE &&
|
||||
!processInterfaceMember(functionDescriptor, contextKind, state)) {
|
||||
return;
|
||||
}
|
||||
if (isInterface(containingDeclaration) && !processInterfaceMethod(functionDescriptor, contextKind, false)) return;
|
||||
|
||||
boolean hasSpecialBridge = hasSpecialBridgeMethod(functionDescriptor);
|
||||
JvmMethodGenericSignature jvmSignature = strategy.mapMethodSignature(functionDescriptor, typeMapper, contextKind, hasSpecialBridge);
|
||||
@@ -220,10 +219,6 @@ public class FunctionCodegen {
|
||||
generateBridges(functionDescriptor);
|
||||
}
|
||||
|
||||
if (isJvm8InterfaceWithDefaultsMember(functionDescriptor, state) && contextKind != OwnerKind.DEFAULT_IMPLS && state.getGenerateDefaultImplsForJvm8()) {
|
||||
generateDelegateForDefaultImpl(functionDescriptor, origin.getElement());
|
||||
}
|
||||
|
||||
boolean staticInCompanionObject = CodegenUtilKt.isJvmStaticInCompanionObject(functionDescriptor);
|
||||
if (staticInCompanionObject) {
|
||||
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
|
||||
@@ -376,7 +371,7 @@ public class FunctionCodegen {
|
||||
boolean staticInCompanionObject
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
|
||||
if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind)) {
|
||||
generateLocalVariableTable(
|
||||
mv,
|
||||
jvmSignature,
|
||||
@@ -597,18 +592,6 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else if (OwnerKind.DEFAULT_IMPLS == context.getContextKind() && isJvm8InterfaceWithDefaultsMember(functionDescriptor, parentCodegen.state)) {
|
||||
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;
|
||||
Type type = typeMapper.mapOwner(functionDescriptor);
|
||||
Method asmMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.DEFAULT_IMPLS);
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
new Method(asmMethod.getName() + JvmAbi.DEFAULT_IMPLS_DELEGATE_SUFFIX, asmMethod.getDescriptor()),
|
||||
type.getInternalName()
|
||||
);
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else {
|
||||
FrameMap frameMap = createFrameMap(
|
||||
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
|
||||
@@ -959,14 +942,14 @@ public class FunctionCodegen {
|
||||
private boolean hasSpecialBridgeMethod(@NotNull FunctionDescriptor descriptor) {
|
||||
if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) == null) return false;
|
||||
return !BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||
descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER
|
||||
descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER
|
||||
).isEmpty();
|
||||
}
|
||||
|
||||
public void generateBridges(@NotNull FunctionDescriptor descriptor) {
|
||||
if (descriptor instanceof ConstructorDescriptor) return;
|
||||
if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
|
||||
if (IS_PURE_INTERFACE_CHECKER.invoke(descriptor.getContainingDeclaration())) return;
|
||||
if (!DECLARATION_AND_DEFINITION_CHECKER.invoke(descriptor)) return;
|
||||
|
||||
// equals(Any?), hashCode(), toString() never need bridges
|
||||
if (isMethodOfAny(descriptor)) return;
|
||||
@@ -976,7 +959,7 @@ public class FunctionCodegen {
|
||||
Set<Bridge<Method>> bridgesToGenerate;
|
||||
if (!isSpecial) {
|
||||
bridgesToGenerate =
|
||||
ImplKt.generateBridgesForFunctionDescriptor(descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER);
|
||||
ImplKt.generateBridgesForFunctionDescriptor(descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER);
|
||||
if (!bridgesToGenerate.isEmpty()) {
|
||||
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
|
||||
boolean isSpecialBridge =
|
||||
@@ -989,7 +972,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
else {
|
||||
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||
descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER
|
||||
descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER
|
||||
);
|
||||
|
||||
if (!specials.isEmpty()) {
|
||||
@@ -1001,7 +984,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state)) {
|
||||
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
|
||||
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
|
||||
assert overridden != null;
|
||||
|
||||
@@ -1073,7 +1056,8 @@ public class FunctionCodegen {
|
||||
) {
|
||||
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
||||
|
||||
if (isInterface(contextClass) && !processInterface(contextClass, kind, state)) {
|
||||
if (isInterface(contextClass) &&
|
||||
!processInterfaceMethod(functionDescriptor, kind, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1088,7 +1072,7 @@ public class FunctionCodegen {
|
||||
AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
|
||||
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
|
||||
if (!(functionDescriptor instanceof ConstructorDescriptor)) {
|
||||
flags |= ACC_STATIC;
|
||||
flags |= ACC_STATIC | ACC_BRIDGE;
|
||||
}
|
||||
|
||||
Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);
|
||||
@@ -1330,7 +1314,7 @@ public class FunctionCodegen {
|
||||
iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false);
|
||||
}
|
||||
else {
|
||||
if (isJvm8InterfaceWithDefaultsMember(descriptor, state)) {
|
||||
if (hasJvmDefaultAnnotation(descriptor)) {
|
||||
iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
|
||||
}
|
||||
else {
|
||||
@@ -1489,20 +1473,23 @@ public class FunctionCodegen {
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean processInterfaceMember(
|
||||
@NotNull CallableMemberDescriptor function,
|
||||
public static boolean processInterfaceMethod(
|
||||
@NotNull CallableMemberDescriptor memberDescriptor,
|
||||
@NotNull OwnerKind kind,
|
||||
@NotNull GenerationState state
|
||||
boolean isDefaultOrSynthetic
|
||||
) {
|
||||
return processInterface(function.getContainingDeclaration(), kind, state);
|
||||
}
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
|
||||
containingDeclaration;
|
||||
|
||||
public static boolean processInterface(
|
||||
@NotNull DeclarationDescriptor contextClass,
|
||||
@NotNull OwnerKind kind,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
assert isInterface(contextClass) : "'processInterface' method should be called only for interfaces, but: " + contextClass;
|
||||
return JvmCodegenUtil.isJvm8InterfaceWithDefaults(contextClass, state) ? kind != OwnerKind.DEFAULT_IMPLS : kind == OwnerKind.DEFAULT_IMPLS;
|
||||
if (hasJvmDefaultAnnotation(memberDescriptor)) {
|
||||
return kind != OwnerKind.DEFAULT_IMPLS;
|
||||
} else {
|
||||
switch (kind) {
|
||||
case DEFAULT_IMPLS: return true;
|
||||
case IMPLEMENTATION: return !Visibilities.isPrivate(memberDescriptor.getVisibility()) && !isDefaultOrSynthetic;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationCons
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
@@ -216,7 +217,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Override
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
if (isInterface(descriptor) && !isLocal && (!JvmCodegenUtil.isJvm8InterfaceWithDefaults(descriptor, state) || state.getGenerateDefaultImplsForJvm8())) {
|
||||
if (isInterface(descriptor) && !isLocal) {
|
||||
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
|
||||
ClassBuilder defaultImplsBuilder =
|
||||
state.getFactory().newVisitor(JvmDeclarationOriginKt.DefaultImpls(myClass.getPsiOrParent(), descriptor), defaultImplsType, myClass.getContainingKtFile());
|
||||
@@ -400,9 +401,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateDelegates(delegationFieldsInfo);
|
||||
|
||||
if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
|
||||
generateSyntheticAccessors();
|
||||
}
|
||||
generateSyntheticAccessors();
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
@@ -1405,23 +1404,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateTraitMethods() {
|
||||
if (isInterfaceWithoutDefaults(descriptor, state)) return;
|
||||
if (isInterface(descriptor)) return;
|
||||
|
||||
List<FunctionDescriptor> restrictedInheritance = new ArrayList<>();
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
FunctionDescriptor interfaceFun = entry.getKey();
|
||||
//skip java 8 default methods
|
||||
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !isJvm8InterfaceWithDefaultsMember(interfaceFun, state)) {
|
||||
if (state.isJvm8TargetWithDefaults() && !JvmCodegenUtil.isJvm8InterfaceWithDefaults(interfaceFun.getContainingDeclaration(), state)) {
|
||||
restrictedInheritance.add(interfaceFun);
|
||||
}
|
||||
else {
|
||||
generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
|
||||
}
|
||||
if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !hasJvmDefaultAnnotation(interfaceFun)) {
|
||||
generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
CodegenUtilKt.reportTarget6InheritanceErrorIfNeeded(descriptor, myClass.getPsiOrParent(), restrictedInheritance, state);
|
||||
}
|
||||
|
||||
private void generateDelegationToDefaultImpl(@NotNull FunctionDescriptor interfaceFun, @NotNull FunctionDescriptor inheritedFun) {
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.FacadePartWithSourceFile;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.context.RootContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
@@ -36,9 +35,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -48,6 +45,7 @@ import static org.jetbrains.kotlin.descriptors.Modality.ABSTRACT;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
|
||||
public class JvmCodegenUtil {
|
||||
@@ -55,40 +53,7 @@ public class JvmCodegenUtil {
|
||||
private JvmCodegenUtil() {
|
||||
}
|
||||
|
||||
public static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
||||
return isInterfaceWithoutDefaults(descriptor, state.isJvm8Target(), state.isJvm8TargetWithDefaults());
|
||||
}
|
||||
|
||||
private static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
|
||||
if (!DescriptorUtils.isInterface(descriptor)) return false;
|
||||
|
||||
if (descriptor instanceof DeserializedClassDescriptor) {
|
||||
SourceElement source = ((DeserializedClassDescriptor) descriptor).getSource();
|
||||
if (source instanceof KotlinJvmBinarySourceElement) {
|
||||
KotlinJvmBinaryClass binaryClass = ((KotlinJvmBinarySourceElement) source).getBinaryClass();
|
||||
assert binaryClass instanceof FileBasedKotlinClass :
|
||||
"KotlinJvmBinaryClass should be subclass of FileBasedKotlinClass, but " + binaryClass;
|
||||
/*TODO need add some flags to compiled code*/
|
||||
return true || ((FileBasedKotlinClass) binaryClass).getClassVersion() == Opcodes.V1_6;
|
||||
}
|
||||
}
|
||||
return !isJvm8TargetWithDefaults;
|
||||
}
|
||||
|
||||
public static boolean isJvm8InterfaceWithDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
||||
return isJvm8InterfaceWithDefaults(descriptor, state.isJvm8Target(), state.isJvm8TargetWithDefaults());
|
||||
}
|
||||
|
||||
public static boolean isJvm8InterfaceWithDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
|
||||
return DescriptorUtils.isInterface(descriptor) && !isInterfaceWithoutDefaults(descriptor, isJvm8Target, isJvm8TargetWithDefaults);
|
||||
}
|
||||
|
||||
public static boolean isJvm8InterfaceWithDefaultsMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) {
|
||||
DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
|
||||
return isJvm8InterfaceWithDefaults(declaration, state);
|
||||
}
|
||||
|
||||
public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) {
|
||||
public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor) {
|
||||
if (!isJvmInterface(descriptor.getContainingDeclaration())) {
|
||||
return false;
|
||||
}
|
||||
@@ -96,7 +61,7 @@ public class JvmCodegenUtil {
|
||||
return descriptor.getModality() == Modality.ABSTRACT;
|
||||
}
|
||||
|
||||
return !isJvm8InterfaceWithDefaultsMember(descriptor, state);
|
||||
return !hasJvmDefaultAnnotation(descriptor);
|
||||
}
|
||||
|
||||
public static boolean isJvmInterface(DeclarationDescriptor descriptor) {
|
||||
@@ -202,7 +167,15 @@ public class JvmCodegenUtil {
|
||||
}
|
||||
|
||||
if (!isCallInsideSameClassAsFieldRepresentingProperty(property, context)) {
|
||||
if (!isDebuggerContext(context)) {
|
||||
DeclarationDescriptor propertyOwner = property.getContainingDeclaration();
|
||||
boolean isAnnotationValue;
|
||||
if (propertyOwner instanceof ClassDescriptor) {
|
||||
isAnnotationValue = ((ClassDescriptor) propertyOwner).getKind() == ANNOTATION_CLASS;
|
||||
} else {
|
||||
isAnnotationValue = false;
|
||||
}
|
||||
|
||||
if (isAnnotationValue || !isDebuggerContext(context)) {
|
||||
// Unless we are evaluating expression in debugger context, only properties of the same class can be directly accessed
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -63,12 +63,12 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getInlineName;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
|
||||
@@ -407,7 +407,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
ClassDescriptor classDescriptor = ((ClassContext) outermost).getContextDescriptor();
|
||||
if (context instanceof MethodContext) {
|
||||
FunctionDescriptor functionDescriptor = ((MethodContext) context).getFunctionDescriptor();
|
||||
if (isInterface(functionDescriptor.getContainingDeclaration()) && !isJvm8InterfaceWithDefaultsMember(functionDescriptor, state)) {
|
||||
if (isInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor)) {
|
||||
return typeMapper.mapDefaultImpls(classDescriptor);
|
||||
}
|
||||
}
|
||||
@@ -695,9 +695,16 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateSyntheticAccessors() {
|
||||
protected final void generateSyntheticAccessors() {
|
||||
for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) {
|
||||
generateSyntheticAccessor(accessor);
|
||||
boolean hasJvmDefaultAnnotation = hasJvmDefaultAnnotation(accessor.getCalleeDescriptor());
|
||||
OwnerKind kind = context.getContextKind();
|
||||
|
||||
if (!isInterface(context.getContextDescriptor()) ||
|
||||
(hasJvmDefaultAnnotation && kind == OwnerKind.IMPLEMENTATION) ||
|
||||
(!hasJvmDefaultAnnotation && kind == OwnerKind.DEFAULT_IMPLS)) {
|
||||
generateSyntheticAccessor(accessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,7 +820,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) &&
|
||||
!isNonDefaultInterfaceMember(functionDescriptor, state) &&
|
||||
!isNonDefaultInterfaceMember(functionDescriptor) &&
|
||||
!isJvmStaticInObjectOrClass;
|
||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
|
||||
|
||||
@@ -350,9 +350,7 @@ public class PropertyCodegen {
|
||||
if (annotations.getAllAnnotations().isEmpty()) return;
|
||||
|
||||
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
|
||||
if (!isInterface(contextDescriptor) ||
|
||||
(FunctionCodegen.processInterface(contextDescriptor, kind, state) ||
|
||||
(kind == OwnerKind.DEFAULT_IMPLS && state.getGenerateDefaultImplsForJvm8()))) {
|
||||
if (!isInterface(contextDescriptor) || FunctionCodegen.processInterfaceMethod(descriptor, kind, true)) {
|
||||
memberCodegen.generateSyntheticAnnotationsMethod(
|
||||
descriptor, getSyntheticMethodSignature(descriptor), annotations, AnnotationUseSiteTarget.PROPERTY
|
||||
);
|
||||
|
||||
@@ -2061,7 +2061,7 @@ public abstract class StackValue {
|
||||
@NotNull CallableDescriptor descriptor
|
||||
) {
|
||||
throw new RuntimeException(
|
||||
"Augment assignment and increment are not supported for local delegated properties ans inline properties: " +
|
||||
"Augmented assignment and increment are not supported for local delegated properties and inline properties: " +
|
||||
descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.common.bridges.DescriptorBasedFunctionHandle
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
@@ -45,16 +44,16 @@ class BridgeForBuiltinSpecial<out Signature : Any>(
|
||||
|
||||
object BuiltinSpecialBridgesUtil {
|
||||
@JvmStatic fun <Signature : Any> generateBridgesForBuiltinSpecial(
|
||||
function: FunctionDescriptor,
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature,
|
||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
||||
function: FunctionDescriptor,
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature,
|
||||
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||
): Set<BridgeForBuiltinSpecial<Signature>> {
|
||||
|
||||
val functionHandle = DescriptorBasedFunctionHandle(function, isBodyOwner)
|
||||
val functionHandle = DescriptorBasedFunctionHandle(function, areDeclarationAndDefinitionSame)
|
||||
val fake = !functionHandle.isDeclaration
|
||||
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
|
||||
|
||||
val reachableDeclarations = findAllReachableDeclarations(function, isBodyOwner)
|
||||
val reachableDeclarations = findAllReachableDeclarations(function, areDeclarationAndDefinitionSame)
|
||||
|
||||
// e.g. `getSize()I`
|
||||
val methodItself = signatureByDescriptor(function)
|
||||
@@ -78,8 +77,10 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
if (fake) {
|
||||
for (overridden in function.overriddenDescriptors.map { it.original }) {
|
||||
if (!DescriptorBasedFunctionHandle(overridden, isBodyOwner).isAbstract) {
|
||||
commonBridges.removeAll(findAllReachableDeclarations(overridden, isBodyOwner).map(signatureByDescriptor))
|
||||
if (!DescriptorBasedFunctionHandle(overridden, areDeclarationAndDefinitionSame).isAbstract) {
|
||||
commonBridges.removeAll(findAllReachableDeclarations(overridden,
|
||||
areDeclarationAndDefinitionSame
|
||||
).map(signatureByDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +89,7 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
val superImplementationDescriptor =
|
||||
if (specialBridge != null && fake && !functionHandle.isAbstract)
|
||||
findSuperImplementationForStubDelegation(function, isBodyOwner, signatureByDescriptor)
|
||||
findSuperImplementationForStubDelegation(function, areDeclarationAndDefinitionSame, signatureByDescriptor)
|
||||
else
|
||||
null
|
||||
|
||||
@@ -137,11 +138,11 @@ object BuiltinSpecialBridgesUtil {
|
||||
* Also note that there is no special bridges for final declarations, thus no stubs either
|
||||
*/
|
||||
private fun <Signature> findSuperImplementationForStubDelegation(
|
||||
function: FunctionDescriptor,
|
||||
isBodyOwner: (DeclarationDescriptor) -> Boolean,
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||
function: FunctionDescriptor,
|
||||
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean,
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||
): FunctionDescriptor? {
|
||||
val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function, isBodyOwner)).descriptor
|
||||
val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function, areDeclarationAndDefinitionSame)).descriptor
|
||||
|
||||
// Implementation from interface will be generated by common mechanism
|
||||
if (DescriptorUtils.isInterface(implementation.containingDeclaration)) return null
|
||||
@@ -157,10 +158,15 @@ private fun <Signature> findSuperImplementationForStubDelegation(
|
||||
}
|
||||
|
||||
private fun findAllReachableDeclarations(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||
): MutableSet<FunctionDescriptor> =
|
||||
findAllReachableDeclarations(DescriptorBasedFunctionHandle(functionDescriptor, isBodyOwner)).map { it.descriptor }.toMutableSet()
|
||||
findAllReachableDeclarations(
|
||||
DescriptorBasedFunctionHandle(
|
||||
functionDescriptor,
|
||||
areDeclarationAndDefinitionSame
|
||||
)
|
||||
).map { it.descriptor }.toMutableSet()
|
||||
|
||||
private fun <Signature> CallableMemberDescriptor.getSpecialBridgeSignatureIfExists(
|
||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||
|
||||
@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
@@ -39,7 +37,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
@@ -233,26 +230,6 @@ fun ClassBuilder.generateMethod(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun reportTarget6InheritanceErrorIfNeeded(
|
||||
classDescriptor: ClassDescriptor, classElement: PsiElement, restrictedInheritance: List<FunctionDescriptor>, state: GenerationState
|
||||
) {
|
||||
if (!restrictedInheritance.isEmpty()) {
|
||||
val groupBy = restrictedInheritance.groupBy { descriptor -> descriptor.containingDeclaration as ClassDescriptor }
|
||||
|
||||
for ((key, value) in groupBy) {
|
||||
state.diagnostics.report(
|
||||
ErrorsJvm.TARGET6_INTERFACE_INHERITANCE.on(
|
||||
classElement, classDescriptor, key,
|
||||
value.joinToString(separator = "\n", prefix = "\n") {
|
||||
Renderers.COMPACT.render(JvmCodegenUtil.getDirectMember(it), RenderingContext.Empty)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CallableDescriptor.isJvmStaticInObjectOrClassOrInterface(): Boolean =
|
||||
isJvmStaticIn {
|
||||
DescriptorUtils.isNonCompanionObject(it) ||
|
||||
@@ -439,4 +416,4 @@ fun MethodNode.textifyMethodNode(): String {
|
||||
val sw = StringWriter()
|
||||
text.print(PrintWriter(sw))
|
||||
return "$sw"
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,8 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.isCallableMemberWithJvmDefaultAnnotation;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
|
||||
|
||||
@@ -414,7 +416,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
@NotNull D descriptor,
|
||||
@Nullable ClassDescriptor superCallTarget,
|
||||
@NotNull GenerationState state) {
|
||||
if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor, state)) {
|
||||
if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor)) {
|
||||
CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext();
|
||||
CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + descriptor;
|
||||
@@ -569,10 +571,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
CodegenContext properContext = getFirstCrossInlineOrNonInlineContext();
|
||||
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
|
||||
boolean isInliningContext = properContext.isInlineMethodContext();
|
||||
boolean sameJvmDefault = hasJvmDefaultAnnotation(descriptor) ==
|
||||
isCallableMemberWithJvmDefaultAnnotation(properContext.contextDescriptor) ||
|
||||
properContext.contextDescriptor instanceof AccessorForCallableDescriptor;
|
||||
if (!isInliningContext && (
|
||||
!properContext.hasThisDescriptor() ||
|
||||
enclosing == properContext.getThisDescriptor() ||
|
||||
enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) {
|
||||
((enclosing == properContext.getThisDescriptor()) && sameJvmDefault) ||
|
||||
((enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor()) && sameJvmDefault))) {
|
||||
return descriptor;
|
||||
}
|
||||
return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext);
|
||||
@@ -623,6 +628,11 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (descriptorContext == null) {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
if (hasJvmDefaultAnnotation(descriptor) && descriptorContext instanceof DefaultImplsClassContext) {
|
||||
descriptorContext = ((DefaultImplsClassContext) descriptorContext).getInterfaceContext();
|
||||
}
|
||||
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
int propertyAccessFlag = getVisibilityAccessFlag(descriptor);
|
||||
|
||||
@@ -23,20 +23,21 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
|
||||
class DefaultImplsClassContext(
|
||||
typeMapper: KotlinTypeMapper,
|
||||
contextDescriptor: ClassDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>?,
|
||||
localLookup: ((DeclarationDescriptor) -> Boolean)?,
|
||||
private val interfaceContext: ClassContext
|
||||
typeMapper: KotlinTypeMapper,
|
||||
contextDescriptor: ClassDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>?,
|
||||
localLookup: ((DeclarationDescriptor) -> Boolean)?,
|
||||
val interfaceContext: ClassContext
|
||||
) : ClassContext(typeMapper, contextDescriptor, contextKind, parentContext, localLookup) {
|
||||
|
||||
override fun getCompanionObjectContext(): CodegenContext<*>? = interfaceContext.companionObjectContext
|
||||
|
||||
override fun getAccessors(): Collection<AccessorForCallableDescriptor<*>> {
|
||||
val accessors = super.getAccessors()
|
||||
val alreadyExistKeys = accessors.map ({ Pair(it.calleeDescriptor, it.superCallTarget) })
|
||||
val filtered = interfaceContext.accessors.associateByTo(linkedMapOf()) { Pair(it.calleeDescriptor, it.superCallTarget) }.apply { keys -= alreadyExistKeys }
|
||||
val alreadyExistKeys = accessors.map({ Pair(it.calleeDescriptor, it.superCallTarget) })
|
||||
val filtered = interfaceContext.accessors.associateByTo(linkedMapOf()) { Pair(it.calleeDescriptor, it.superCallTarget) }
|
||||
.apply { keys -= alreadyExistKeys }
|
||||
return accessors + filtered.values
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
|
||||
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
|
||||
if (succ.opcode != Opcodes.POP) continue
|
||||
if (insn.opcode == Opcodes.ALOAD && methodNode.localVariables.firstOrNull { it.index == insn.localIndex() } != null) continue
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ)).values.flatten()
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
|
||||
if (sources.size != 1) continue
|
||||
res[insn] = succ
|
||||
}
|
||||
@@ -182,7 +182,7 @@ class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
|
||||
it.opcode == Opcodes.ASTORE && it.localIndex() == succ.localIndex()
|
||||
} != 1) continue
|
||||
if (!ignoreLocalVariableTable && methodNode.localVariables.firstOrNull { it.index == succ.localIndex() } != null) continue
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ)).values.flatten()
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ), ignoreCopy = false).values.flatten()
|
||||
if (sources.size > 1) continue
|
||||
res[insn] = succ
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||
|
||||
/*
|
||||
* Replace POP with ARETURN iff
|
||||
@@ -47,7 +48,7 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
|
||||
|
||||
val pops = methodNode.instructions.asSequence().filter { it.opcode == Opcodes.POP }.toList()
|
||||
val popSuccessors = findSuccessors(methodNode, pops)
|
||||
val sourceInsns = findSourceInstructions(internalClassName, methodNode, pops)
|
||||
val sourceInsns = findSourceInstructions(internalClassName, methodNode, pops, ignoreCopy = true)
|
||||
val safePops = filterOutUnsafes(popSuccessors, units, sourceInsns)
|
||||
|
||||
// Replace POP with ARETURN for tail call optimization
|
||||
@@ -122,9 +123,14 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
|
||||
internal fun findSourceInstructions(
|
||||
internalClassName: String,
|
||||
methodNode: MethodNode,
|
||||
insns: Collection<AbstractInsnNode>
|
||||
insns: Collection<AbstractInsnNode>,
|
||||
ignoreCopy: Boolean
|
||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||
val frames = MethodTransformer.analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||
val frames = MethodTransformer.analyze(
|
||||
internalClassName,
|
||||
methodNode,
|
||||
if (ignoreCopy) IgnoringCopyOperationSourceInterpreter() else SourceInterpreter()
|
||||
)
|
||||
return insns.keysToMap {
|
||||
val index = methodNode.instructions.indexOf(it)
|
||||
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -291,7 +291,7 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
val isContinuationCreate = isContinuation && oldInfo != null && resultNode.name == "create" &&
|
||||
resultNode.desc.startsWith("(" + CONTINUATION_ASM_TYPE.descriptor)
|
||||
resultNode.desc.endsWith(")" + CONTINUATION_ASM_TYPE.descriptor)
|
||||
|
||||
for (capturedParamDesc in info.allRecapturedParameters) {
|
||||
if (capturedParamDesc.fieldName == THIS && isContinuationCreate) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberWithJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -58,21 +59,23 @@ interface SourceCompilerForInline {
|
||||
|
||||
val lazySourceMapper: DefaultSourceMapper
|
||||
|
||||
fun generateLambdaBody(adapter: MethodVisitor,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: ExpressionLambda): SMAP
|
||||
fun generateLambdaBody(
|
||||
adapter: MethodVisitor,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: ExpressionLambda
|
||||
): SMAP
|
||||
|
||||
fun doCreateMethodNodeFromSource(
|
||||
callableDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
asmMethod: Method
|
||||
callableDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
asmMethod: Method
|
||||
): SMAPAndMethodNode
|
||||
|
||||
fun generateAndInsertFinallyBlocks(
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
offsetForFinallyLocalVar: Int
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
offsetForFinallyLocalVar: Int
|
||||
)
|
||||
|
||||
fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean
|
||||
@@ -89,7 +92,7 @@ interface SourceCompilerForInline {
|
||||
}
|
||||
|
||||
|
||||
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement): SourceCompilerForInline {
|
||||
class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, override val callElement: KtElement) : SourceCompilerForInline {
|
||||
|
||||
override val state = codegen.state
|
||||
|
||||
@@ -126,51 +129,53 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
val signature = codegen.state.typeMapper.mapSignatureSkipGeneric(context.functionDescriptor, context.contextKind)
|
||||
return InlineCallSiteInfo(
|
||||
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
|
||||
parentCodegen.className, signature.asmMethod.name, signature.asmMethod.descriptor
|
||||
)
|
||||
}
|
||||
|
||||
override val lazySourceMapper
|
||||
get() = codegen.parentCodegen.orCreateSourceMapper
|
||||
|
||||
override fun generateLambdaBody(adapter: MethodVisitor,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: ExpressionLambda): SMAP {
|
||||
override fun generateLambdaBody(
|
||||
adapter: MethodVisitor,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: ExpressionLambda
|
||||
): SMAP {
|
||||
lambdaInfo as? PsiExpressionLambda ?: error("TODO")
|
||||
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
|
||||
val closureContext =
|
||||
if (lambdaInfo.isPropertyReference)
|
||||
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
||||
else
|
||||
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
|
||||
if (lambdaInfo.isPropertyReference)
|
||||
codegen.getContext().intoAnonymousClass(lambdaInfo.classDescriptor, codegen, OwnerKind.IMPLEMENTATION)
|
||||
else
|
||||
codegen.getContext().intoClosure(invokeMethodDescriptor, codegen, state.typeMapper)
|
||||
val context = closureContext.intoInlinedLambda(invokeMethodDescriptor, lambdaInfo.isCrossInline, lambdaInfo.isPropertyReference)
|
||||
|
||||
return generateMethodBody(
|
||||
adapter, invokeMethodDescriptor, context,
|
||||
lambdaInfo.functionWithBodyOrCallableReference,
|
||||
jvmMethodSignature, lambdaInfo
|
||||
adapter, invokeMethodDescriptor, context,
|
||||
lambdaInfo.functionWithBodyOrCallableReference,
|
||||
jvmMethodSignature, lambdaInfo
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateMethodBody(
|
||||
adapter: MethodVisitor,
|
||||
descriptor: FunctionDescriptor,
|
||||
context: MethodContext,
|
||||
expression: KtExpression,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: PsiExpressionLambda?
|
||||
adapter: MethodVisitor,
|
||||
descriptor: FunctionDescriptor,
|
||||
context: MethodContext,
|
||||
expression: KtExpression,
|
||||
jvmMethodSignature: JvmMethodSignature,
|
||||
lambdaInfo: PsiExpressionLambda?
|
||||
): SMAP {
|
||||
val isLambda = lambdaInfo != null
|
||||
|
||||
// Wrapping for preventing marking actual parent codegen as containing reified markers
|
||||
val parentCodegen = FakeMemberCodegen(
|
||||
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
|
||||
if (isLambda)
|
||||
codegen.parentCodegen.className
|
||||
else
|
||||
state.typeMapper.mapImplementationOwner(descriptor).internalName,
|
||||
if (isLambda) emptyList() else additionalInnerClasses,
|
||||
isLambda
|
||||
codegen.parentCodegen, expression, context.parentContext as FieldOwnerContext<*>,
|
||||
if (isLambda)
|
||||
codegen.parentCodegen.className
|
||||
else
|
||||
state.typeMapper.mapImplementationOwner(descriptor).internalName,
|
||||
if (isLambda) emptyList() else additionalInnerClasses,
|
||||
isLambda
|
||||
)
|
||||
|
||||
val strategy = when (expression) {
|
||||
@@ -182,11 +187,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
|
||||
val info = lambdaInfo.propertyReferenceInfo
|
||||
PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
||||
true, info!!.getFunction, info.target, asmType, receiverType,
|
||||
lambdaInfo.functionWithBodyOrCallableReference, state, true
|
||||
true, info!!.getFunction, info.target, asmType, receiverType,
|
||||
lambdaInfo.functionWithBodyOrCallableReference, state, true
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
FunctionReferenceGenerationStrategy(state, descriptor, resolvedCall, receiverType, null, true)
|
||||
}
|
||||
}
|
||||
@@ -205,8 +209,8 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
|
||||
private fun createSMAPWithDefaultMapping(
|
||||
declaration: KtExpression,
|
||||
mappings: List<FileMapping>
|
||||
declaration: KtExpression,
|
||||
mappings: List<FileMapping>
|
||||
): SMAP {
|
||||
val containingFile = declaration.containingFile
|
||||
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in " + containingFile)
|
||||
@@ -216,12 +220,12 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private class FakeMemberCodegen(
|
||||
internal val delegate: MemberCodegen<*>,
|
||||
declaration: KtElement,
|
||||
codegenContext: FieldOwnerContext<*>,
|
||||
private val className: String,
|
||||
private val parentAsInnerClasses: List<ClassDescriptor>,
|
||||
private val isInlineLambdaCodegen: Boolean
|
||||
internal val delegate: MemberCodegen<*>,
|
||||
declaration: KtElement,
|
||||
codegenContext: FieldOwnerContext<*>,
|
||||
private val className: String,
|
||||
private val parentAsInnerClasses: List<ClassDescriptor>,
|
||||
private val isInlineLambdaCodegen: Boolean
|
||||
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
|
||||
|
||||
override fun generateDeclaration() {
|
||||
@@ -248,18 +252,17 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
|
||||
if (isInlineLambdaCodegen) {
|
||||
super.addParentsToInnerClassesIfNeeded(innerClasses)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
innerClasses.addAll(parentAsInnerClasses)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun doCreateMethodNodeFromSource(
|
||||
callableDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
asmMethod: Method
|
||||
callableDescriptor: FunctionDescriptor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
asmMethod: Method
|
||||
): SMAPAndMethodNode {
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor)
|
||||
|
||||
@@ -269,10 +272,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val inliningFunction = element as KtDeclarationWithBody?
|
||||
|
||||
val node = MethodNode(
|
||||
API,
|
||||
AsmUtil.getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
|
||||
asmMethod.name,
|
||||
asmMethod.descriptor, null, null
|
||||
API,
|
||||
AsmUtil.getMethodAsmFlags(callableDescriptor, context.contextKind, state) or if (callDefault) Opcodes.ACC_STATIC else 0,
|
||||
asmMethod.name,
|
||||
asmMethod.descriptor, null, null
|
||||
)
|
||||
|
||||
//for maxLocals calculation
|
||||
@@ -283,10 +286,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val smap = if (callDefault) {
|
||||
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
|
||||
val parentCodegen = FakeMemberCodegen(
|
||||
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
||||
implementationOwner.internalName,
|
||||
additionalInnerClasses,
|
||||
false
|
||||
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
||||
implementationOwner.internalName,
|
||||
additionalInnerClasses,
|
||||
false
|
||||
)
|
||||
if (element !is KtNamedFunction) {
|
||||
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
|
||||
@@ -296,8 +299,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
|
||||
)
|
||||
createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
|
||||
}
|
||||
maxCalcAdapter.visitMaxs(-1, -1)
|
||||
@@ -307,9 +309,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
}
|
||||
|
||||
override fun generateAndInsertFinallyBlocks(
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
offsetForFinallyLocalVar: Int
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
offsetForFinallyLocalVar: Int
|
||||
) {
|
||||
if (!codegen.hasFinallyBlocks()) return
|
||||
|
||||
@@ -336,8 +338,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val finallyNode = createEmptyMethodNode()
|
||||
finallyNode.visitLabel(start)
|
||||
|
||||
val finallyCodegen = ExpressionCodegen(finallyNode, codegen.frameMap, codegen.returnType,
|
||||
codegen.getContext(), codegen.state, codegen.parentCodegen)
|
||||
val finallyCodegen = ExpressionCodegen(
|
||||
finallyNode, codegen.frameMap, codegen.returnType,
|
||||
codegen.getContext(), codegen.state, codegen.parentCodegen
|
||||
)
|
||||
finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.blockStackElements, curFinallyDepth)
|
||||
|
||||
val frameMap = finallyCodegen.frameMap
|
||||
@@ -390,19 +394,28 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val parentContext = context.parentContext
|
||||
val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) {
|
||||
parentContext.originalSuspendLambdaDescriptor!!
|
||||
}
|
||||
else context.contextDescriptor
|
||||
} else context.contextDescriptor
|
||||
|
||||
return InlineCodegen.getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor)
|
||||
}
|
||||
|
||||
override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
|
||||
context = getContext(functionDescriptor, functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile, additionalInnerClasses)
|
||||
context = getContext(
|
||||
functionDescriptor,
|
||||
functionDescriptor,
|
||||
state,
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile,
|
||||
additionalInnerClasses
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getContext(
|
||||
descriptor: DeclarationDescriptor, innerDescriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?, additionalInners: MutableList<ClassDescriptor>
|
||||
descriptor: DeclarationDescriptor,
|
||||
innerDescriptor: DeclarationDescriptor,
|
||||
state: GenerationState,
|
||||
sourceFile: KtFile?,
|
||||
additionalInners: MutableList<ClassDescriptor>
|
||||
): CodegenContext<*> {
|
||||
if (descriptor is PackageFragmentDescriptor) {
|
||||
//no inners
|
||||
@@ -411,30 +424,32 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
|
||||
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
|
||||
val parent = getContext(
|
||||
container,
|
||||
descriptor,
|
||||
state,
|
||||
sourceFile,
|
||||
additionalInners
|
||||
container,
|
||||
descriptor,
|
||||
state,
|
||||
sourceFile,
|
||||
additionalInners
|
||||
)
|
||||
|
||||
return when (descriptor) {
|
||||
is ScriptDescriptor -> {
|
||||
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
||||
parent.intoScript(
|
||||
descriptor,
|
||||
earlierScripts ?: emptyList(),
|
||||
descriptor as ClassDescriptor, state.typeMapper
|
||||
descriptor,
|
||||
earlierScripts ?: emptyList(),
|
||||
descriptor as ClassDescriptor, state.typeMapper
|
||||
)
|
||||
}
|
||||
is ClassDescriptor -> {
|
||||
val kind =
|
||||
if (DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor)
|
||||
OwnerKind.DEFAULT_IMPLS
|
||||
else OwnerKind.IMPLEMENTATION
|
||||
if (DescriptorUtils.isInterface(descriptor) &&
|
||||
innerDescriptor !is ClassDescriptor && !innerDescriptor.isCallableMemberWithJvmDefaultAnnotation()
|
||||
)
|
||||
OwnerKind.DEFAULT_IMPLS
|
||||
else OwnerKind.IMPLEMENTATION
|
||||
|
||||
additionalInners.addIfNotNull(
|
||||
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
|
||||
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
|
||||
)
|
||||
parent.intoClass(descriptor, kind, state)
|
||||
}
|
||||
|
||||
@@ -82,17 +82,28 @@ class RedundantGotoMethodTransformer : MethodTransformer() {
|
||||
|
||||
private fun rewriteLabelIfNeeded(
|
||||
jumpInsn: JumpInsnNode,
|
||||
labelsToReplace: HashMap<LabelNode, JumpInsnNode>
|
||||
labelsToReplace: Map<LabelNode, JumpInsnNode>
|
||||
) {
|
||||
val lastTargetLabel = getLastTargetJumpInsn(jumpInsn, labelsToReplace).label
|
||||
if (lastTargetLabel != jumpInsn.label) {
|
||||
val lastJumpInsn = getLastTargetJumpInsn(jumpInsn, labelsToReplace, mutableListOf())
|
||||
if (lastJumpInsn != null && lastJumpInsn != jumpInsn) {
|
||||
// Do not remove the old label because it can be used to define a local variable range.
|
||||
jumpInsn.label = lastTargetLabel
|
||||
jumpInsn.label = lastJumpInsn.label
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLastTargetJumpInsn(jumpInsn: JumpInsnNode, labelsToReplace: HashMap<LabelNode, JumpInsnNode>): JumpInsnNode {
|
||||
labelsToReplace[jumpInsn.label]?.let { return getLastTargetJumpInsn(it, labelsToReplace) }
|
||||
private fun getLastTargetJumpInsn(
|
||||
jumpInsn: JumpInsnNode,
|
||||
labelsToReplace: Map<LabelNode, JumpInsnNode>,
|
||||
alreadyVisited: MutableList<JumpInsnNode>
|
||||
): JumpInsnNode? {
|
||||
labelsToReplace[jumpInsn.label]?.let {
|
||||
if (alreadyVisited.contains(it)) {
|
||||
// Cycle detected, do no apply goto optimization
|
||||
return null
|
||||
}
|
||||
alreadyVisited.add(it)
|
||||
return getLastTargetJumpInsn(it, labelsToReplace, alreadyVisited)
|
||||
}
|
||||
return jumpInsn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.range.forLoop
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.generateCallReceiver
|
||||
@@ -24,7 +25,7 @@ class ArrayWithIndexForLoopGenerator(
|
||||
) : AbstractWithIndexForLoopGenerator(codegen, forExpression, loopParameter, rangeCall) {
|
||||
|
||||
private val arrayType = codegen.asmType(ExpressionCodegen.getExpectedReceiverType(rangeCall))
|
||||
private val arrayElementType = arrayType.elementType
|
||||
private val arrayElementType = AsmUtil.correctElementType(arrayType)
|
||||
private var arrayVar = -1
|
||||
private var arrayLengthVar = -1
|
||||
|
||||
|
||||
@@ -26,8 +26,9 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper
|
||||
|
||||
class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
|
||||
// We use empty BindingContext, because it is only used by KotlinTypeMapper for purposes irrelevant to the needs of this class
|
||||
private val typeMapper = KotlinTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
|
||||
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, false)
|
||||
private val typeMapper = KotlinTypeMapper(
|
||||
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
|
||||
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false)
|
||||
|
||||
override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapAsmMethod(function)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
|
||||
// Avoid errors when some classes are not loaded for some reason
|
||||
private val typeMapper = KotlinTypeMapper(
|
||||
bindingContext, ClassBuilderMode.LIGHT_CLASSES, IncompatibleClassTracker.DoNothing, moduleName, false, false
|
||||
bindingContext, ClassBuilderMode.LIGHT_CLASSES, IncompatibleClassTracker.DoNothing, moduleName, false
|
||||
)
|
||||
private val reportDiagnosticsTasks = ArrayList<() -> Unit>()
|
||||
|
||||
|
||||
@@ -177,8 +177,6 @@ class GenerationState private constructor(
|
||||
|
||||
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
|
||||
val isJvm8Target: Boolean = target == JvmTarget.JVM_1_8
|
||||
val isJvm8TargetWithDefaults: Boolean = isJvm8Target && configuration.getBoolean(JVMConfigurationKeys.JVM8_TARGET_WITH_DEFAULTS)
|
||||
val generateDefaultImplsForJvm8: Boolean = configuration.getBoolean(JVMConfigurationKeys.INTERFACE_COMPATIBILITY)
|
||||
|
||||
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
|
||||
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
|
||||
@@ -189,7 +187,7 @@ class GenerationState private constructor(
|
||||
val bindingContext: BindingContext = bindingTrace.bindingContext
|
||||
val typeMapper: KotlinTypeMapper = KotlinTypeMapper(
|
||||
this.bindingContext, classBuilderMode, IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace),
|
||||
this.moduleName, isJvm8Target, isJvm8TargetWithDefaults
|
||||
this.moduleName, isJvm8Target
|
||||
)
|
||||
val intrinsics: IntrinsicMethods = run {
|
||||
val shouldUseConsistentEquals = languageVersionSettings.supportsFeature(LanguageFeature.ThrowNpeOnExplicitEqualsForBoxedNull) &&
|
||||
|
||||
@@ -72,6 +72,7 @@ import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
|
||||
@@ -83,7 +84,6 @@ public class KotlinTypeMapper {
|
||||
private final IncompatibleClassTracker incompatibleClassTracker;
|
||||
private final String moduleName;
|
||||
private final boolean isJvm8Target;
|
||||
private final boolean isJvm8TargetWithDefaults;
|
||||
|
||||
private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() {
|
||||
@NotNull
|
||||
@@ -143,15 +143,13 @@ public class KotlinTypeMapper {
|
||||
@NotNull ClassBuilderMode classBuilderMode,
|
||||
@NotNull IncompatibleClassTracker incompatibleClassTracker,
|
||||
@NotNull String moduleName,
|
||||
boolean isJvm8Target,
|
||||
boolean isJvm8TargetWithDefaults
|
||||
boolean isJvm8Target
|
||||
) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.classBuilderMode = classBuilderMode;
|
||||
this.incompatibleClassTracker = incompatibleClassTracker;
|
||||
this.moduleName = moduleName;
|
||||
this.isJvm8Target = isJvm8Target;
|
||||
this.isJvm8TargetWithDefaults = isJvm8TargetWithDefaults;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -730,8 +728,8 @@ public class KotlinTypeMapper {
|
||||
descriptor = classCallable;
|
||||
continue;
|
||||
}
|
||||
else if (isSuperCall && !isJvm8TargetWithDefaults && !isInterface(descriptor.getContainingDeclaration())) {
|
||||
//Don't unwrap fake overrides from class to interface cause substituted override would be implicitly generated for target 1.6
|
||||
else if (isSuperCall && !hasJvmDefaultAnnotation(descriptor) && !isInterface(descriptor.getContainingDeclaration())) {
|
||||
//Don't unwrap fake overrides from class to interface cause substituted override would be implicitly generated
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@@ -749,7 +747,7 @@ public class KotlinTypeMapper {
|
||||
String defaultImplDesc = mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
|
||||
return new CallableMethod(
|
||||
owner, owner, defaultImplDesc, method, INVOKESPECIAL,
|
||||
null, null, null, null, null, originalDescriptor.getReturnType(), false
|
||||
null, null, null, null, null, originalDescriptor.getReturnType(), false, false
|
||||
);
|
||||
}
|
||||
|
||||
@@ -773,6 +771,7 @@ public class KotlinTypeMapper {
|
||||
Type thisClass;
|
||||
KotlinType dispatchReceiverKotlinType;
|
||||
boolean isInterfaceMember = false;
|
||||
boolean isDefaultMethodInInterface = false;
|
||||
|
||||
if (functionParent instanceof ClassDescriptor) {
|
||||
FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
|
||||
@@ -787,14 +786,15 @@ public class KotlinTypeMapper {
|
||||
|
||||
baseMethodDescriptor = findBaseDeclaration(functionDescriptor).getOriginal();
|
||||
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
|
||||
isDefaultMethodInInterface = isJvmInterface(ownerForDefault) && hasJvmDefaultAnnotation(baseMethodDescriptor);
|
||||
ownerForDefaultImpl =
|
||||
isJvmInterface(ownerForDefault) && !isJvm8InterfaceWithDefaults(ownerForDefault) ?
|
||||
isJvmInterface(ownerForDefault) && !hasJvmDefaultAnnotation(baseMethodDescriptor) ?
|
||||
mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
|
||||
|
||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
|
||||
thisClass = mapClass(currentOwner);
|
||||
dispatchReceiverKotlinType = currentOwner.getDefaultType();
|
||||
if (declarationOwner instanceof JavaClassDescriptor || isJvm8InterfaceWithDefaults(declarationOwner)) {
|
||||
if (declarationOwner instanceof JavaClassDescriptor || hasJvmDefaultAnnotation(declarationFunctionDescriptor)) {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
signature = mapSignatureSkipGeneric(functionDescriptor);
|
||||
returnKotlinType = functionDescriptor.getReturnType();
|
||||
@@ -806,7 +806,14 @@ public class KotlinTypeMapper {
|
||||
FunctionDescriptor originalDescriptor = descriptor.getOriginal();
|
||||
signature = mapSignatureSkipGeneric(originalDescriptor, OwnerKind.DEFAULT_IMPLS);
|
||||
returnKotlinType = originalDescriptor.getReturnType();
|
||||
owner = mapDefaultImpls(currentOwner);
|
||||
if (descriptor instanceof AccessorForCallableDescriptor &&
|
||||
hasJvmDefaultAnnotation(((AccessorForCallableDescriptor) descriptor).getCalleeDescriptor())) {
|
||||
owner = mapClass(currentOwner);
|
||||
isInterfaceMember = true;
|
||||
}
|
||||
else {
|
||||
owner = mapDefaultImpls(currentOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -896,15 +903,10 @@ public class KotlinTypeMapper {
|
||||
return new CallableMethod(
|
||||
owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
|
||||
thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType, calleeType, returnKotlinType,
|
||||
isJvm8Target ? isInterfaceMember : invokeOpcode == INVOKEINTERFACE
|
||||
isJvm8Target ? isInterfaceMember : invokeOpcode == INVOKEINTERFACE, isDefaultMethodInInterface
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isJvm8InterfaceWithDefaults(@NotNull ClassDescriptor ownerForDefault) {
|
||||
return isJvmInterface(ownerForDefault) &&
|
||||
JvmCodegenUtil.isJvm8InterfaceWithDefaults(ownerForDefault, isJvm8Target, isJvm8TargetWithDefaults);
|
||||
}
|
||||
|
||||
public static boolean isAccessor(@Nullable CallableMemberDescriptor descriptor) {
|
||||
return descriptor instanceof AccessorForCallableDescriptor<?>;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.MemberKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
|
||||
@@ -82,7 +84,9 @@ class SignatureDumpingBuilderFactory(
|
||||
}
|
||||
|
||||
override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor {
|
||||
signatures += RawSignature(name, desc, MemberKind.METHOD) to origin.descriptor
|
||||
signatures += RawSignature(name, desc, MemberKind.METHOD) to origin.descriptor?.let {
|
||||
if (it is CallableDescriptor) it.unwrapInitialDescriptorForSuspendFunction() else it
|
||||
}
|
||||
return super.newMethod(origin, access, name, desc, signature, exceptions)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
package org.jetbrains.kotlin.cli.common.arguments
|
||||
|
||||
import com.intellij.util.xmlb.annotations.Transient
|
||||
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.*
|
||||
import java.util.*
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@@ -164,9 +165,89 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
put(AnalysisFlag.allowKotlinPackage, allowKotlinPackage)
|
||||
put(AnalysisFlag.experimental, experimental?.toList().orEmpty())
|
||||
put(AnalysisFlag.useExperimental, useExperimental?.toList().orEmpty())
|
||||
put(AnalysisFlag.explicitApiVersion, apiVersion != null)
|
||||
}
|
||||
}
|
||||
|
||||
open fun configureLanguageFeatures(collector: MessageCollector): MutableMap<LanguageFeature, LanguageFeature.State> =
|
||||
HashMap<LanguageFeature, LanguageFeature.State>().apply {
|
||||
if (multiPlatform) {
|
||||
put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
when (coroutinesState) {
|
||||
CommonCompilerArguments.ERROR -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED_WITH_ERROR)
|
||||
CommonCompilerArguments.ENABLE -> put(LanguageFeature.Coroutines, LanguageFeature.State.ENABLED)
|
||||
CommonCompilerArguments.WARN -> {}
|
||||
else -> {
|
||||
val message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + coroutinesState
|
||||
collector.report(CompilerMessageSeverity.ERROR, message, null)
|
||||
}
|
||||
}
|
||||
|
||||
if (newInference) {
|
||||
put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (legacySmartCastAfterTry) {
|
||||
put(LanguageFeature.SoundSmartCastsAfterTry, LanguageFeature.State.DISABLED)
|
||||
}
|
||||
|
||||
if (effectSystem) {
|
||||
put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED)
|
||||
put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (readDeserializedContracts) {
|
||||
put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (properIeee754Comparisons) {
|
||||
put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
}
|
||||
|
||||
fun configureLanguageVersionSettings(collector: MessageCollector): LanguageVersionSettings {
|
||||
|
||||
// If only "-api-version" is specified, language version is assumed to be the latest stable
|
||||
val languageVersion = parseVersion(collector, languageVersion, "language") ?: LanguageVersion.LATEST_STABLE
|
||||
|
||||
// If only "-language-version" is specified, API version is assumed to be equal to the language version
|
||||
// (API version cannot be greater than the language version)
|
||||
val apiVersion = parseVersion(collector, apiVersion, "API") ?: languageVersion
|
||||
|
||||
if (apiVersion > languageVersion) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.ERROR,
|
||||
"-api-version (${apiVersion.versionString}) cannot be greater than -language-version (${languageVersion.versionString})"
|
||||
)
|
||||
}
|
||||
|
||||
if (!languageVersion.isStable) {
|
||||
collector.report(
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
"Language version ${languageVersion.versionString} is experimental, there are no backwards compatibility guarantees for new language and library features"
|
||||
)
|
||||
}
|
||||
|
||||
return LanguageVersionSettingsImpl(
|
||||
languageVersion,
|
||||
ApiVersion.createByLanguageVersion(apiVersion),
|
||||
configureAnalysisFlags(collector),
|
||||
configureLanguageFeatures(collector)
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseVersion(collector: MessageCollector, value: String?, versionOf: String): LanguageVersion? =
|
||||
if (value == null) null
|
||||
else LanguageVersion.fromVersionString(value)
|
||||
?: run {
|
||||
val versionStrings = LanguageVersion.values().map(LanguageVersion::description)
|
||||
val message = "Unknown $versionOf version: $value\nSupported $versionOf versions: ${versionStrings.joinToString(", ")}"
|
||||
collector.report(CompilerMessageSeverity.ERROR, message, null)
|
||||
null
|
||||
}
|
||||
|
||||
// Used only for serialize and deserialize settings. Don't use in other places!
|
||||
class DummyImpl : CommonCompilerArguments()
|
||||
}
|
||||
|
||||
@@ -99,6 +99,10 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
|
||||
|
||||
// Advanced options
|
||||
|
||||
@GradleOption(DefaultValues.BooleanTrueDefault::class)
|
||||
@Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays")
|
||||
var typedArrays: Boolean by FreezableVar(true)
|
||||
|
||||
@GradleOption(DefaultValues.BooleanFalseDefault::class)
|
||||
@Argument(value = "-Xfriend-modules-disabled", description = "Disable internal declaration export")
|
||||
var friendModulesDisabled: Boolean by FreezableVar(false)
|
||||
|
||||
@@ -20,6 +20,7 @@ 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
|
||||
|
||||
class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
companion object {
|
||||
@@ -137,6 +138,9 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
@Argument(value = "-Xmultifile-parts-inherit", description = "Compile multifile classes as a hierarchy of parts and facade")
|
||||
var inheritMultifileParts: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(value = "-Xuse-type-table", description = "Use type table in metadata serialization")
|
||||
var useTypeTable: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xskip-runtime-version-check",
|
||||
description = "Allow Kotlin runtime libraries of incompatible versions in the classpath"
|
||||
@@ -224,6 +228,9 @@ 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)
|
||||
|
||||
// Paths to output directories for friend modules.
|
||||
var friendPaths: Array<String>? by FreezableVar(null)
|
||||
|
||||
@@ -233,6 +240,15 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
jsr305,
|
||||
supportCompatqualCheckerFrameworkAnnotations
|
||||
)
|
||||
result[AnalysisFlag.enableJvmDefault] = enableJvmDefault
|
||||
return result
|
||||
}
|
||||
|
||||
override fun configureLanguageFeatures(collector: MessageCollector): MutableMap<LanguageFeature, LanguageFeature.State> {
|
||||
val result = super.configureLanguageFeatures(collector)
|
||||
if (strictJavaNullabilityAssertions) {
|
||||
result[LanguageFeature.StrictJavaNullabilityAssertions] = LanguageFeature.State.ENABLED
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -162,89 +161,10 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
|
||||
}
|
||||
|
||||
private void setupLanguageVersionSettings(@NotNull CompilerConfiguration configuration, @NotNull A arguments) {
|
||||
LanguageVersion languageVersion = parseVersion(configuration, arguments.getLanguageVersion(), "language");
|
||||
LanguageVersion apiVersion = parseVersion(configuration, arguments.getApiVersion(), "API");
|
||||
|
||||
if (languageVersion != null || apiVersion != null) {
|
||||
configuration.put(CLIConfigurationKeys.IS_API_VERSION_EXPLICIT, true);
|
||||
}
|
||||
|
||||
if (languageVersion == null) {
|
||||
// If no "-language-version" is specified, language version is assumed to be the latest stable
|
||||
languageVersion = LanguageVersion.LATEST_STABLE;
|
||||
}
|
||||
|
||||
if (apiVersion == null) {
|
||||
// If no "-api-version" is specified, API version is assumed to be equal to the language version
|
||||
// (API version cannot be greater than the language version)
|
||||
apiVersion = languageVersion;
|
||||
}
|
||||
|
||||
MessageCollector collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
|
||||
if (apiVersion.compareTo(languageVersion) > 0) {
|
||||
collector.report(
|
||||
ERROR,
|
||||
"-api-version (" + apiVersion.getVersionString() + ") cannot be greater than " +
|
||||
"-language-version (" + languageVersion.getVersionString() + ")",
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
if (!languageVersion.isStable()) {
|
||||
collector.report(
|
||||
STRONG_WARNING,
|
||||
"Language version " + languageVersion.getVersionString() + " is experimental, there are " +
|
||||
"no backwards compatibility guarantees for new language and library features",
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
Map<LanguageFeature, LanguageFeature.State> extraLanguageFeatures = new HashMap<>(0);
|
||||
if (arguments.getMultiPlatform()) {
|
||||
extraLanguageFeatures.put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED);
|
||||
}
|
||||
|
||||
LanguageFeature.State coroutinesState = chooseCoroutinesApplicabilityLevel(configuration, arguments);
|
||||
if (coroutinesState != null) {
|
||||
extraLanguageFeatures.put(LanguageFeature.Coroutines, coroutinesState);
|
||||
}
|
||||
|
||||
if (arguments.getNewInference()) {
|
||||
extraLanguageFeatures.put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED);
|
||||
}
|
||||
|
||||
if (arguments.getLegacySmartCastAfterTry()) {
|
||||
extraLanguageFeatures.put(LanguageFeature.SoundSmartCastsAfterTry, LanguageFeature.State.DISABLED);
|
||||
}
|
||||
|
||||
if (arguments.getEffectSystem()) {
|
||||
extraLanguageFeatures.put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED);
|
||||
extraLanguageFeatures.put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED);
|
||||
}
|
||||
|
||||
if (arguments.getReadDeserializedContracts()) {
|
||||
extraLanguageFeatures.put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED);
|
||||
}
|
||||
|
||||
if (arguments.getProperIeee754Comparisons()) {
|
||||
extraLanguageFeatures.put(LanguageFeature.ProperIeee754Comparisons, LanguageFeature.State.ENABLED);
|
||||
}
|
||||
|
||||
setupPlatformSpecificLanguageFeatureSettings(extraLanguageFeatures, arguments);
|
||||
|
||||
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new LanguageVersionSettingsImpl(
|
||||
languageVersion,
|
||||
ApiVersion.createByLanguageVersion(apiVersion),
|
||||
arguments.configureAnalysisFlags(collector),
|
||||
extraLanguageFeatures
|
||||
));
|
||||
}
|
||||
|
||||
protected void setupPlatformSpecificLanguageFeatureSettings(
|
||||
@NotNull Map<LanguageFeature, LanguageFeature.State> extraLanguageFeatures,
|
||||
@NotNull A commandLineArguments
|
||||
) {
|
||||
// do nothing
|
||||
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, arguments.configureLanguageVersionSettings(collector));
|
||||
}
|
||||
|
||||
private static final String kotlinHomeEnvVar = System.getenv(KOTLIN_HOME_ENV_VAR);
|
||||
@@ -299,43 +219,6 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LanguageFeature.State chooseCoroutinesApplicabilityLevel(
|
||||
@NotNull CompilerConfiguration configuration,
|
||||
@NotNull CommonCompilerArguments arguments
|
||||
) {
|
||||
switch (arguments.getCoroutinesState()) {
|
||||
case CommonCompilerArguments.ERROR:
|
||||
return LanguageFeature.State.ENABLED_WITH_ERROR;
|
||||
case CommonCompilerArguments.ENABLE:
|
||||
return LanguageFeature.State.ENABLED;
|
||||
case CommonCompilerArguments.WARN:
|
||||
return null;
|
||||
default:
|
||||
String message = "Invalid value of -Xcoroutines (should be: enable, warn or error): " + arguments.getCoroutinesState();
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(ERROR, message, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LanguageVersion parseVersion(
|
||||
@NotNull CompilerConfiguration configuration, @Nullable String value, @NotNull String versionOf
|
||||
) {
|
||||
if (value == null) return null;
|
||||
|
||||
LanguageVersion version = LanguageVersion.fromVersionString(value);
|
||||
if (version != null) {
|
||||
return version;
|
||||
}
|
||||
|
||||
List<String> versionStrings = ArraysKt.map(LanguageVersion.values(), LanguageVersion::getDescription);
|
||||
String message = "Unknown " + versionOf + " version: " + value + "\n" +
|
||||
"Supported " + versionOf + " versions: " + StringsKt.join(versionStrings, ", ");
|
||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(ERROR, message, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void setupPlatformSpecificArgumentsAndServices(
|
||||
@NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services
|
||||
);
|
||||
|
||||
@@ -29,8 +29,6 @@ public class CLIConfigurationKeys {
|
||||
CompilerConfigurationKey.create("allow kotlin package");
|
||||
public static final CompilerConfigurationKey<Boolean> REPORT_PERF =
|
||||
CompilerConfigurationKey.create("report performance information");
|
||||
public static final CompilerConfigurationKey<Boolean> IS_API_VERSION_EXPLICIT =
|
||||
CompilerConfigurationKey.create("is API version explicit");
|
||||
|
||||
// Used in Eclipse plugin (see KotlinCLICompiler)
|
||||
public static final CompilerConfigurationKey<String> INTELLIJ_PLUGIN_ROOT =
|
||||
|
||||
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import java.io.PrintStream
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
import java.util.function.Predicate
|
||||
|
||||
abstract class CLITool<A : CommonToolArguments> {
|
||||
@@ -79,6 +81,8 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
}
|
||||
|
||||
fun exec(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode {
|
||||
disableURLConnectionCaches()
|
||||
|
||||
printVersionIfNeeded(messageCollector, arguments)
|
||||
|
||||
val fixedMessageCollector = if (arguments.suppressWarnings && !arguments.allWarningsAsErrors) {
|
||||
@@ -92,6 +96,16 @@ abstract class CLITool<A : CommonToolArguments> {
|
||||
return execImpl(fixedMessageCollector, services, arguments)
|
||||
}
|
||||
|
||||
private fun disableURLConnectionCaches() {
|
||||
// We disable caches to avoid problems with compiler under daemon, see https://youtrack.jetbrains.com/issue/KT-22513
|
||||
// For some inexplicable reason, URLConnection.setDefaultUseCaches is an instance method modifying a static field,
|
||||
// so we have to create a dummy instance to call that method
|
||||
|
||||
object : URLConnection(URL("file:.")) {
|
||||
override fun connect() = throw UnsupportedOperationException()
|
||||
}.defaultUseCaches = false
|
||||
}
|
||||
|
||||
// Used in kotlin-maven-plugin (KotlinCompileMojoBase)
|
||||
protected abstract fun execImpl(messageCollector: MessageCollector, services: Services, arguments: A): ExitCode
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.script.ScriptContentLoader
|
||||
import org.jetbrains.kotlin.script.ScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||
import org.jetbrains.kotlin.script.adjustByDefinition
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
@@ -48,7 +49,9 @@ class CliScriptDependenciesProvider(
|
||||
else {
|
||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file)
|
||||
if (scriptDef != null) {
|
||||
val deps = scriptContentLoader.loadContentsAndResolveDependencies(scriptDef, file)
|
||||
val deps = scriptContentLoader
|
||||
.loadContentsAndResolveDependencies(scriptDef, file)
|
||||
.dependencies?.adjustByDefinition(scriptDef)
|
||||
|
||||
if (deps != null) {
|
||||
log.info("[kts] new cached deps for $path: ${deps.classpath.joinToString(File.pathSeparator)}")
|
||||
|
||||
@@ -37,6 +37,7 @@ class CliScriptReportSink(private val messageCollector: MessageCollector) : Scri
|
||||
}
|
||||
|
||||
private fun ScriptReport.Severity.convertSeverity(): CompilerMessageSeverity = when(this) {
|
||||
ScriptReport.Severity.FATAL -> CompilerMessageSeverity.ERROR
|
||||
ScriptReport.Severity.ERROR -> CompilerMessageSeverity.ERROR
|
||||
ScriptReport.Severity.WARNING -> CompilerMessageSeverity.WARNING
|
||||
ScriptReport.Severity.INFO -> CompilerMessageSeverity.INFO
|
||||
|
||||
@@ -65,10 +65,7 @@ import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver;
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||
import org.jetbrains.kotlin.utils.PathUtil;
|
||||
import org.jetbrains.kotlin.utils.StringsKt;
|
||||
import org.jetbrains.kotlin.utils.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -388,6 +385,8 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
configuration.put(JSConfigurationKeys.META_INFO, true);
|
||||
}
|
||||
|
||||
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, arguments.getTypedArrays());
|
||||
|
||||
configuration.put(JSConfigurationKeys.FRIEND_PATHS_DISABLED, arguments.getFriendModulesDisabled());
|
||||
|
||||
if (!arguments.getFriendModulesDisabled() && arguments.getFriendModules() != null) {
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.cli.jvm
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
@@ -47,6 +46,8 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN = "manifest.impl.value.kotlin.runtime.component.main"
|
||||
|
||||
private const val KOTLIN_STDLIB_MODULE = "$META_INF/kotlin-stdlib.kotlin_module"
|
||||
private const val KOTLIN_STDLIB_JRE_7_MODULE = "$META_INF/kotlin-stdlib-jre7.kotlin_module"
|
||||
private const val KOTLIN_STDLIB_JRE_8_MODULE = "$META_INF/kotlin-stdlib-jre8.kotlin_module"
|
||||
private const val KOTLIN_REFLECT_MODULE = "$META_INF/kotlin-reflection.kotlin_module"
|
||||
|
||||
private val RUNTIME_IMPLEMENTATION_TITLES = setOf(
|
||||
@@ -90,7 +91,9 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
// Runtime jars with components "Core" only (a subset of [jars])
|
||||
val coreJars: List<KotlinLibraryFile>,
|
||||
// Library jars which have some Kotlin Runtime library bundled into them
|
||||
val otherLibrariesWithBundledRuntime: List<VirtualFile>
|
||||
val otherLibrariesWithBundledRuntime: List<VirtualFile>,
|
||||
val stdlibJre7: List<KotlinLibraryFile>,
|
||||
val stdlibJre8: List<KotlinLibraryFile>
|
||||
)
|
||||
|
||||
fun checkCompilerClasspathConsistency(
|
||||
@@ -129,7 +132,7 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
val actualApi = ApiVersion.parse(actualRuntimeVersion.toString())
|
||||
if (actualApi == null) {
|
||||
messageCollector.issue(null, "Could not parse runtime JAR version: $actualRuntimeVersion")
|
||||
} else if (!configuration.getBoolean(CLIConfigurationKeys.IS_API_VERSION_EXPLICIT) && actualApi < currentApi) {
|
||||
} else if (!languageVersionSettings.getFlag(AnalysisFlag.explicitApiVersion) && actualApi < currentApi) {
|
||||
// If there's no explicit "-api-version" AND there's an old stdlib in the classpath (older than the default value of API),
|
||||
// we infer API = the version of that stdlib.
|
||||
// Note that "no explicit -api-version" requirement is necessary because for example, in
|
||||
@@ -152,6 +155,15 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
)
|
||||
}
|
||||
|
||||
if (configuration.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_2) {
|
||||
for (stdlibJre7 in runtimeJarsInfo.stdlibJre7) {
|
||||
messageCollector.issue(stdlibJre7.file, "kotlin-stdlib-jre7 is deprecated. Please use kotlin-stdlib-jdk7 instead")
|
||||
}
|
||||
for (stdlibJre8 in runtimeJarsInfo.stdlibJre8) {
|
||||
messageCollector.issue(stdlibJre8.file, "kotlin-stdlib-jre8 is deprecated. Please use kotlin-stdlib-jdk8 instead")
|
||||
}
|
||||
}
|
||||
|
||||
val librariesWithBundled = runtimeJarsInfo.otherLibrariesWithBundledRuntime
|
||||
if (librariesWithBundled.isNotEmpty()) {
|
||||
messageCollector.issue(
|
||||
@@ -264,6 +276,8 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
val jars = ArrayList<KotlinLibraryFile>(2)
|
||||
val coreJars = ArrayList<KotlinLibraryFile>(2)
|
||||
val otherLibrariesWithBundledRuntime = ArrayList<VirtualFile>(0)
|
||||
val stdlibJre7 = ArrayList<KotlinLibraryFile>(0)
|
||||
val stdlibJre8 = ArrayList<KotlinLibraryFile>(0)
|
||||
|
||||
val visitedPaths = hashSetOf<String>()
|
||||
|
||||
@@ -281,17 +295,28 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
if (fileKind.isCoreComponent) {
|
||||
coreJars.add(file)
|
||||
}
|
||||
if (fileKind.isStdlibJre7) {
|
||||
stdlibJre7.add(file)
|
||||
}
|
||||
if (fileKind.isStdlibJre8) {
|
||||
stdlibJre8.add(file)
|
||||
}
|
||||
}
|
||||
FileKind.OldRuntime -> jars.add(KotlinLibraryFile(jarFile, ApiVersion.KOTLIN_1_0.version))
|
||||
FileKind.LibraryWithBundledRuntime -> otherLibrariesWithBundledRuntime.add(jarFile)
|
||||
}
|
||||
}
|
||||
|
||||
return RuntimeJarsInfo(jars, coreJars, otherLibrariesWithBundledRuntime)
|
||||
return RuntimeJarsInfo(jars, coreJars, otherLibrariesWithBundledRuntime, stdlibJre7, stdlibJre8)
|
||||
}
|
||||
|
||||
private sealed class FileKind {
|
||||
class Runtime(val version: MavenComparableVersion, val isCoreComponent: Boolean) : FileKind()
|
||||
class Runtime(
|
||||
val version: MavenComparableVersion,
|
||||
val isStdlibJre7: Boolean,
|
||||
val isStdlibJre8: Boolean,
|
||||
val isCoreComponent: Boolean
|
||||
) : FileKind()
|
||||
|
||||
// Runtime library of Kotlin 1.0
|
||||
object OldRuntime : FileKind()
|
||||
@@ -311,11 +336,13 @@ object JvmRuntimeVersionsConsistencyChecker {
|
||||
}
|
||||
|
||||
val runtimeComponent = manifest?.mainAttributes?.getValue(KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE)
|
||||
val isStdlibJre7 = jarRoot.findFileByRelativePath(KOTLIN_STDLIB_JRE_7_MODULE) != null
|
||||
val isStdlibJre8 = jarRoot.findFileByRelativePath(KOTLIN_STDLIB_JRE_8_MODULE) != null
|
||||
return when (runtimeComponent) {
|
||||
KOTLIN_RUNTIME_COMPONENT_MAIN ->
|
||||
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isCoreComponent = false)
|
||||
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = false)
|
||||
KOTLIN_RUNTIME_COMPONENT_CORE ->
|
||||
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isCoreComponent = true)
|
||||
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = true)
|
||||
null -> when {
|
||||
jarRoot.findFileByRelativePath(KOTLIN_STDLIB_MODULE) == null &&
|
||||
jarRoot.findFileByRelativePath(KOTLIN_REFLECT_MODULE) == null -> FileKind.Irrelevant
|
||||
|
||||
@@ -227,17 +227,6 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun setupPlatformSpecificLanguageFeatureSettings(
|
||||
extraLanguageFeatures: MutableMap<LanguageFeature, LanguageFeature.State>,
|
||||
commandLineArguments: K2JVMCompilerArguments
|
||||
) {
|
||||
if (commandLineArguments.strictJavaNullabilityAssertions) {
|
||||
extraLanguageFeatures[LanguageFeature.StrictJavaNullabilityAssertions] = LanguageFeature.State.ENABLED
|
||||
}
|
||||
|
||||
super.setupPlatformSpecificLanguageFeatureSettings(extraLanguageFeatures, commandLineArguments)
|
||||
}
|
||||
|
||||
private fun registerJavacIfNeeded(
|
||||
environment: KotlinCoreEnvironment,
|
||||
arguments: K2JVMCompilerArguments
|
||||
@@ -388,6 +377,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
)
|
||||
|
||||
configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, arguments.inheritMultifileParts)
|
||||
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable)
|
||||
configuration.put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
|
||||
configuration.put(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING, !arguments.useOldClassFilesReading)
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ class ClasspathRootsResolver(
|
||||
}
|
||||
}
|
||||
|
||||
if (requireStdlibModule && sourceModule != null && KOTLIN_STDLIB_MODULE_NAME !in allDependencies) {
|
||||
if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) {
|
||||
report(
|
||||
ERROR,
|
||||
"The Kotlin standard library is not found in the module graph. " +
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.cli.jvm.repl.reader
|
||||
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.writer.END_LINE
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.writer.ReplWriter
|
||||
import org.w3c.dom.Element
|
||||
import org.xml.sax.InputSource
|
||||
@@ -78,12 +77,10 @@ class ReplSystemInWrapper(
|
||||
val xmlInput = byteBuilder.toString()
|
||||
val unescapedXml = parseXml(xmlInput)
|
||||
|
||||
val resultLine = if (isReplScriptExecuting)
|
||||
return if (isReplScriptExecuting)
|
||||
unescapeLineBreaks(unescapedXml)
|
||||
else
|
||||
unescapedXml
|
||||
|
||||
return "$resultLine$END_LINE"
|
||||
}
|
||||
|
||||
private fun resetBufferIfNeeded() {
|
||||
|
||||
@@ -62,7 +62,11 @@ class IncrementalCompilationOptions(
|
||||
requestedCompilationResults: Array<Int>,
|
||||
val resultDifferenceFile: File? = null,
|
||||
val friendDifferenceFile: File? = null,
|
||||
val usePreciseJavaTracking: Boolean
|
||||
val usePreciseJavaTracking: Boolean,
|
||||
/**
|
||||
* Directories that should be cleared when IC decides to rebuild
|
||||
*/
|
||||
val localStateDirs: List<File>
|
||||
) : CompilationOptions(compilerMode, targetPlatform, reportCategories, reportSeverity, requestedCompilationResults) {
|
||||
companion object {
|
||||
const val serialVersionUID: Long = 0
|
||||
@@ -80,6 +84,7 @@ class IncrementalCompilationOptions(
|
||||
"resultDifferenceFile=$resultDifferenceFile, " +
|
||||
"friendDifferenceFile=$friendDifferenceFile, " +
|
||||
"usePreciseJavaTracking=$usePreciseJavaTracking" +
|
||||
"localStateDirs=$localStateDirs" +
|
||||
")"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,12 @@ interface CompileService : Remote {
|
||||
compilationResults: CompilationResults?
|
||||
): CallResult<Int>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun classesFqNamesByFiles(
|
||||
sessionId: Int,
|
||||
sourceFiles: Set<File>
|
||||
): CallResult<Set<String>>
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
fun clearJarCache()
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapte
|
||||
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.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
@@ -352,6 +353,15 @@ class CompileServiceImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun classesFqNamesByFiles(
|
||||
sessionId: Int, sourceFiles: Set<File>
|
||||
): CompileService.CallResult<Set<String>> =
|
||||
ifAlive {
|
||||
withValidClientOrSessionProxy(sessionId) {
|
||||
CompileService.CallResult.Good(classesFqNames(sourceFiles))
|
||||
}
|
||||
}
|
||||
|
||||
override fun compile(
|
||||
sessionId: Int,
|
||||
compilerArguments: Array<out String>,
|
||||
@@ -522,7 +532,8 @@ class CompileServiceImpl(
|
||||
artifactChanges, changesRegistry,
|
||||
buildHistoryFile = incrementalCompilationOptions.resultDifferenceFile,
|
||||
friendBuildHistoryFile = incrementalCompilationOptions.friendDifferenceFile,
|
||||
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking
|
||||
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking,
|
||||
localStateDirs = incrementalCompilationOptions.localStateDirs
|
||||
)
|
||||
return compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles)
|
||||
}
|
||||
|
||||
@@ -97,12 +97,6 @@ public class JVMConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<Boolean> PARAMETERS_METADATA =
|
||||
CompilerConfigurationKey.create("Parameters metadata for java 1.8 reflection");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> INTERFACE_COMPATIBILITY =
|
||||
CompilerConfigurationKey.create("Generate additional 'DefaultImpls' class files for jvm 8 target for compatibility with 6 target interfaces");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> JVM8_TARGET_WITH_DEFAULTS =
|
||||
CompilerConfigurationKey.create("Generate default methods in interfaces");
|
||||
|
||||
public static final CompilerConfigurationKey<IncrementalCompilationComponents> INCREMENTAL_COMPILATION_COMPONENTS =
|
||||
CompilerConfigurationKey.create("incremental cache provider");
|
||||
|
||||
@@ -135,4 +129,7 @@ public class JVMConfigurationKeys {
|
||||
|
||||
public static final CompilerConfigurationKey<List<String>> ADDITIONAL_JAVA_MODULES =
|
||||
CompilerConfigurationKey.create("additional Java modules");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_DEFAULT =
|
||||
CompilerConfigurationKey.create("Allow to use '@JvmDefault'");
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||
|
||||
object JvmDelegationFilter : DelegationFilter {
|
||||
@@ -33,7 +34,9 @@ object JvmDelegationFilter : DelegationFilter {
|
||||
|
||||
//We always have only one implementation otherwise it's an error in kotlin and java
|
||||
val realMember = DescriptorUtils.unwrapFakeOverride(interfaceMember)
|
||||
return !isJavaDefaultMethod(realMember) && !isBuiltInMemberMappedToJavaDefault(realMember)
|
||||
return !isJavaDefaultMethod(realMember) &&
|
||||
!realMember.hasJvmDefaultAnnotation() &&
|
||||
!isBuiltInMemberMappedToJavaDefault(realMember)
|
||||
}
|
||||
|
||||
private fun isJavaDefaultMethod(interfaceMember: CallableMemberDescriptor): Boolean {
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
|
||||
fun DeclarationDescriptor.findJvmOverloadsAnnotation() = annotations.findAnnotation(FqName("kotlin.jvm.JvmOverloads"))
|
||||
|
||||
@@ -26,4 +28,7 @@ fun DeclarationDescriptor.findJvmFieldAnnotation() = DescriptorUtils.getAnnotati
|
||||
|
||||
fun DeclarationDescriptor.hasJvmFieldAnnotation(): Boolean {
|
||||
return findJvmFieldAnnotation() != null
|
||||
}
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.isCallableMemberWithJvmDefaultAnnotation() =
|
||||
(this as? CallableMemberDescriptor)?.hasJvmDefaultAnnotation() ?: false
|
||||
|
||||
@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
@@ -36,7 +38,8 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val supportDefaults = jvmTarget == JvmTarget.JVM_1_8
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return
|
||||
val descriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
if (descriptor is JavaPropertyDescriptor) return
|
||||
|
||||
if (!supportDefaults &&
|
||||
isStaticDeclaration(descriptor) &&
|
||||
@@ -46,26 +49,64 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker
|
||||
context.trace.report(diagnostic.on(reportOn))
|
||||
}
|
||||
|
||||
if (getSuperCallExpression(resolvedCall.call) == null) return
|
||||
val superCallExpression = getSuperCallExpression(resolvedCall.call) ?: return
|
||||
|
||||
if (!isInterface(descriptor.original.containingDeclaration)) return
|
||||
|
||||
val realDescriptor = unwrapFakeOverride(descriptor)
|
||||
val realDescriptorOwner = realDescriptor.containingDeclaration as? ClassDescriptor ?: return
|
||||
|
||||
if (isInterface(realDescriptorOwner) && realDescriptor is JavaCallableMemberDescriptor) {
|
||||
val classifier = DescriptorUtils.getParentOfType(context.scope.ownerDescriptor, ClassifierDescriptor::class.java)
|
||||
//is java interface default method called from trait
|
||||
if (classifier != null && DescriptorUtils.isInterface(classifier)) {
|
||||
context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn))
|
||||
if (isInterface(realDescriptorOwner) && (realDescriptor is JavaCallableMemberDescriptor || realDescriptor.hasJvmDefaultAnnotation())) {
|
||||
val bindingContext = context.trace.bindingContext
|
||||
val thisForSuperCall = getSuperCallLabelTarget(bindingContext, superCallExpression)
|
||||
|
||||
if (thisForSuperCall != null && DescriptorUtils.isInterface(thisForSuperCall)) {
|
||||
val declarationWithCall = findInterfaceMember(thisForSuperCall, superCallExpression, bindingContext)
|
||||
if (declarationWithCall?.hasJvmDefaultAnnotation() == false) {
|
||||
context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn))
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (!supportDefaults) {
|
||||
val diagnostic = if (isDefaultCallsProhibited(context)) DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET_ERROR else DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET
|
||||
|
||||
if (!supportDefaults) {
|
||||
val diagnostic =
|
||||
if (isDefaultCallsProhibited(context)) DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET_ERROR else DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET
|
||||
context.trace.report(diagnostic.on(reportOn))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findInterfaceMember(
|
||||
descriptorToSearch: ClassDescriptor,
|
||||
startExpression: KtSuperExpression,
|
||||
bindingContext: BindingContext
|
||||
): CallableMemberDescriptor? {
|
||||
val parents = generateSequence({ startExpression.parent }) { it.parent }
|
||||
parents.fold<PsiElement, PsiElement>(startExpression) { child, parent ->
|
||||
if (parent is KtClassBody &&
|
||||
descriptorToSearch == bindingContext.get(BindingContext.CLASS, parent.parent)
|
||||
) {
|
||||
return when (child) {
|
||||
is KtNamedFunction -> bindingContext.get(BindingContext.FUNCTION, child)
|
||||
is KtProperty -> bindingContext.get(BindingContext.VARIABLE, child) as? PropertyDescriptor
|
||||
else -> null
|
||||
}
|
||||
} else parent
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isDefaultCallsProhibited(context: CallCheckerContext) =
|
||||
context.languageVersionSettings.supportsFeature(LanguageFeature.DefaultMethodsCallFromJava6TargetError)
|
||||
context.languageVersionSettings.supportsFeature(LanguageFeature.DefaultMethodsCallFromJava6TargetError)
|
||||
|
||||
private fun getSuperCallLabelTarget(
|
||||
bindingContext: BindingContext,
|
||||
expression: KtSuperExpression
|
||||
): ClassDescriptor? {
|
||||
val thisTypeForSuperCall = bindingContext.get(BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression) ?: return null
|
||||
val descriptor = thisTypeForSuperCall.constructor.declarationDescriptor
|
||||
return descriptor as? ClassDescriptor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.resolve.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.config.AnalysisFlag
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.annotations.JVM_DEFAULT_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
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)
|
||||
|
||||
descriptor.annotations.findAnnotation(JVM_DEFAULT_FQ_NAME)?.let { annotationDescriptor ->
|
||||
val reportOn = DescriptorToSourceUtils.getSourceFromAnnotation(annotationDescriptor) ?: declaration
|
||||
if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) {
|
||||
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) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_DECLARATION.on(declaration))
|
||||
}
|
||||
return@check
|
||||
}
|
||||
|
||||
if (descriptor is ClassDescriptor) {
|
||||
val hasDeclaredJvmDefaults =
|
||||
descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>().any {
|
||||
it.kind.isReal && it.hasJvmDefaultAnnotation()
|
||||
}
|
||||
if (!hasDeclaredJvmDefaults && !checkJvmDefaultsInHierarchy(descriptor, enableJvmDefault)) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_THROUGH_INHERITANCE.on(declaration))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) return
|
||||
val memberDescriptor = descriptor as? CallableMemberDescriptor ?: return
|
||||
if (descriptor is PropertyAccessorDescriptor) return
|
||||
|
||||
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) {
|
||||
descriptor.overriddenDescriptors.flatMap { OverridingUtil.getOverriddenDeclarations(it) }.toSet().let {
|
||||
for (realDescriptor in OverridingUtil.filterOutOverridden(it)) {
|
||||
if (realDescriptor is JavaMethodDescriptor && realDescriptor.modality != Modality.ABSTRACT) {
|
||||
return context.trace.report(ErrorsJvm.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT.on(declaration))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkJvmDefaultsInHierarchy(descriptor: DeclarationDescriptor, enableJvmDefault: Boolean): Boolean {
|
||||
if (enableJvmDefault) return true
|
||||
|
||||
if (descriptor !is ClassDescriptor) return true
|
||||
|
||||
return descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>()
|
||||
.all { memberDescriptor ->
|
||||
memberDescriptor.kind.isReal || OverridingUtil.filterOutOverridden(memberDescriptor.overriddenDescriptors.toSet()).all {
|
||||
!isInterface(it.containingDeclaration) || !it.hasJvmDefaultAnnotation() || it.modality == Modality.ABSTRACT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(NO_REFLECTION_IN_CLASS_PATH, "Call uses reflection API which is not found in compilation classpath. " +
|
||||
"Make sure you have kotlin-reflect.jar in the classpath");
|
||||
|
||||
MAP.put(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER, "Interfaces can't call Java default methods via super");
|
||||
MAP.put(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER, "Interfaces can call default methods via super only within @JvmDefault members. Please annotate the containing interface member with @JvmDefault");
|
||||
MAP.put(SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC, "Using non-JVM static members protected in the superclass companion is unsupported yet");
|
||||
|
||||
MAP.put(ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS,
|
||||
@@ -133,6 +133,14 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
|
||||
MAP.put(ASSIGNMENT_TO_ARRAY_LOOP_VARIABLE, "Assignment to a for-in-array loop range variable. Behavior may change in Kotlin 1.3. " +
|
||||
"See https://youtrack.jetbrains.com/issue/KT-21354 for more details");
|
||||
|
||||
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(NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, "Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -114,6 +114,15 @@ public interface ErrorsJvm {
|
||||
|
||||
DiagnosticFactory0<KtExpression> ASSIGNMENT_TO_ARRAY_LOOP_VARIABLE = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<PsiElement> JVM_DEFAULT_NOT_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> JVM_DEFAULT_IN_JVM6_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_REQUIRED_FOR_OVERRIDE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_IN_DECLARATION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_THROUGH_INHERITANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<PsiElement> USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtDeclaration> NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
|
||||
enum NullabilityInformationSource {
|
||||
KOTLIN {
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.jvm.platform
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.AnalysisFlag
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
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 superExpression = getSuperCallExpression(resolvedCall.call) ?: return
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
if (!resultingDescriptor.hasJvmDefaultAnnotation()) return
|
||||
|
||||
if (DescriptorUtils.isInterface(resultingDescriptor.containingDeclaration)) {
|
||||
context.trace.report(ErrorsJvm.USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL.on(reportOn))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,9 +91,11 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
container.useImpl<JavaSyntheticScopes>()
|
||||
container.useImpl<SamConversionResolverImpl>()
|
||||
container.useImpl<InterfaceDefaultMethodCallChecker>()
|
||||
container.useImpl<JvmDefaultChecker>()
|
||||
container.useImpl<InlinePlatformCompatibilityChecker>()
|
||||
container.useImpl<JvmModuleAccessibilityChecker>()
|
||||
container.useImpl<JvmModuleAccessibilityChecker.ClassifierUsage>()
|
||||
container.useInstance(JvmTypeSpecificityComparator)
|
||||
container.useImpl<JvmDefaultSuperCallChecker>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,21 +28,22 @@ import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.full.memberFunctions
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
import kotlin.script.dependencies.ScriptDependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||
import kotlin.script.templates.AcceptedAnnotations
|
||||
import kotlin.script.templates.*
|
||||
|
||||
open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
template: KClass<out Any>,
|
||||
val environment: Map<String, Any?>? = null,
|
||||
val templateClasspath: List<File> = emptyList()
|
||||
) : KotlinScriptDefinition(template) {
|
||||
|
||||
val scriptFilePattern by lazy {
|
||||
val pattern =
|
||||
takeUnlessError {
|
||||
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()?.scriptFilePattern
|
||||
val ann = template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>()
|
||||
ann?.scriptFilePattern
|
||||
}
|
||||
?: takeUnlessError { template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>()?.scriptFilePattern }
|
||||
?: DEFAULT_SCRIPT_FILE_PATTERN
|
||||
@@ -144,6 +145,15 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
|
||||
override val annotationsForSamWithReceivers: List<String>
|
||||
get() = samWithReceiverAnnotations ?: super.annotationsForSamWithReceivers
|
||||
|
||||
override val additionalCompilerArguments: Iterable<String>? by lazy {
|
||||
takeUnlessError {
|
||||
template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateAdditionalCompilerArguments>()?.let {
|
||||
val res = it.provider.primaryConstructor?.call(it.arguments.asIterable())
|
||||
res
|
||||
}
|
||||
}?.getAdditionalCompilerArguments(environment)
|
||||
}
|
||||
|
||||
private inline fun<T> takeUnlessError(reportError: Boolean = true, body: () -> T?): T? =
|
||||
try {
|
||||
body()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.script
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
@@ -25,8 +26,9 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.io.File
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult.Failure
|
||||
import kotlin.script.dependencies.ScriptContents
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult.Failure
|
||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||
import kotlin.script.experimental.dependencies.ScriptReport
|
||||
|
||||
@@ -37,13 +39,15 @@ class ScriptContentLoader(private val project: Project) {
|
||||
private fun loadAnnotations(scriptDefinition: KotlinScriptDefinition, file: VirtualFile): List<Annotation> {
|
||||
val classLoader = scriptDefinition.template.java.classLoader
|
||||
// TODO_R: report error on failure to load annotation class
|
||||
return getAnnotationEntries(file, project)
|
||||
return ApplicationManager.getApplication().runReadAction<List<Annotation>> {
|
||||
getAnnotationEntries(file, project)
|
||||
.mapNotNull { psiAnn ->
|
||||
// TODO: consider advanced matching using semantic similar to actual resolving
|
||||
scriptDefinition.acceptedAnnotations.find { ann ->
|
||||
psiAnn.typeName.let { it == ann.simpleName || it == ann.qualifiedName }
|
||||
}?.let { constructAnnotation(psiAnn, classLoader.loadClass(it.qualifiedName).kotlin as KClass<out Annotation>) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAnnotationEntries(file: VirtualFile, project: Project): Iterable<KtAnnotationEntry> {
|
||||
@@ -62,7 +66,7 @@ class ScriptContentLoader(private val project: Project) {
|
||||
fun loadContentsAndResolveDependencies(
|
||||
scriptDef: KotlinScriptDefinition,
|
||||
file: VirtualFile
|
||||
): ScriptDependencies? {
|
||||
): DependenciesResolver.ResolveResult {
|
||||
val scriptContents = getScriptContents(scriptDef, file)
|
||||
val environment = getEnvironment(scriptDef)
|
||||
val result = try {
|
||||
@@ -75,7 +79,7 @@ class ScriptContentLoader(private val project: Project) {
|
||||
e.asResolveFailure(scriptDef)
|
||||
}
|
||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
||||
return result.dependencies?.adjustByDefinition(scriptDef)
|
||||
return result
|
||||
}
|
||||
|
||||
fun getEnvironment(scriptDef: KotlinScriptDefinition) =
|
||||
@@ -92,5 +96,5 @@ fun ScriptDependencies.adjustByDefinition(
|
||||
|
||||
fun Throwable.asResolveFailure(scriptDef: KotlinScriptDefinition): Failure {
|
||||
val prefix = "${scriptDef.dependencyResolver::class.simpleName} threw exception ${this::class.simpleName}:\n "
|
||||
return Failure(ScriptReport(prefix + (message ?: "<no message>")))
|
||||
return Failure(ScriptReport(prefix + (message ?: "<no message>"), ScriptReport.Severity.FATAL))
|
||||
}
|
||||
@@ -218,12 +218,13 @@ public interface Errors {
|
||||
DiagnosticFactory0<PsiElement> ANNOTATION_CLASS_MEMBER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> INVALID_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> NULLABLE_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotatedExpression> ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> ANNOTATION_USED_AS_ANNOTATION_ARGUMENT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ANNOTATION_ARGUMENT_IS_NON_CONST = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory1<PsiElement, FqName> ILLEGAL_KOTLIN_VERSION_STRING_VALUE = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);
|
||||
|
||||
@@ -818,9 +818,9 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ANNOTATION_CLASS_MEMBER, "Members are not allowed in annotation class");
|
||||
MAP.put(INVALID_TYPE_OF_ANNOTATION_MEMBER, "Invalid type of annotation member");
|
||||
MAP.put(NULLABLE_TYPE_OF_ANNOTATION_MEMBER, "An annotation parameter cannot be nullable");
|
||||
MAP.put(ANNOTATION_PARAMETER_MUST_BE_CONST, "An annotation parameter must be a compile-time constant");
|
||||
MAP.put(ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST, "An enum annotation parameter must be a enum constant");
|
||||
MAP.put(ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL, "An annotation parameter must be a class literal (T::class)");
|
||||
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_CONST, "An annotation argument must be a compile-time constant");
|
||||
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST, "An enum annotation argument must be a enum constant");
|
||||
MAP.put(ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL, "An annotation argument must be a class literal (T::class)");
|
||||
MAP.put(ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT, "Default value of annotation parameter must be a compile-time constant");
|
||||
|
||||
MAP.put(ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE,
|
||||
@@ -828,6 +828,7 @@ public class DefaultErrorMessages {
|
||||
"Use new line if whole block-level expression must be annotated or wrap annotated expression in parentheses");
|
||||
|
||||
MAP.put(ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, "An annotation can't be used as the annotations argument");
|
||||
MAP.put(ANNOTATION_ARGUMENT_IS_NON_CONST, "An annotation argument must be a compile-time constant");
|
||||
|
||||
MAP.put(CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, "Const 'val' are only allowed on top level or in objects");
|
||||
MAP.put(CONST_VAL_WITH_DELEGATE, "Const 'val' should not have a delegate");
|
||||
|
||||
@@ -40,5 +40,19 @@ interface DeclarationAttributeAltererExtension {
|
||||
isImplicitModality: Boolean
|
||||
): Modality? = null
|
||||
|
||||
@Deprecated(
|
||||
"Use refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, isImplicitModality)",
|
||||
ReplaceWith("refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, false)")
|
||||
)
|
||||
fun refineDeclarationModality(
|
||||
modifierListOwner: KtModifierListOwner,
|
||||
declaration: DeclarationDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor?,
|
||||
currentModality: Modality,
|
||||
bindingContext: BindingContext
|
||||
): Modality? {
|
||||
return refineDeclarationModality(modifierListOwner, declaration, containingDeclaration, currentModality, bindingContext, false)
|
||||
}
|
||||
|
||||
fun shouldConvertFirstSAMParameterToReceiver(function: FunctionDescriptor): Boolean = false
|
||||
}
|
||||
@@ -1,23 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -154,15 +142,11 @@ class AnnotationChecker(
|
||||
}
|
||||
}
|
||||
|
||||
fun checkWithUseSiteTargets(additionalTarget: KotlinTarget? = null, useDeprecatedTargets: Boolean = false): Boolean {
|
||||
fun checkWithUseSiteTargets(): Boolean {
|
||||
if (useSiteTarget == null) return false
|
||||
|
||||
val useSiteMapping = KotlinTarget.USE_SITE_MAPPING[useSiteTarget].let {
|
||||
if (useDeprecatedTargets && it == RECEIVER) KotlinTarget.VALUE_PARAMETER else it
|
||||
}
|
||||
|
||||
val allTargets = actualTargets.onlyWithUseSiteTarget + listOfNotNull(additionalTarget)
|
||||
return allTargets.any { it in applicableTargets && it == useSiteMapping }
|
||||
val useSiteMapping = KotlinTarget.USE_SITE_MAPPING[useSiteTarget]
|
||||
return actualTargets.onlyWithUseSiteTarget.any { it in applicableTargets && it == useSiteMapping }
|
||||
}
|
||||
|
||||
if (check(actualTargets.defaultTargets) || check(actualTargets.canBeSubstituted) || checkWithUseSiteTargets()) {
|
||||
@@ -170,14 +154,6 @@ class AnnotationChecker(
|
||||
return
|
||||
}
|
||||
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes)) {
|
||||
val isAnnotationOnType = TargetLists.T_TYPE_REFERENCE == actualTargets
|
||||
if (isAnnotationOnType && checkWithUseSiteTargets(KotlinTarget.VALUE_PARAMETER, true)) {
|
||||
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE.on(entry, useSiteTarget!!.renderName))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (useSiteTarget != null) {
|
||||
trace.report(
|
||||
Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(
|
||||
@@ -350,7 +326,7 @@ class AnnotationChecker(
|
||||
val T_OBJECT_LITERAL = targetList(OBJECT_LITERAL, CLASS, EXPRESSION)
|
||||
|
||||
val T_TYPE_REFERENCE = targetList(TYPE) {
|
||||
onlyWithUseSiteTarget(RECEIVER)
|
||||
onlyWithUseSiteTarget(VALUE_PARAMETER)
|
||||
}
|
||||
|
||||
val T_TYPE_PARAMETER = targetList(TYPE_PARAMETER)
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
@@ -26,14 +17,60 @@ import org.jetbrains.kotlin.psi.*
|
||||
|
||||
object AnnotationUseSiteTargetChecker {
|
||||
|
||||
fun check(annotated: KtAnnotated, descriptor: DeclarationDescriptor, trace: BindingTrace) {
|
||||
fun check(
|
||||
annotated: KtAnnotated,
|
||||
descriptor: DeclarationDescriptor,
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
trace.checkDeclaration(annotated, descriptor)
|
||||
|
||||
if (annotated is KtCallableDeclaration) {
|
||||
annotated.receiverTypeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = true) }
|
||||
annotated.typeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = false) }
|
||||
}
|
||||
|
||||
if (annotated is KtFunction) {
|
||||
for (parameter in annotated.valueParameters) {
|
||||
if (parameter.hasValOrVar()) continue
|
||||
val parameterDescriptor = trace.bindingContext[BindingContext.VALUE_PARAMETER, parameter] ?: continue
|
||||
|
||||
trace.checkDeclaration(parameter, parameterDescriptor)
|
||||
parameter.typeReference?.let { trace.checkTypeReference(it, languageVersionSettings, isReceiver = false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun BindingTrace.checkTypeReference(
|
||||
topLevelTypeReference: KtTypeReference,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
isReceiver: Boolean
|
||||
) {
|
||||
checkAsTopLevelTypeReference(topLevelTypeReference, languageVersionSettings, isReceiver)
|
||||
|
||||
topLevelTypeReference.acceptChildren(
|
||||
typeReferenceRecursiveVisitor { typeReference ->
|
||||
checkAsTopLevelTypeReference(typeReference, languageVersionSettings, isReceiver = false)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun BindingTrace.checkAsTopLevelTypeReference(
|
||||
topLevelTypeReference: KtTypeReference,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
isReceiver: Boolean
|
||||
) {
|
||||
for (annotationEntry in topLevelTypeReference.annotationEntries) {
|
||||
val target = annotationEntry.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue
|
||||
|
||||
if (target != AnnotationUseSiteTarget.RECEIVER || !isReceiver) {
|
||||
val diagnostic =
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes))
|
||||
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(annotationEntry, "undefined target", target.renderName)
|
||||
else
|
||||
WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE.on(annotationEntry, target.renderName)
|
||||
|
||||
reportDiagnosticOnce(diagnostic)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,8 +101,9 @@ object AnnotationUseSiteTargetChecker {
|
||||
}
|
||||
AnnotationUseSiteTarget.SETTER_PARAMETER -> checkIfMutableProperty(annotated, annotation)
|
||||
AnnotationUseSiteTarget.FILE -> reportDiagnosticOnce(INAPPLICABLE_FILE_TARGET.on(useSiteTarget))
|
||||
AnnotationUseSiteTarget.RECEIVER -> {
|
||||
}
|
||||
AnnotationUseSiteTarget.RECEIVER ->
|
||||
// annotation with use-site target `receiver` can be only on type reference, but not on declaration
|
||||
reportDiagnosticOnce(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(annotation, "declaration", target.renderName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -28,6 +29,12 @@ val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
|
||||
|
||||
val JVM_FIELD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmField")
|
||||
|
||||
val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault")
|
||||
|
||||
fun CallableMemberDescriptor.hasJvmDefaultAnnotation() =
|
||||
DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)
|
||||
|
||||
|
||||
fun DeclarationDescriptor.hasJvmStaticAnnotation(): Boolean {
|
||||
return annotations.findAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) != null
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.resolve;
|
||||
@@ -222,7 +211,7 @@ public class ModifiersChecker {
|
||||
}
|
||||
|
||||
private void checkModifierListCommon(@NotNull KtDeclaration modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
|
||||
AnnotationUseSiteTargetChecker.INSTANCE.check(modifierListOwner, descriptor, trace);
|
||||
AnnotationUseSiteTargetChecker.INSTANCE.check(modifierListOwner, descriptor, trace, languageVersionSettings);
|
||||
runDeclarationCheckers(modifierListOwner, descriptor);
|
||||
annotationChecker.check(modifierListOwner, trace, descriptor);
|
||||
ModifierCheckerCore.INSTANCE.check(modifierListOwner, trace, descriptor, languageVersionSettings);
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* 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.resolve.calls.callResolverUtil
|
||||
@@ -22,20 +11,19 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
|
||||
@@ -186,41 +174,65 @@ fun getSuperCallExpression(call: Call): KtSuperExpression? {
|
||||
|
||||
fun getEffectiveExpectedType(
|
||||
parameterDescriptor: ValueParameterDescriptor,
|
||||
argument: ValueArgument,
|
||||
context: ResolutionContext<*>
|
||||
resolvedArgument: ResolvedValueArgument,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
trace: BindingTrace
|
||||
): KotlinType {
|
||||
if (argument.getSpreadElement() != null || shouldCheckAsArray(parameterDescriptor, argument, context)) {
|
||||
if (parameterDescriptor.varargElementType == null) {
|
||||
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
|
||||
return DONT_CARE
|
||||
}
|
||||
return parameterDescriptor.type
|
||||
}
|
||||
val varargElementType = parameterDescriptor.varargElementType
|
||||
if (varargElementType != null) {
|
||||
return varargElementType
|
||||
}
|
||||
|
||||
return parameterDescriptor.type
|
||||
val argument = resolvedArgument.arguments.singleOrNull()
|
||||
return if (argument != null)
|
||||
getEffectiveExpectedTypeForSingleArgument(parameterDescriptor, argument, languageVersionSettings, trace)
|
||||
else
|
||||
getExpectedType(parameterDescriptor)
|
||||
}
|
||||
|
||||
private fun shouldCheckAsArray(
|
||||
fun getEffectiveExpectedType(
|
||||
parameterDescriptor: ValueParameterDescriptor,
|
||||
argument: ValueArgument,
|
||||
context: ResolutionContext<*>
|
||||
): KotlinType {
|
||||
return getEffectiveExpectedTypeForSingleArgument(parameterDescriptor, argument, context.languageVersionSettings, context.trace)
|
||||
}
|
||||
|
||||
fun getEffectiveExpectedTypeForSingleArgument(
|
||||
parameterDescriptor: ValueParameterDescriptor,
|
||||
argument: ValueArgument,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
trace: BindingTrace
|
||||
): KotlinType {
|
||||
if (argument.getSpreadElement() != null) {
|
||||
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
|
||||
return if (parameterDescriptor.varargElementType == null) DONT_CARE else parameterDescriptor.type
|
||||
}
|
||||
|
||||
if (arrayAssignmentToVarargInNamedFormInAnnotation(parameterDescriptor, argument, languageVersionSettings, trace)) {
|
||||
return parameterDescriptor.type
|
||||
}
|
||||
|
||||
return getExpectedType(parameterDescriptor)
|
||||
}
|
||||
|
||||
private fun getExpectedType(parameterDescriptor: ValueParameterDescriptor): KotlinType {
|
||||
return parameterDescriptor.varargElementType ?: parameterDescriptor.type
|
||||
}
|
||||
|
||||
private fun arrayAssignmentToVarargInNamedFormInAnnotation(
|
||||
parameterDescriptor: ValueParameterDescriptor,
|
||||
argument: ValueArgument,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
trace: BindingTrace
|
||||
): Boolean {
|
||||
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.AssigningArraysToVarargsInNamedFormInAnnotations)) return false
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.AssigningArraysToVarargsInNamedFormInAnnotations)) return false
|
||||
|
||||
if (!isParameterOfAnnotation(parameterDescriptor)) return false
|
||||
|
||||
return argument.isNamed() && parameterDescriptor.isVararg && isArrayOrArrayLiteral(argument, context)
|
||||
return argument.isNamed() && parameterDescriptor.isVararg && isArrayOrArrayLiteral(argument, trace)
|
||||
}
|
||||
|
||||
fun isArrayOrArrayLiteral(argument: ValueArgument, context: ResolutionContext<*>): Boolean {
|
||||
fun isArrayOrArrayLiteral(argument: ValueArgument, trace: BindingTrace): Boolean {
|
||||
val argumentExpression = argument.getArgumentExpression() ?: return false
|
||||
if (argumentExpression is KtCollectionLiteralExpression) return true
|
||||
|
||||
val type = context.trace.getType(argumentExpression) ?: return false
|
||||
val type = trace.getType(argumentExpression) ?: return false
|
||||
return KotlinBuiltIns.isArrayOrPrimitiveArray(type)
|
||||
}
|
||||
|
||||
@@ -276,15 +288,3 @@ fun createResolutionCandidatesForConstructors(
|
||||
ResolutionCandidate.create(call, it, dispatchReceiver, receiverKind, knownSubstitutor)
|
||||
}
|
||||
}
|
||||
|
||||
fun KtLambdaExpression.getCorrespondingParameterForFunctionArgument(
|
||||
bindingContext: BindingContext
|
||||
): ValueParameterDescriptor? {
|
||||
val resolvedCall = KtPsiUtil.getParentCallIfPresent(this)?.getResolvedCall(bindingContext) ?: return null
|
||||
val valueArgument =
|
||||
resolvedCall.call.getValueArgumentForExpression(this)
|
||||
?: return null
|
||||
val mapping = resolvedCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: return null
|
||||
|
||||
return mapping.valueParameter
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* 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.resolve.calls.checkers
|
||||
@@ -61,7 +50,7 @@ class AssigningNamedArgumentToVarargChecker : CallChecker {
|
||||
argumentExpression: KtExpression,
|
||||
context: ResolutionContext<*>
|
||||
) {
|
||||
if (isArrayOrArrayLiteral(argument, context)) {
|
||||
if (isArrayOrArrayLiteral(argument, context.trace)) {
|
||||
if (argument.hasSpread()) {
|
||||
context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION.on(argumentExpression))
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* 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.resolve.constants.evaluate
|
||||
@@ -33,6 +22,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.COLLECTION_LITERAL_CALL
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
@@ -97,8 +87,9 @@ class ConstantExpressionEvaluator(
|
||||
val varargElementType = parameterDescriptor.varargElementType
|
||||
val argumentsAsVararg = varargElementType != null && !hasSpread(resolvedArgument)
|
||||
val constantType = if (argumentsAsVararg) varargElementType else parameterDescriptor.type
|
||||
val compileTimeConstants = resolveAnnotationValueArguments(resolvedArgument, constantType!!, trace)
|
||||
val constants = compileTimeConstants.map { it.toConstantValue(constantType) }
|
||||
val expectedType = getEffectiveExpectedType(parameterDescriptor, resolvedArgument, languageVersionSettings, trace)
|
||||
val compileTimeConstants = resolveAnnotationValueArguments(resolvedArgument, constantType!!, expectedType, trace)
|
||||
val constants = compileTimeConstants.map { it.toConstantValue(expectedType) }
|
||||
|
||||
if (argumentsAsVararg) {
|
||||
if (isArrayPassedInNamedForm(constants, resolvedArgument)) return constants.single()
|
||||
@@ -120,72 +111,82 @@ class ConstantExpressionEvaluator(
|
||||
|
||||
private fun checkCompileTimeConstant(
|
||||
argumentExpression: KtExpression,
|
||||
expectedType: KotlinType,
|
||||
trace: BindingTrace
|
||||
expressionType: KotlinType,
|
||||
trace: BindingTrace,
|
||||
useDeprecationWarning: Boolean
|
||||
) {
|
||||
val expressionType = trace.getType(argumentExpression)
|
||||
|
||||
if (expressionType == null || !KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
|
||||
// TYPE_MISMATCH should be reported otherwise
|
||||
return
|
||||
}
|
||||
|
||||
// array(1, <!>null<!>, 3) - error should be reported on inner expression
|
||||
if (argumentExpression is KtCallExpression) {
|
||||
getArgumentExpressionsForArrayCall(argumentExpression, trace)?.let { checkArgumentsAreCompileTimeConstants(it, trace) }
|
||||
}
|
||||
if (argumentExpression is KtCollectionLiteralExpression) {
|
||||
getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)?.let {
|
||||
checkArgumentsAreCompileTimeConstants(
|
||||
it,
|
||||
trace
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext)
|
||||
if (constant != null && constant.canBeUsedInAnnotations) {
|
||||
if (constant.usesNonConstValAsConstant) {
|
||||
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
|
||||
}
|
||||
|
||||
if (argumentExpression is KtClassLiteralExpression) {
|
||||
val lhsExpression = argumentExpression.receiverExpression
|
||||
if (lhsExpression != null) {
|
||||
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
|
||||
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
|
||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkInnerPartsOfCompileTimeConstant(constant, trace, argumentExpression, useDeprecationWarning)
|
||||
return
|
||||
}
|
||||
|
||||
val descriptor = expressionType.constructor.declarationDescriptor
|
||||
if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) {
|
||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression))
|
||||
} else if (descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor)) {
|
||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||
} else {
|
||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression))
|
||||
val diagnosticFactory = when {
|
||||
DescriptorUtils.isEnumClass(descriptor) -> Errors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
|
||||
descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor) -> Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||
else -> Errors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||
}
|
||||
|
||||
if (useDeprecationWarning)
|
||||
reportDeprecationWarningOnNonConst(argumentExpression, trace)
|
||||
else
|
||||
trace.report(diagnosticFactory.on(argumentExpression))
|
||||
}
|
||||
|
||||
private fun checkInnerPartsOfCompileTimeConstant(
|
||||
constant: CompileTimeConstant<*>,
|
||||
trace: BindingTrace,
|
||||
argumentExpression: KtExpression,
|
||||
useDeprecationWarning: Boolean
|
||||
) {
|
||||
// array(1, <!>null<!>, 3) - error should be reported on inner expression
|
||||
val callArguments = when (argumentExpression) {
|
||||
is KtCallExpression -> getArgumentExpressionsForArrayCall(argumentExpression, trace)
|
||||
is KtCollectionLiteralExpression -> getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (callArguments != null) {
|
||||
for (argument in callArguments) {
|
||||
val type = trace.getType(argument) ?: continue
|
||||
checkCompileTimeConstant(argument, type, trace, useDeprecationWarning)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Consider removing this check, because we already checked inner expression
|
||||
if (constant.usesNonConstValAsConstant) {
|
||||
if (useDeprecationWarning) {
|
||||
reportDeprecationWarningOnNonConst(argumentExpression, trace)
|
||||
} else {
|
||||
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (argumentExpression is KtClassLiteralExpression) {
|
||||
val lhsExpression = argumentExpression.receiverExpression
|
||||
if (lhsExpression != null) {
|
||||
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
|
||||
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
|
||||
if (useDeprecationWarning) {
|
||||
reportDeprecationWarningOnNonConst(argumentExpression, trace)
|
||||
} else {
|
||||
trace.report(Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkArgumentsAreCompileTimeConstants(
|
||||
argumentsWithComponentType: Pair<List<KtExpression>, KotlinType?>,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
val (arguments, componentType) = argumentsWithComponentType
|
||||
for (expression in arguments) {
|
||||
checkCompileTimeConstant(expression, componentType!!, trace)
|
||||
}
|
||||
private fun reportDeprecationWarningOnNonConst(expression: KtExpression, trace: BindingTrace) {
|
||||
trace.report(Errors.ANNOTATION_ARGUMENT_IS_NON_CONST.on(expression))
|
||||
}
|
||||
|
||||
private fun getArgumentExpressionsForArrayCall(
|
||||
expression: KtCallExpression,
|
||||
trace: BindingTrace
|
||||
): Pair<List<KtExpression>, KotlinType?>? {
|
||||
): List<KtExpression>? {
|
||||
val resolvedCall = expression.getResolvedCall(trace.bindingContext) ?: return null
|
||||
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
||||
}
|
||||
@@ -193,19 +194,16 @@ class ConstantExpressionEvaluator(
|
||||
private fun getArgumentExpressionsForCollectionLiteralCall(
|
||||
expression: KtCollectionLiteralExpression,
|
||||
trace: BindingTrace
|
||||
): Pair<List<KtExpression>, KotlinType?>? {
|
||||
): List<KtExpression>? {
|
||||
val resolvedCall = trace[COLLECTION_LITERAL_CALL, expression] ?: return null
|
||||
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
||||
}
|
||||
|
||||
private fun getArgumentExpressionsForArrayLikeCall(resolvedCall: ResolvedCall<*>): Pair<List<KtExpression>, KotlinType>? {
|
||||
private fun getArgumentExpressionsForArrayLikeCall(resolvedCall: ResolvedCall<*>): List<KtExpression>? {
|
||||
if (!CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
|
||||
val componentType = module.builtIns.getArrayElementType(returnType)
|
||||
|
||||
val result = arrayListOf<KtExpression>()
|
||||
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
||||
for (valueArgument in resolvedValueArgument.arguments) {
|
||||
@@ -216,7 +214,7 @@ class ConstantExpressionEvaluator(
|
||||
}
|
||||
}
|
||||
|
||||
return Pair<List<KtExpression>, KotlinType>(result, componentType)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun hasSpread(argument: ResolvedValueArgument): Boolean {
|
||||
@@ -226,6 +224,7 @@ class ConstantExpressionEvaluator(
|
||||
|
||||
private fun resolveAnnotationValueArguments(
|
||||
resolvedValueArgument: ResolvedValueArgument,
|
||||
deprecatedExpectedType: KotlinType,
|
||||
expectedType: KotlinType,
|
||||
trace: BindingTrace
|
||||
): List<CompileTimeConstant<*>> {
|
||||
@@ -240,7 +239,21 @@ class ConstantExpressionEvaluator(
|
||||
if (constant != null) {
|
||||
constants.add(constant)
|
||||
}
|
||||
checkCompileTimeConstant(argumentExpression, expectedType, trace)
|
||||
|
||||
val expressionType = trace.getType(argumentExpression) ?: continue
|
||||
|
||||
// this type check should not used as it can introduce subtle bugs when type checking rules against expected type are changing
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonConstValuesAsVarargsInAnnotations) &&
|
||||
!KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, deprecatedExpectedType)
|
||||
) {
|
||||
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
|
||||
checkCompileTimeConstant(argumentExpression, expressionType, trace, useDeprecationWarning = true)
|
||||
}
|
||||
|
||||
continue // TYPE_MISMATCH should be reported otherwise
|
||||
}
|
||||
|
||||
checkCompileTimeConstant(argumentExpression, expressionType, trace, useDeprecationWarning = false)
|
||||
}
|
||||
return constants
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ class DeprecationResolver(
|
||||
ProtoBuf.VersionRequirement.VersionKind.API_VERSION ->
|
||||
languageVersionSettings.apiVersion.version
|
||||
ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION ->
|
||||
KotlinCompilerVersion.getVersion()?.takeIf { "SNAPSHOT" !in it }?.let(::createVersion)
|
||||
KotlinCompilerVersion.getVersion()?.substringBefore('-')?.let(::createVersion)
|
||||
else -> null
|
||||
}
|
||||
if (currentVersion != null && currentVersion < requiredVersion) {
|
||||
|
||||
@@ -40,7 +40,7 @@ class ClassResolutionScopesSupport(
|
||||
}
|
||||
}
|
||||
|
||||
val scopeForClassHeaderResolution: () -> LexicalScope = storageManager.createLazyValue {
|
||||
val scopeForClassHeaderResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createErrorLexicalScope) {
|
||||
scopeWithGenerics(getOuterScope())
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ sourceSets {
|
||||
|
||||
projectTest {
|
||||
workingDir = rootDir
|
||||
doFirst {
|
||||
systemProperty("idea.home.path", intellijRootDir().canonicalPath)
|
||||
}
|
||||
}
|
||||
|
||||
testsJar()
|
||||
|
||||
@@ -29,6 +29,7 @@ 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
|
||||
import java.io.File
|
||||
@@ -43,7 +44,8 @@ abstract class IncrementalCompilerRunner<
|
||||
protected val cacheVersions: List<CacheVersion>,
|
||||
protected val reporter: ICReporter,
|
||||
protected val artifactChangesProvider: ArtifactChangesProvider?,
|
||||
protected val changesRegistry: ChangesRegistry?
|
||||
protected val changesRegistry: ChangesRegistry?,
|
||||
private val localStateDirs: Collection<File> = emptyList()
|
||||
) {
|
||||
|
||||
protected val cacheDirectory = File(workingDir, cacheDirName)
|
||||
@@ -70,7 +72,15 @@ abstract class IncrementalCompilerRunner<
|
||||
|
||||
caches.clean()
|
||||
dirtySourcesSinceLastTimeFile.delete()
|
||||
destinationDir(args).deleteRecursively()
|
||||
|
||||
reporter.report { "Deleting output directories on rebuild:" }
|
||||
for (dir in sequenceOf(destinationDir(args)) + localStateDirs.asSequence()) {
|
||||
if (!dir.isDirectory) continue
|
||||
|
||||
dir.deleteRecursively()
|
||||
dir.mkdirs()
|
||||
reporter.report { "deleted $dir" }
|
||||
}
|
||||
|
||||
caches = createCacheManager(args)
|
||||
if (providedChangedFiles == null) {
|
||||
@@ -271,6 +281,30 @@ abstract class IncrementalCompilerRunner<
|
||||
return exitCode
|
||||
}
|
||||
|
||||
protected fun getRemovedClassesChanges(
|
||||
caches: IncrementalCachesManager<*>,
|
||||
changedFiles: ChangedFiles.Known
|
||||
): DirtyData {
|
||||
val removedClasses = HashSet<String>()
|
||||
val dirtyFiles = changedFiles.modified.filterTo(HashSet()) { it.isKotlinFile() }
|
||||
val removedFiles = changedFiles.removed.filterTo(HashSet()) { it.isKotlinFile() }
|
||||
|
||||
val existingClasses = classesFqNames(dirtyFiles)
|
||||
val previousClasses = caches.platformCache
|
||||
.classesFqNamesBySources(dirtyFiles + removedFiles)
|
||||
.map { it.asString() }
|
||||
|
||||
for (fqName in previousClasses) {
|
||||
if (fqName !in existingClasses) {
|
||||
removedClasses.add(fqName)
|
||||
}
|
||||
}
|
||||
|
||||
val changesCollector = ChangesCollector()
|
||||
removedClasses.forEach { changesCollector.collectSignature(FqName(it), areSubclassesAffected = true) }
|
||||
return changesCollector.getDirtyData(listOf(caches.platformCache), reporter)
|
||||
}
|
||||
|
||||
open fun runWithNoDirtyKotlinSources(caches: CacheManager): Boolean = false
|
||||
|
||||
protected open fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) {
|
||||
|
||||
@@ -27,6 +27,7 @@ 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.js.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.File
|
||||
|
||||
fun makeJsIncrementally(
|
||||
@@ -92,7 +93,29 @@ class IncrementalJsCompilerRunner(
|
||||
|
||||
if (changedLib != null) return CompilationMode.Rebuild { "Library has been changed: $changedLib" }
|
||||
|
||||
return CompilationMode.Incremental(getDirtyFiles(changedFiles))
|
||||
val dirtyFiles = getDirtyFiles(changedFiles)
|
||||
|
||||
// todo: unify with JVM calculateSourcesToCompile
|
||||
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
|
||||
if (lookupSymbols.isEmpty()) return
|
||||
|
||||
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
|
||||
dirtyFiles.addAll(dirtyFilesFromLookups)
|
||||
}
|
||||
|
||||
fun markDirtyBy(dirtyClassesFqNames: Collection<FqName>) {
|
||||
if (dirtyClassesFqNames.isEmpty()) return
|
||||
|
||||
val fqNamesWithSubtypes = dirtyClassesFqNames.flatMap { withSubtypes(it, listOf(caches.platformCache)) }
|
||||
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.platformCache), fqNamesWithSubtypes, reporter)
|
||||
dirtyFiles.addAll(dirtyFilesFromFqNames)
|
||||
}
|
||||
|
||||
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
|
||||
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
|
||||
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
|
||||
|
||||
return CompilationMode.Incremental(dirtyFiles)
|
||||
}
|
||||
|
||||
override fun makeServices(
|
||||
|
||||
@@ -71,7 +71,8 @@ fun makeIncrementally(
|
||||
sourceRoots.map { JvmSourceRoot(it, null) }.toSet(),
|
||||
versions, reporter,
|
||||
// Use precise setting in case of non-Gradle build
|
||||
usePreciseJavaTracking = true
|
||||
usePreciseJavaTracking = true,
|
||||
localStateDirs = emptyList()
|
||||
)
|
||||
compiler.compile(sourceFiles, args, messageCollector, providedChangedFiles = null)
|
||||
}
|
||||
@@ -104,14 +105,16 @@ class IncrementalJvmCompilerRunner(
|
||||
changesRegistry: ChangesRegistry? = null,
|
||||
private val buildHistoryFile: File? = null,
|
||||
private val friendBuildHistoryFile: File? = null,
|
||||
private val usePreciseJavaTracking: Boolean
|
||||
private val usePreciseJavaTracking: Boolean,
|
||||
localStateDirs: Collection<File>
|
||||
) : IncrementalCompilerRunner<K2JVMCompilerArguments, IncrementalJvmCachesManager>(
|
||||
workingDir,
|
||||
"caches-jvm",
|
||||
cacheVersions,
|
||||
reporter,
|
||||
artifactChangesProvider,
|
||||
changesRegistry
|
||||
changesRegistry,
|
||||
localStateDirs = localStateDirs
|
||||
) {
|
||||
override fun isICEnabled(): Boolean =
|
||||
IncrementalCompilation.isEnabled()
|
||||
@@ -138,7 +141,11 @@ class IncrementalJvmCompilerRunner(
|
||||
else
|
||||
null
|
||||
|
||||
override fun calculateSourcesToCompile(caches: IncrementalJvmCachesManager, changedFiles: ChangedFiles.Known, args: K2JVMCompilerArguments): CompilationMode {
|
||||
override fun calculateSourcesToCompile(
|
||||
caches: IncrementalJvmCachesManager,
|
||||
changedFiles: ChangedFiles.Known,
|
||||
args: K2JVMCompilerArguments
|
||||
): CompilationMode {
|
||||
val dirtyFiles = getDirtyFiles(changedFiles)
|
||||
|
||||
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
|
||||
@@ -211,10 +218,13 @@ class IncrementalJvmCompilerRunner(
|
||||
}
|
||||
|
||||
val androidLayoutChanges = processLookupSymbolsForAndroidLayouts(changedFiles)
|
||||
val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles)
|
||||
|
||||
markDirtyBy(androidLayoutChanges)
|
||||
markDirtyBy(classpathChanges.lookupSymbols)
|
||||
markDirtyBy(classpathChanges.fqNames)
|
||||
markDirtyBy(removedClassesChanges.dirtyLookupSymbols)
|
||||
markDirtyBy(removedClassesChanges.dirtyClassesFqNames)
|
||||
|
||||
return CompilationMode.Incremental(dirtyFiles)
|
||||
}
|
||||
@@ -311,7 +321,9 @@ class IncrementalJvmCompilerRunner(
|
||||
override fun preBuildHook(args: K2JVMCompilerArguments, compilationMode: CompilationMode) {
|
||||
when (compilationMode) {
|
||||
is CompilationMode.Incremental -> {
|
||||
args.classpathAsList += args.destinationAsFile.apply { mkdirs() }
|
||||
val destinationDir = args.destinationAsFile
|
||||
destinationDir.mkdirs()
|
||||
args.classpathAsList = listOf(destinationDir) + args.classpathAsList
|
||||
}
|
||||
is CompilationMode.Rebuild -> {
|
||||
// there is no point in updating annotation file since all files will be compiled anyway
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.parsing
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.openapi.vfs.local.CoreLocalFileSystem
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.SingleRootFileViewProvider
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
fun classesFqNames(files: Set<File>): Set<String> {
|
||||
val existingKotlinFiles = files.filter { it.name.endsWith(".kt", ignoreCase = true) && it.isFile }
|
||||
if (existingKotlinFiles.isEmpty()) return emptySet()
|
||||
|
||||
val disposable = Disposer.newDisposable()
|
||||
|
||||
return try {
|
||||
classesFqNames(existingKotlinFiles, disposable)
|
||||
} finally {
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun classesFqNames(kotlinFiles: Collection<File>, disposable: Disposable): Set<String> {
|
||||
val config = CompilerConfiguration()
|
||||
config.put(JVMConfigurationKeys.NO_JDK, true)
|
||||
config.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
|
||||
val configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||
val environment = KotlinCoreEnvironment.createForProduction(disposable, config, configFiles)
|
||||
val psiManager = PsiManager.getInstance(environment.project)
|
||||
val fileManager = VirtualFileManager.getInstance()
|
||||
val localFS = fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem
|
||||
|
||||
val result = HashSet<String>()
|
||||
|
||||
for (file in kotlinFiles) {
|
||||
val virtualFile = localFS.findFileByIoFile(file)!!
|
||||
|
||||
for (psiFile in SingleRootFileViewProvider(psiManager, virtualFile).allFiles) {
|
||||
if (psiFile !is KtFile) continue
|
||||
|
||||
val classes = ArrayDeque<KtClassOrObject>()
|
||||
psiFile.declarations.filterClassesTo(classes)
|
||||
while (classes.isNotEmpty()) {
|
||||
val klass = classes.pollFirst()
|
||||
klass.fqName?.let {
|
||||
result.add(it.asString())
|
||||
}
|
||||
klass.declarations.filterClassesTo(classes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun Collection<KtDeclaration>.filterClassesTo(classes: Deque<KtClassOrObject>) {
|
||||
filterIsInstanceTo<KtClassOrObject, Deque<KtClassOrObject>>(classes)
|
||||
}
|
||||
@@ -101,7 +101,7 @@ abstract class AbstractIncrementalCompilerRunnerTestBase<Args : CommonCompilerAr
|
||||
Assert.assertEquals("Rebuild exit code differs from incremental exit code", rebuildExpectedToSucceed, rebuildSucceeded)
|
||||
|
||||
if (rebuildSucceeded) {
|
||||
assertEqualDirectories(outDir, rebuildOutDir, forgiveExtraFiles = rebuildSucceeded)
|
||||
assertEqualDirectories(rebuildOutDir, outDir, forgiveExtraFiles = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ abstract class AbstractIncrementalJsCompilerRunnerTest : AbstractIncrementalComp
|
||||
override fun createCompilerArguments(destinationDir: File, testDir: File): K2JSCompilerArguments =
|
||||
K2JSCompilerArguments().apply {
|
||||
outputFile = File(destinationDir, "${testDir.name}.js").path
|
||||
sourceMap = true
|
||||
sourceMap = false
|
||||
metaInfo = true
|
||||
}
|
||||
}
|
||||
@@ -756,6 +756,12 @@ public class IncrementalJsCompilerRunnerTestGenerated extends AbstractIncrementa
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classMovedIntoOtherClass")
|
||||
public void testClassMovedIntoOtherClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classMovedIntoOtherClass/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classRemoved")
|
||||
public void testClassRemoved() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classRemoved/");
|
||||
|
||||
@@ -756,6 +756,12 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classMovedIntoOtherClass")
|
||||
public void testClassMovedIntoOtherClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classMovedIntoOtherClass/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classRemoved")
|
||||
public void testClassRemoved() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classRemoved/");
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.parsing
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class ClassesFqNamesTest {
|
||||
private lateinit var workingDir: File
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
workingDir = FileUtil.createTempDirectory("ClassesFqNamesTest", null)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
workingDir.deleteRecursively()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSingleClass() {
|
||||
doTest(
|
||||
setOf("test.Foo"),
|
||||
"""
|
||||
package test
|
||||
|
||||
class Foo""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleClasses() {
|
||||
doTest(
|
||||
setOf("test.Fizz", "test.Buzz"),
|
||||
"""
|
||||
package test
|
||||
|
||||
class Fizz
|
||||
class Buzz""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInnerClasses() {
|
||||
doTest(
|
||||
setOf("test.Foo", "test.Foo.Fizz", "test.Foo.Buzz"),
|
||||
"""
|
||||
package test
|
||||
|
||||
class Foo {
|
||||
class Fizz
|
||||
class Buzz
|
||||
}""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testObject() {
|
||||
doTest(
|
||||
setOf("test.Foo", "test.Foo.Fizz", "test.Bar", "test.Bar.Buzz"),
|
||||
"""
|
||||
package test
|
||||
|
||||
object Foo {
|
||||
class Fizz
|
||||
}
|
||||
|
||||
class Bar {
|
||||
object Buzz
|
||||
}""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private fun doTest(expectedClasses: Set<String>, code: String) {
|
||||
val testKt = File(workingDir, "test.kt")
|
||||
testKt.writeText(code)
|
||||
|
||||
val expected = expectedClasses.sorted().joinToString("\n")
|
||||
val actual = classesFqNames(setOf(testKt)).sorted().joinToString("\n")
|
||||
UsefulTestCase.assertEquals(expected, actual)
|
||||
}
|
||||
}
|
||||
@@ -34,11 +34,11 @@ import org.jetbrains.kotlin.codegen.AsmUtil.isAbstractMethod
|
||||
import org.jetbrains.kotlin.codegen.BuiltinSpecialBridgesUtil
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen.isMethodOfAny
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen.isThereOverriddenInKotlinClass
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -60,6 +60,8 @@ import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescripto
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -73,12 +75,12 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
private val typeMapper = state.typeMapper
|
||||
|
||||
private val IS_PURE_INTERFACE_CHECKER = fun(descriptor: DeclarationDescriptor): Boolean =
|
||||
JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state)
|
||||
private val DECLARATION_AND_DEFINITION_CHECKER = fun(descriptor: CallableMemberDescriptor): Boolean =
|
||||
!isInterface(descriptor.containingDeclaration) || state.target !== JvmTarget.JVM_1_6 && descriptor.hasJvmDefaultAnnotation()
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
val classDescriptor = irClass.descriptor
|
||||
if (IS_PURE_INTERFACE_CHECKER(classDescriptor) || classDescriptor is FileClassDescriptor) return
|
||||
if (classDescriptor is FileClassDescriptor) return
|
||||
|
||||
if (classDescriptor is DefaultImplsClassDescriptor) {
|
||||
return /*TODO?*/
|
||||
@@ -133,7 +135,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
bridgesToGenerate = generateBridgesForFunctionDescriptor(
|
||||
descriptor,
|
||||
getSignatureMapper(typeMapper),
|
||||
IS_PURE_INTERFACE_CHECKER
|
||||
DECLARATION_AND_DEFINITION_CHECKER
|
||||
)
|
||||
if (!bridgesToGenerate.isEmpty()) {
|
||||
val origin = if (descriptor.kind == DECLARATION) getSourceFromDescriptor(descriptor) else null
|
||||
@@ -148,7 +150,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
val specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||
descriptor,
|
||||
getSignatureMapper(typeMapper),
|
||||
IS_PURE_INTERFACE_CHECKER
|
||||
DECLARATION_AND_DEFINITION_CHECKER
|
||||
)
|
||||
|
||||
if (!specials.isEmpty()) {
|
||||
@@ -160,7 +162,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
if (!descriptor.kind.isReal && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state)) {
|
||||
if (!descriptor.kind.isReal && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
|
||||
descriptor.getOverriddenBuiltinReflectingJvmDescriptor<CallableMemberDescriptor>() ?:
|
||||
error("Expect to find overridden descriptors for $descriptor")
|
||||
|
||||
|
||||
@@ -31,6 +31,12 @@ interface CommandLineProcessor {
|
||||
put(option, paths)
|
||||
}
|
||||
|
||||
fun <T> CompilerConfiguration.appendList(option: CompilerConfigurationKey<List<T>>, values: List<T>) {
|
||||
val paths = getList(option).toMutableList()
|
||||
paths.addAll(values)
|
||||
put(option, paths)
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.applyOptionsFrom(map: Map<String, List<String>>, pluginOptions: Collection<CliOption>) {
|
||||
for ((key, values) in map) {
|
||||
val option = pluginOptions.firstOrNull { it.name == key } ?: continue
|
||||
|
||||
@@ -37,6 +37,8 @@ public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveSt
|
||||
super(stub, KtStubElementTypes.IMPORT_DIRECTIVE);
|
||||
}
|
||||
|
||||
private volatile FqName importedFqName;
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(@NotNull KtVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitImportDirective(this, data);
|
||||
@@ -78,7 +80,16 @@ public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveSt
|
||||
if (stub != null) {
|
||||
return stub.getImportedFqName();
|
||||
}
|
||||
return fqNameFromExpression(getImportedReference());
|
||||
|
||||
FqName importedFqName = this.importedFqName;
|
||||
if (importedFqName != null) return importedFqName;
|
||||
KtExpression importedReference = getImportedReference();
|
||||
// in case it's not parsed
|
||||
if (importedReference == null) return null;
|
||||
|
||||
importedFqName = fqNameFromExpression(importedReference);
|
||||
this.importedFqName = importedFqName;
|
||||
return importedFqName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -106,6 +117,12 @@ public class KtImportDirective extends KtElementImplStub<KotlinImportDirectiveSt
|
||||
return !PsiTreeUtil.hasErrorElements(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subtreeChanged() {
|
||||
super.subtreeChanged();
|
||||
importedFqName = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FqName fqNameFromExpression(@Nullable KtExpression expression) {
|
||||
if (expression == null) {
|
||||
|
||||
@@ -170,6 +170,14 @@ fun prefixExpressionRecursiveVisitor(block: (KtPrefixExpression) -> Unit) =
|
||||
}
|
||||
}
|
||||
|
||||
fun typeReferenceRecursiveVisitor(block: (KtTypeReference) -> Unit) =
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitTypeReference(typeReference: KtTypeReference) {
|
||||
super.visitTypeReference(typeReference)
|
||||
block(typeReference)
|
||||
}
|
||||
}
|
||||
|
||||
fun namedFunctionVisitor(block: (KtNamedFunction) -> Unit) =
|
||||
object : KtVisitorVoid() {
|
||||
override fun visitNamedFunction(namedFunction: KtNamedFunction) {
|
||||
|
||||
@@ -28,7 +28,7 @@ object KotlinStubVersions {
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 64
|
||||
private const val BINARY_STUB_VERSION = 66
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.script
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||
import com.intellij.openapi.util.UserDataHolderBase
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
@@ -26,7 +27,7 @@ import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||
|
||||
open class KotlinScriptDefinition(val template: KClass<out Any>) {
|
||||
open class KotlinScriptDefinition(val template: KClass<out Any>) : UserDataHolderBase() {
|
||||
|
||||
open val name: String = "Kotlin Script"
|
||||
|
||||
@@ -45,6 +46,9 @@ open class KotlinScriptDefinition(val template: KClass<out Any>) {
|
||||
open val dependencyResolver: DependenciesResolver get() = DependenciesResolver.NoDependencies
|
||||
|
||||
open val acceptedAnnotations: List<KClass<out Annotation>> get() = emptyList()
|
||||
|
||||
@Deprecated("temporary workaround for missing functionality, will be replaced by the new API soon")
|
||||
open val additionalCompilerArguments: Iterable<String>? = null
|
||||
}
|
||||
|
||||
object StandardScriptDefinition : KotlinScriptDefinition(ScriptTemplateWithArgs::class)
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
@@ -70,20 +69,44 @@ fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
|
||||
return DFS.ifAny(
|
||||
listOf(this),
|
||||
{ current -> current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
|
||||
{ it.declaresDefaultValue() || it.isActualParameterWithExpectedDefault }
|
||||
{ it.declaresDefaultValue() || it.isActualParameterWithAnyExpectedDefault }
|
||||
)
|
||||
}
|
||||
|
||||
val ValueParameterDescriptor.isActualParameterWithExpectedDefault: Boolean
|
||||
get() {
|
||||
val function = containingDeclaration
|
||||
if (function is FunctionDescriptor && function.isActual) {
|
||||
with(ExpectedActualResolver) {
|
||||
val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull()
|
||||
return expected is FunctionDescriptor && expected.valueParameters[index].hasDefaultValue()
|
||||
}
|
||||
fun ValueParameterDescriptor.checkExpectedParameter(checker: (ValueParameterDescriptor) -> Boolean) : Boolean {
|
||||
val function = containingDeclaration
|
||||
if (function is FunctionDescriptor && function.isActual) {
|
||||
with(ExpectedActualResolver) {
|
||||
val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull()
|
||||
return expected is FunctionDescriptor && checker(expected.valueParameters[index])
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* The following two properties describe two different situations:
|
||||
*
|
||||
* Consider hierarchy:
|
||||
* expect open class A { foo(p = 1) }
|
||||
* expect open class B : A { foo(p) }
|
||||
*
|
||||
* actual open class A { foo(p) }
|
||||
* actual open class B : A { foo(p) }
|
||||
*
|
||||
* For parameter `p` of method `foo`:
|
||||
* `Any` property returns `true` for both actual A and B
|
||||
* `Corresponding` property returns `true` only for `actual A` because `expect B` declaration doesn't have an default value
|
||||
*/
|
||||
|
||||
val ValueParameterDescriptor.isActualParameterWithAnyExpectedDefault: Boolean
|
||||
get() {
|
||||
return checkExpectedParameter { it.hasDefaultValue() }
|
||||
}
|
||||
|
||||
val ValueParameterDescriptor.isActualParameterWithCorrespondingExpectedDefault: Boolean
|
||||
get() {
|
||||
return checkExpectedParameter { it.declaresDefaultValue() }
|
||||
}
|
||||
|
||||
private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation(
|
||||
|
||||
@@ -22,9 +22,11 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.RequireKotlinNames
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithExpectedDefault
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmDefaultAnnotation
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithAnyExpectedDefault
|
||||
import org.jetbrains.kotlin.resolve.checkers.KotlinVersionStringAnnotationValueChecker
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.constants.IntValue
|
||||
@@ -141,6 +143,8 @@ class DescriptorSerializer private constructor(
|
||||
val requirement = serializeVersionRequirement(classDescriptor)
|
||||
if (requirement != null) {
|
||||
builder.versionRequirement = requirement
|
||||
} else {
|
||||
writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor, builder)
|
||||
}
|
||||
|
||||
val versionRequirementTableProto = versionRequirementTable.serialize()
|
||||
@@ -306,8 +310,7 @@ class DescriptorSerializer private constructor(
|
||||
val requirement = serializeVersionRequirement(descriptor)
|
||||
if (requirement != null) {
|
||||
builder.versionRequirement = requirement
|
||||
}
|
||||
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
} else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
|
||||
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
|
||||
}
|
||||
|
||||
@@ -408,7 +411,7 @@ class DescriptorSerializer private constructor(
|
||||
private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder {
|
||||
val builder = ProtoBuf.ValueParameter.newBuilder()
|
||||
|
||||
val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithExpectedDefault
|
||||
val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithAnyExpectedDefault
|
||||
|
||||
val flags = Flags.getValueParameterFlags(
|
||||
hasAnnotations(descriptor), declaresDefaultValue, descriptor.isCrossinline, descriptor.isNoinline
|
||||
@@ -615,13 +618,36 @@ class DescriptorSerializer private constructor(
|
||||
return builder
|
||||
}
|
||||
|
||||
// Interfaces which have @JvmDefault members somewhere in the hierarchy need the compiler 1.2.40+
|
||||
// so that the generated bridges in subclasses would call the super members correctly
|
||||
private fun writeVersionRequirementForJvmDefaultIfNeeded(classDescriptor: ClassDescriptor, builder: ProtoBuf.Class.Builder) {
|
||||
if (
|
||||
isInterface(classDescriptor) &&
|
||||
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors().any {
|
||||
it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation()
|
||||
}
|
||||
) {
|
||||
builder.versionRequirement = writeVersionRequirement(1, 2, 40, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION)
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeVersionRequirement(languageFeature: LanguageFeature): Int {
|
||||
val languageVersion = languageFeature.sinceVersion!!
|
||||
return writeVersionRequirement(
|
||||
languageVersion.major, languageVersion.minor, 0,
|
||||
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION
|
||||
)
|
||||
}
|
||||
|
||||
private fun writeVersionRequirement(major: Int, minor: Int, patch: Int, versionKind: ProtoBuf.VersionRequirement.VersionKind): Int {
|
||||
val requirement = ProtoBuf.VersionRequirement.newBuilder().apply {
|
||||
VersionRequirement.Version(languageVersion.major, languageVersion.minor).encode(
|
||||
writeVersion = { version = it },
|
||||
writeVersionFull = { versionFull = it }
|
||||
VersionRequirement.Version(major, minor, patch).encode(
|
||||
writeVersion = { version = it },
|
||||
writeVersionFull = { versionFull = it }
|
||||
)
|
||||
if (versionKind != defaultInstanceForType.versionKind) {
|
||||
this.versionKind = versionKind
|
||||
}
|
||||
}
|
||||
return versionRequirementTable[requirement]
|
||||
}
|
||||
|
||||
1
compiler/testData/cli/js/jsExtraHelp.out
vendored
1
compiler/testData/cli/js/jsExtraHelp.out
vendored
@@ -2,6 +2,7 @@ Usage: kotlinc-js <options> <source files>
|
||||
where advanced options include:
|
||||
-Xfriend-modules=<path> Paths to friend modules
|
||||
-Xfriend-modules-disabled Disable internal declaration export
|
||||
-Xtyped-arrays Translate primitive arrays to JS typed arrays
|
||||
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
|
||||
-Xcoroutines={enable|warn|error}
|
||||
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
||||
|
||||
2
compiler/testData/cli/jvm/extraHelp.out
vendored
2
compiler/testData/cli/jvm/extraHelp.out
vendored
@@ -8,6 +8,7 @@ where advanced options include:
|
||||
-Xnormalize-constructor-calls={disable|enable}
|
||||
Normalize constructor calls (disable: don't normalize; enable: normalize), default is disable
|
||||
-Xdump-declarations-to=<path> Path to JSON file to dump Java to Kotlin declaration mappings
|
||||
-Xenable-jvm-default Allow to use '@JvmDefault' for JVM default method support
|
||||
-Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade
|
||||
-Xmodule-path=<path> Paths where to find Java 9+ modules
|
||||
-Xjavac-arguments=<option[,]> Java compiler arguments
|
||||
@@ -40,6 +41,7 @@ where advanced options include:
|
||||
Default value is 'enable'
|
||||
-Xuse-javac Use javac for Java source and class files analysis
|
||||
-Xuse-old-class-files-reading Use old class files reading implementation (may slow down the build and should be used in case of problems with the new implementation)
|
||||
-Xuse-type-table Use type table in metadata serialization
|
||||
-Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info
|
||||
-Xcoroutines={enable|warn|error}
|
||||
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user