mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-17 15:51:23 +00:00
Compare commits
2 Commits
rr/stdlib/
...
get-script
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
106ea55afc | ||
|
|
977d170d11 |
@@ -10,7 +10,7 @@
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value=":compiler:tests-for-compiler-generator:generateTests" />
|
||||
<option value=":compiler:generateTests" />
|
||||
<option value=":compiler:tests-java8:generateTests" />
|
||||
<option value=":compiler:tests-against-klib:generateTests" />
|
||||
<option value=":js:js.tests:generateTests" />
|
||||
@@ -22,4 +22,4 @@
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
</component>
|
||||
@@ -1,24 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Generate FIR Checker Components and FIR/IDE Diagnostics" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value=":compiler:fir:checkers:generateCheckersComponents" />
|
||||
<option value=":idea:idea-frontend-fir:generateCode" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
443
ChangeLog.md
443
ChangeLog.md
@@ -1,440 +1,5 @@
|
||||
# CHANGELOG
|
||||
|
||||
|
||||
## 1.4.30
|
||||
|
||||
### Android
|
||||
|
||||
- [`KT-42383`](https://youtrack.jetbrains.com/issue/KT-42383) HMPP: Bad IDEA dependencies: Missing dependency from p1:jvmAndAndroid to p2:jvmAndAndroid
|
||||
|
||||
### Backend. Native
|
||||
|
||||
- [`KT-38772`](https://youtrack.jetbrains.com/issue/KT-38772) Native: support non-reified type parameters in typeOf
|
||||
- [`KT-42234`](https://youtrack.jetbrains.com/issue/KT-42234) Move LLVM optimization parameters into konan.properties
|
||||
- [`KT-42649`](https://youtrack.jetbrains.com/issue/KT-42649) IndexOutOfBoundsException during InlineClassTransformer lowering
|
||||
- [`KT-42942`](https://youtrack.jetbrains.com/issue/KT-42942) Native: optimize peak backend memory by clearing BindingContext after psi2ir
|
||||
- [`KT-43198`](https://youtrack.jetbrains.com/issue/KT-43198) Native: support `init` blocks inside inline classes
|
||||
|
||||
### Compiler
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-28055`](https://youtrack.jetbrains.com/issue/KT-28055) Support `init` blocks inside inline classes
|
||||
- [`KT-28056`](https://youtrack.jetbrains.com/issue/KT-28056) Consider supporting non-public primary constructors for inline classes
|
||||
- [`KT-41265`](https://youtrack.jetbrains.com/issue/KT-41265) Support noarg compiler plugin for JVM IR
|
||||
- [`KT-42094`](https://youtrack.jetbrains.com/issue/KT-42094) Allow open callable members in expect interfaces
|
||||
- [`KT-43129`](https://youtrack.jetbrains.com/issue/KT-43129) FIR: Support OverloadResolutionByLambdaReturnType
|
||||
- [`KT-43592`](https://youtrack.jetbrains.com/issue/KT-43592) Promote JVM IR compiler backend to Beta
|
||||
- [`KT-43919`](https://youtrack.jetbrains.com/issue/KT-43919) Support loading Java annotations on base classes and implementing interfaces' type arguments
|
||||
- [`KT-44021`](https://youtrack.jetbrains.com/issue/KT-44021) Enable JVM IR backend by default in 1.5
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
- [`KT-41352`](https://youtrack.jetbrains.com/issue/KT-41352) JVM IR: reduce bytecode size in for loops and range checks with 'until' by not using inclusive end
|
||||
- [`KT-41644`](https://youtrack.jetbrains.com/issue/KT-41644) NI: Infinite compilation
|
||||
- [`KT-42791`](https://youtrack.jetbrains.com/issue/KT-42791) OutOfMemoryError on compilation using kotlin 1.4 on a class with a lot of type inference
|
||||
- [`KT-42920`](https://youtrack.jetbrains.com/issue/KT-42920) NI: Improve performance around adding constraints
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-11454`](https://youtrack.jetbrains.com/issue/KT-11454) Load annotations on TYPE_USE/TYPE_PARAMETER positions from Java class-files
|
||||
- [`KT-11732`](https://youtrack.jetbrains.com/issue/KT-11732) Verify error for generic interface method invocation with default parameters
|
||||
- [`KT-14612`](https://youtrack.jetbrains.com/issue/KT-14612) "ISE: Recursive call in a lazy value" during processing of a (weakly) recursive type alias
|
||||
- [`KT-18344`](https://youtrack.jetbrains.com/issue/KT-18344) Upper bound of a typealias type parameter is not reported correctly if it contains the typealias itself
|
||||
- [`KT-18768`](https://youtrack.jetbrains.com/issue/KT-18768) @Notnull annotation from Java does not work with varargs
|
||||
- [`KT-20548`](https://youtrack.jetbrains.com/issue/KT-20548) java.lang.IllegalStateException: Illegal class container on simple Java code parsing
|
||||
- [`KT-22465`](https://youtrack.jetbrains.com/issue/KT-22465) Excessive synthetic method for private setter from superclass
|
||||
- [`KT-23816`](https://youtrack.jetbrains.com/issue/KT-23816) Inline classes: constants and annotations
|
||||
- [`KT-24158`](https://youtrack.jetbrains.com/issue/KT-24158) AE: No receiver found on incomplete code with $-signs
|
||||
- [`KT-24392`](https://youtrack.jetbrains.com/issue/KT-24392) Nullability of Java arrays is read incorrectly if @Nullable annotation has both targets TYPE_USE and VALUE_PARAMETER
|
||||
- [`KT-26229`](https://youtrack.jetbrains.com/issue/KT-26229) Lambda/anonymous function argument in parentheses is not supported for callsInPlace effect
|
||||
- [`KT-29735`](https://youtrack.jetbrains.com/issue/KT-29735) KNPE at `KtEnumEntrySuperclassReferenceExpression.getReferencedElement` with explicit type argument inside enum member constructor
|
||||
- [`KT-31389`](https://youtrack.jetbrains.com/issue/KT-31389) ClassFormatError with companion object in annotation with @JvmStatic
|
||||
- [`KT-31907`](https://youtrack.jetbrains.com/issue/KT-31907) ISE: UNIT_EXPECTED_TYPE on parsing array literal inside lambda with Unit return type
|
||||
- [`KT-32228`](https://youtrack.jetbrains.com/issue/KT-32228) Inconsistent boxing/unboxing for inline classes when interface is specialized by object expression
|
||||
- [`KT-32450`](https://youtrack.jetbrains.com/issue/KT-32450) Inline class incorrectly gets re-wrapped when provided to a function
|
||||
- [`KT-35849`](https://youtrack.jetbrains.com/issue/KT-35849) Missing nullability assertion on lambda return value if expected type has generic return value type
|
||||
- [`KT-35902`](https://youtrack.jetbrains.com/issue/KT-35902) Kotlin generates a private parameterless constructor for constructors taking inline class arguments with default values
|
||||
- [`KT-36399`](https://youtrack.jetbrains.com/issue/KT-36399) Gradually support TYPE_USE nullability annotations read from class-files
|
||||
- [`KT-36769`](https://youtrack.jetbrains.com/issue/KT-36769) JVM IR: Missing LVT entries for inline function (default) parameters at call site
|
||||
- [`KT-36982`](https://youtrack.jetbrains.com/issue/KT-36982) JVM IR: SAM adapter classes are generated as synthetic
|
||||
- [`KT-37007`](https://youtrack.jetbrains.com/issue/KT-37007) JVM IR: extraneous property accessors are generated in multifile facade for InlineOnly property
|
||||
- [`KT-37317`](https://youtrack.jetbrains.com/issue/KT-37317) [FIR] Add support of extension functions in postponed lambda completion
|
||||
- [`KT-38400`](https://youtrack.jetbrains.com/issue/KT-38400) FIR: interface abstract is preferred to Any method in super resolve
|
||||
- [`KT-38536`](https://youtrack.jetbrains.com/issue/KT-38536) JVM IR: bound adapted function references are not inlined
|
||||
- [`KT-38656`](https://youtrack.jetbrains.com/issue/KT-38656) FIR: determine overridden member visibility properly
|
||||
- [`KT-38901`](https://youtrack.jetbrains.com/issue/KT-38901) FIR: Make behavior of integer literals overflow consistent with FE 1.0
|
||||
- [`KT-39709`](https://youtrack.jetbrains.com/issue/KT-39709) [FIR] False positive UNINITIALIZED_VARIABLE in presence of complex graph with jumps
|
||||
- [`KT-39923`](https://youtrack.jetbrains.com/issue/KT-39923) Result.Failure will get wrapped with Success when using with RxJava
|
||||
- [`KT-40198`](https://youtrack.jetbrains.com/issue/KT-40198) '$default' methods in 'kotlin/test/AssertionsKt' generated as non-synthetic by JVM_IR
|
||||
- [`KT-40200`](https://youtrack.jetbrains.com/issue/KT-40200) IDE: Multiple top-level main functions in different files: broken highlighting, "No descriptor resolved for FUN"
|
||||
- [`KT-40262`](https://youtrack.jetbrains.com/issue/KT-40262) ACC_DEPRECATED flag not generated for property getter delegate in multifile class facade in JVM_IR
|
||||
- [`KT-40282`](https://youtrack.jetbrains.com/issue/KT-40282) Inline class wrapping Any gets double boxed
|
||||
- [`KT-40464`](https://youtrack.jetbrains.com/issue/KT-40464) JVM_IR does not generate LINENUMBER at closing brace of (suspend) lambda
|
||||
- [`KT-40500`](https://youtrack.jetbrains.com/issue/KT-40500) Warnings reporting by Java nullability annotations doesn't work for not top-level types
|
||||
- [`KT-40926`](https://youtrack.jetbrains.com/issue/KT-40926) IDE import actions do not add required import for convention `invoke()` extension call
|
||||
- [`KT-40948`](https://youtrack.jetbrains.com/issue/KT-40948) IllegalAccessError while initializing val property in EXACTLY_ONCE lambda that is passed to another function
|
||||
- [`KT-40991`](https://youtrack.jetbrains.com/issue/KT-40991) NI: UNRESOLVED_REFERENCE_WRONG_RECEIVER instead of FUNCTION_EXPECTED with convention `invoke` call
|
||||
- [`KT-41163`](https://youtrack.jetbrains.com/issue/KT-41163) Double wrapped value in Result class after map operation
|
||||
- [`KT-41284`](https://youtrack.jetbrains.com/issue/KT-41284) Spring CGLIB proxies break auto-generated data class componentN and copy methods when using JVM IR
|
||||
- [`KT-41468`](https://youtrack.jetbrains.com/issue/KT-41468) JVM IR: IllegalAccessError on access to abstract base member from another package, from anonymous object inside abstract class
|
||||
- [`KT-41491`](https://youtrack.jetbrains.com/issue/KT-41491) UNRESOLVED_REFERENCE_WRONG_RECEIVER instead of FUNCTION_EXPECTED when invoking non-functional value as a function
|
||||
- [`KT-41493`](https://youtrack.jetbrains.com/issue/KT-41493) JVM IR: names of classes for local delegated variables contain the variable name twice
|
||||
- [`KT-41792`](https://youtrack.jetbrains.com/issue/KT-41792) [FIR] Introduce & use ConeAttribute.UnsafeVariance
|
||||
- [`KT-41793`](https://youtrack.jetbrains.com/issue/KT-41793) [FIR] Make captured types accessible at the end of resolve
|
||||
- [`KT-41809`](https://youtrack.jetbrains.com/issue/KT-41809) JVM IR: name for internal $default method doesn't include module name
|
||||
- [`KT-41810`](https://youtrack.jetbrains.com/issue/KT-41810) JVM IR: Deprecated(HIDDEN) class is incorrectly generated as synthetic
|
||||
- [`KT-41841`](https://youtrack.jetbrains.com/issue/KT-41841) JVM IR: delegates for private functions with default arguments are generated in multifile classes
|
||||
- [`KT-41857`](https://youtrack.jetbrains.com/issue/KT-41857) Flaky 'ConcurrentModificationException' through `kotlin.serialization.DescriptorSerializer`
|
||||
- [`KT-41903`](https://youtrack.jetbrains.com/issue/KT-41903) JVM IR: do not generate LineNumberTable in auto-generated members of data classes
|
||||
- [`KT-41911`](https://youtrack.jetbrains.com/issue/KT-41911) JVM IR: nested big-arity function calls are not lowered
|
||||
- [`KT-41957`](https://youtrack.jetbrains.com/issue/KT-41957) JVM IR: step into suspend function goes to the first line of the file
|
||||
- [`KT-41960`](https://youtrack.jetbrains.com/issue/KT-41960) JVM IR: smart step into members implemented with delegation to interface doesn't work
|
||||
- [`KT-41961`](https://youtrack.jetbrains.com/issue/KT-41961) JVM IR: line numbers are not generated in JvmMultifileClass facade declarations
|
||||
- [`KT-41962`](https://youtrack.jetbrains.com/issue/KT-41962) JVM IR: intermittent -1 line numbers in the state machine cause double stepping in the debugger
|
||||
- [`KT-42001`](https://youtrack.jetbrains.com/issue/KT-42001) Cannot resolve symbol: AssertionError: Module <sdk 1.8> is not contained in his own dependencies
|
||||
- [`KT-42002`](https://youtrack.jetbrains.com/issue/KT-42002) JVM / IR: IllegalStateException: "No mapping for symbol: VAR IR_TEMPORARY_VARIABLE" caused by named arguments
|
||||
- [`KT-42021`](https://youtrack.jetbrains.com/issue/KT-42021) JVM / IR: "IndexOutOfBoundsException: Index 0 out of bounds for length 0" during IR lowering with suspend conversion
|
||||
- [`KT-42033`](https://youtrack.jetbrains.com/issue/KT-42033) JVM IR: accidental override in Map subclass with custom implementations of some members
|
||||
- [`KT-42036`](https://youtrack.jetbrains.com/issue/KT-42036) IR: "AssertionError: TypeAliasDescriptor expected: deserialized class Nothing" when referencing typealias with @UnsafeVariance
|
||||
- [`KT-42043`](https://youtrack.jetbrains.com/issue/KT-42043) JVM IR: Don't generate collection stubs when implementing methods with more specific return types
|
||||
- [`KT-42044`](https://youtrack.jetbrains.com/issue/KT-42044) Compiler error when lambda with contract surrounded with parentheses
|
||||
- [`KT-42114`](https://youtrack.jetbrains.com/issue/KT-42114) JVM_IR generates stub for 'removeIf' in abstract classes implementing 'List' and 'Set'
|
||||
- [`KT-42115`](https://youtrack.jetbrains.com/issue/KT-42115) JVM_IR doesn't generate 'next' and 'hasNext' method in an abstract class implementing 'ListIterator'
|
||||
- [`KT-42116`](https://youtrack.jetbrains.com/issue/KT-42116) FIR: Java accessor function should not exist in scope together with relevant property
|
||||
- [`KT-42117`](https://youtrack.jetbrains.com/issue/KT-42117) IR-based evaluator cannot handle Java static final fields
|
||||
- [`KT-42118`](https://youtrack.jetbrains.com/issue/KT-42118) FIR2IR: field-targeted annotation is placed on a property, not on a field
|
||||
- [`KT-42130`](https://youtrack.jetbrains.com/issue/KT-42130) FIR: type variable is observed after when condition analysis
|
||||
- [`KT-42132`](https://youtrack.jetbrains.com/issue/KT-42132) FIR2IR: companion function reference has no dispatch receiver
|
||||
- [`KT-42137`](https://youtrack.jetbrains.com/issue/KT-42137) JVM IR: AbstractMethodError on complex hierarchy where implementation comes from another supertype and has a more specific type
|
||||
- [`KT-42186`](https://youtrack.jetbrains.com/issue/KT-42186) JVM / IR: Infinite cycle in for expression when unsigned bytes are used in decreasing loop range
|
||||
- [`KT-42251`](https://youtrack.jetbrains.com/issue/KT-42251) JVM / IR: "IllegalStateException: Descriptor can be left only if it is last" when comparing the i-th element of the container of Int? and `i` with change
|
||||
- [`KT-42253`](https://youtrack.jetbrains.com/issue/KT-42253) JVM IR: NoSuchFieldError on local delegated property in inline function whose call site happens before declaration in the source
|
||||
- [`KT-42281`](https://youtrack.jetbrains.com/issue/KT-42281) JVM / IR: AnalyzerException when comparing Int and array that cast to Any in if condition
|
||||
- [`KT-42340`](https://youtrack.jetbrains.com/issue/KT-42340) FIR2IR: duplicating fake overrides
|
||||
- [`KT-42344`](https://youtrack.jetbrains.com/issue/KT-42344) IR-based evaluator doesn't support "annotation in annotation"
|
||||
- [`KT-42346`](https://youtrack.jetbrains.com/issue/KT-42346) FIR: double-vararg in IR while resolving collection literal as Java annotation argument
|
||||
- [`KT-42348`](https://youtrack.jetbrains.com/issue/KT-42348) FIR: false UNINITIALIZED_VARIABLE in local class
|
||||
- [`KT-42350`](https://youtrack.jetbrains.com/issue/KT-42350) FIR: false UNINITIALIZED_VARIABLE after initialization in try block
|
||||
- [`KT-42351`](https://youtrack.jetbrains.com/issue/KT-42351) FIR: false HIDDEN in enum entry member call
|
||||
- [`KT-42354`](https://youtrack.jetbrains.com/issue/KT-42354) JVM / IR: "AssertionError: Unexpected IR element found during code generation" with KProperty `get` invocation
|
||||
- [`KT-42359`](https://youtrack.jetbrains.com/issue/KT-42359) FIR2IR: cannot mangle type parameter
|
||||
- [`KT-42373`](https://youtrack.jetbrains.com/issue/KT-42373) FIR2IR: local object nested class has no parent if forward-referenced by nested class supertype
|
||||
- [`KT-42384`](https://youtrack.jetbrains.com/issue/KT-42384) FIR (BE): top-level field has no parent class in BE
|
||||
- [`KT-42496`](https://youtrack.jetbrains.com/issue/KT-42496) FIR resolve: synthetic property is written but has no setter
|
||||
- [`KT-42517`](https://youtrack.jetbrains.com/issue/KT-42517) FIR: exception in BE for recursive inline call
|
||||
- [`KT-42530`](https://youtrack.jetbrains.com/issue/KT-42530) "AssertionError: No type for resolved lambda argument" on attempting to assign a Pair to a couple of values in a scratch file
|
||||
- [`KT-42601`](https://youtrack.jetbrains.com/issue/KT-42601) [FIR] Inherited declaration clash for stdlib inheritors
|
||||
- [`KT-42622`](https://youtrack.jetbrains.com/issue/KT-42622) NI: IllegalStateException for if expression with method reference inside flow
|
||||
- [`KT-42642`](https://youtrack.jetbrains.com/issue/KT-42642) ISE: No `getProgressionLastElement` for progression type IntProgressionType
|
||||
- [`KT-42650`](https://youtrack.jetbrains.com/issue/KT-42650) JVM IR: extraneous nullability annotation on a generic function of a flexible type
|
||||
- [`KT-42656`](https://youtrack.jetbrains.com/issue/KT-42656) FIR2IR: unsupported callable reference for Java field
|
||||
- [`KT-42725`](https://youtrack.jetbrains.com/issue/KT-42725) Debugger steps into core library inline functions in chained calls
|
||||
- [`KT-42758`](https://youtrack.jetbrains.com/issue/KT-42758) JVM / IR: Deserialized object that overrides readResolve() is not reference equal to the singleton instance
|
||||
- [`KT-42770`](https://youtrack.jetbrains.com/issue/KT-42770) FIR: duplicating signatures in mangler (typealias for functional type)
|
||||
- [`KT-42771`](https://youtrack.jetbrains.com/issue/KT-42771) FIR: duplicating signature in mangler (data class with delegate)
|
||||
- [`KT-42814`](https://youtrack.jetbrains.com/issue/KT-42814) FIR: false UNINITIALIZED_VARIABLE in local function after if...else
|
||||
- [`KT-42844`](https://youtrack.jetbrains.com/issue/KT-42844) FIR: Property write in init block resolved to parameter write
|
||||
- [`KT-42846`](https://youtrack.jetbrains.com/issue/KT-42846) JVM_IR: NPE on function reference to @JvmStatic method in a different file
|
||||
- [`KT-42933`](https://youtrack.jetbrains.com/issue/KT-42933) JVM / IR: "AnalyzerException: Expected an object reference, but found I" with local delegate in inline class
|
||||
- [`KT-43006`](https://youtrack.jetbrains.com/issue/KT-43006) JVM/JVM_IR: do not generate no-arg constructor for constructor with default arguments if there are inline class types in the signature
|
||||
- [`KT-43017`](https://youtrack.jetbrains.com/issue/KT-43017) JVM / IR: AssertionError when callable reference passed into a function requiring a suspendable function
|
||||
- [`KT-43051`](https://youtrack.jetbrains.com/issue/KT-43051) JVM IR: extraneous methods overridding default (Java 8) collection methods in inline class that extends MutableList
|
||||
- [`KT-43067`](https://youtrack.jetbrains.com/issue/KT-43067) Inner class declaration inside inline class should be prohibited
|
||||
- [`KT-43068`](https://youtrack.jetbrains.com/issue/KT-43068) JVM IR: no generic signatures for explicitly written methods in a List subclass, whose signature coincides with MutableList methods
|
||||
- [`KT-43132`](https://youtrack.jetbrains.com/issue/KT-43132) JVM / IR: Method name '<get-...>' in class '...$screenTexts$1$1' cannot be represented in dex format.
|
||||
- [`KT-43145`](https://youtrack.jetbrains.com/issue/KT-43145) JVM IR: $default methods in multi-file facades are generated as non-synthetic final
|
||||
- [`KT-43156`](https://youtrack.jetbrains.com/issue/KT-43156) FIR: false UNINITIALIZED_VARIABLE after initialization in `synchronized` block
|
||||
- [`KT-43196`](https://youtrack.jetbrains.com/issue/KT-43196) JVM: extra non-static member is generated for extension property in inline class
|
||||
- [`KT-43199`](https://youtrack.jetbrains.com/issue/KT-43199) JVM IR: synthetic flag for deprecated-hidden is not generated for DeprecatedSinceKotlin and deprecation from override
|
||||
- [`KT-43207`](https://youtrack.jetbrains.com/issue/KT-43207) JVM IR: no collection stub for `iterator` is generated on extending AbstractCollection
|
||||
- [`KT-43217`](https://youtrack.jetbrains.com/issue/KT-43217) JVM_IR: Multiple FAKE_OVERRIDES for java methods using @NonNull Double and java double
|
||||
- [`KT-43225`](https://youtrack.jetbrains.com/issue/KT-43225) Confusing message of warning NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER
|
||||
- [`KT-43226`](https://youtrack.jetbrains.com/issue/KT-43226) "Incompatible stack heights" with non-local return to outer lambda inside suspend lambda
|
||||
- [`KT-43242`](https://youtrack.jetbrains.com/issue/KT-43242) JVM / IR: "AnalyzerException: Expected I, but found R" caused by `when` inside object with @Nullable Integer subject
|
||||
- [`KT-43249`](https://youtrack.jetbrains.com/issue/KT-43249) Wrong code generated for suspend lambdas with inline class parameters
|
||||
- [`KT-43286`](https://youtrack.jetbrains.com/issue/KT-43286) JVM IR: IAE "Inline class types should have the same representation: Lkotlin/UInt; != I" on smart cast of unsigned type value with JVM target 1.8
|
||||
- [`KT-43326`](https://youtrack.jetbrains.com/issue/KT-43326) JVM_IR: No deprecated flag for getter of deprecated interface property copied to DefaultImpls
|
||||
- [`KT-43327`](https://youtrack.jetbrains.com/issue/KT-43327) JVM_IR: No deprecated or synthetic flag for accessors of deprecated-hidden property of unsigned type
|
||||
- [`KT-43332`](https://youtrack.jetbrains.com/issue/KT-43332) FIR: Smart casts lead to false-positive ambiguity
|
||||
- [`KT-43370`](https://youtrack.jetbrains.com/issue/KT-43370) JVM IR: No deprecated flag for getter of deprecated property copied via delegation by interface
|
||||
- [`KT-43459`](https://youtrack.jetbrains.com/issue/KT-43459) JVM_IR. Wrong signature for synthetic $annotations method for extension property on nullable primitive
|
||||
- [`KT-43478`](https://youtrack.jetbrains.com/issue/KT-43478) NI: "IndexOutOfBoundsException: Index: 3, Size: 3" caused by `is` check with raw type inside `if` condition with `when` inside
|
||||
- [`KT-43519`](https://youtrack.jetbrains.com/issue/KT-43519) JVM_IR. External functions generated differently in multi file facades
|
||||
- [`KT-43524`](https://youtrack.jetbrains.com/issue/KT-43524) JVM_IR. Missed deprecation flag on companion @JvmStatic property accessor
|
||||
- [`KT-43525`](https://youtrack.jetbrains.com/issue/KT-43525) Prohibit JvmOverloads on declarations with inline class types in parameters
|
||||
- [`KT-43536`](https://youtrack.jetbrains.com/issue/KT-43536) JVM IR: IllegalStateException is not caught by runCatching under Deferred.await() with kotlinx.coroutines
|
||||
- [`KT-43562`](https://youtrack.jetbrains.com/issue/KT-43562) JVM IR: incorrect mangling for Collection.size in unsigned arrays
|
||||
- [`KT-43584`](https://youtrack.jetbrains.com/issue/KT-43584) [FIR] Java annotations with named arguments aren't loaded correctly
|
||||
- [`KT-43587`](https://youtrack.jetbrains.com/issue/KT-43587) Invalid default parameter value in expect actual declaration on jvm
|
||||
- [`KT-43630`](https://youtrack.jetbrains.com/issue/KT-43630) "AssertionError: Number of arguments should not be less than number of parameters" during capturing intersection raw type with star projection
|
||||
- [`KT-43698`](https://youtrack.jetbrains.com/issue/KT-43698) NoSuchMethodError for inline class implementing interface with @JvmDefault methods, -Xjvm-default=enable
|
||||
- [`KT-43741`](https://youtrack.jetbrains.com/issue/KT-43741) Report error on inline class implementing 'kotlin.Cloneable'
|
||||
- [`KT-43845`](https://youtrack.jetbrains.com/issue/KT-43845) org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Failed to generate expression: KtBlockExpression
|
||||
- [`KT-43956`](https://youtrack.jetbrains.com/issue/KT-43956) NI: "Error type encountered – UninferredParameterTypeConstructor" on "try" and other constructs with code block as a value
|
||||
- [`KT-44055`](https://youtrack.jetbrains.com/issue/KT-44055) Left uninferred type parameter for callable references inside special calls
|
||||
- [`KT-44113`](https://youtrack.jetbrains.com/issue/KT-44113) Compiler frontend exception: Number of arguments should not be less than number of parameters, but: parameters=2, args=1
|
||||
- [`KT-44145`](https://youtrack.jetbrains.com/issue/KT-44145) No highlighting for not initialized base constructor and NoSuchMethodError in Android plugin
|
||||
|
||||
### IDE
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-44075`](https://youtrack.jetbrains.com/issue/KT-44075) Sealed interfaces: New Kotlin Class/File menu update
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-29454`](https://youtrack.jetbrains.com/issue/KT-29454) Light class with unexpected name when using obfuscated library
|
||||
- [`KT-31553`](https://youtrack.jetbrains.com/issue/KT-31553) Complete Statement: Wrong auto-insertion of closing curly brace for a code block
|
||||
- [`KT-33466`](https://youtrack.jetbrains.com/issue/KT-33466) IDE generates incorrect `external override` with body for overriding `open external` method
|
||||
- [`KT-39458`](https://youtrack.jetbrains.com/issue/KT-39458) Add CLI support for UL classes
|
||||
- [`KT-40403`](https://youtrack.jetbrains.com/issue/KT-40403) UAST: PsiMethod for invoked extension function/property misses `@receiver:` annotations
|
||||
- [`KT-41406`](https://youtrack.jetbrains.com/issue/KT-41406) Kotlin doesn't report annotations for type arguments (no way to add `@Nls`, `@NonNls` annotations to String collections in Kotlin)
|
||||
- [`KT-41420`](https://youtrack.jetbrains.com/issue/KT-41420) UAST does not return information about type annotations
|
||||
- [`KT-42194`](https://youtrack.jetbrains.com/issue/KT-42194) OOME: Java heap space from incremental compilation
|
||||
- [`KT-42754`](https://youtrack.jetbrains.com/issue/KT-42754) MPP: no smart cast for Common nullable property used in platform module
|
||||
- [`KT-42821`](https://youtrack.jetbrains.com/issue/KT-42821) MPP, IDE: Platform-specific errors are reported even when build doesn't target that platform
|
||||
- [`KT-44116`](https://youtrack.jetbrains.com/issue/KT-44116) Add language version 1.5 to the compiler configuration preferences
|
||||
- [`KT-44523`](https://youtrack.jetbrains.com/issue/KT-44523) IDE notification for trying new JVM backend
|
||||
- [`KT-44543`](https://youtrack.jetbrains.com/issue/KT-44543) Kotlin's LowMemoryWatcher leaks on Kotlin plugin unload
|
||||
|
||||
### IDE. Android
|
||||
|
||||
- [`KT-42381`](https://youtrack.jetbrains.com/issue/KT-42381) MPP: Bad IDEA dependencies: JVM module depending on built artifact instead of sources of module with Android Plugin applied
|
||||
|
||||
### IDE. Completion
|
||||
|
||||
- [`KT-44016`](https://youtrack.jetbrains.com/issue/KT-44016) Code completion: support for "sealed interface"
|
||||
- [`KT-44250`](https://youtrack.jetbrains.com/issue/KT-44250) Code completion does not work in when expression with sealed type argument
|
||||
|
||||
### IDE. Gradle. Script
|
||||
|
||||
- [`KT-39105`](https://youtrack.jetbrains.com/issue/KT-39105) AE “JvmBuiltins has not been initialized properly” after creating new Gradle/Kotlin-based project via old Project Wizard
|
||||
|
||||
### IDE. Inspections and Intentions
|
||||
|
||||
#### New Features
|
||||
|
||||
- [`KT-22666`](https://youtrack.jetbrains.com/issue/KT-22666) "Create enum constant" quick fix could be provided
|
||||
- [`KT-24556`](https://youtrack.jetbrains.com/issue/KT-24556) Add Remove quick fix for "Expression under 'when' is never equal to null"
|
||||
- [`KT-34121`](https://youtrack.jetbrains.com/issue/KT-34121) Report unused result of data class `copy` method
|
||||
- [`KT-34533`](https://youtrack.jetbrains.com/issue/KT-34533) INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER: Add quickfix "Add val to parameter"
|
||||
- [`KT-35215`](https://youtrack.jetbrains.com/issue/KT-35215) Quickfix for CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT to remove `const` modifier
|
||||
- [`KT-40251`](https://youtrack.jetbrains.com/issue/KT-40251) Intention action to evaluate compile time expression
|
||||
- [`KT-44017`](https://youtrack.jetbrains.com/issue/KT-44017) Sealed interfaces: Java side Inspection "implementation of Kotlin sealed interface is forbidden"
|
||||
- [`KT-43941`](https://youtrack.jetbrains.com/issue/KT-43941) Sealed interfaces: intention to extend class/interface
|
||||
- [`KT-44043`](https://youtrack.jetbrains.com/issue/KT-44043) Sealed interfaces: quickfix to move class/interface to proper location
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-20420`](https://youtrack.jetbrains.com/issue/KT-20420) Intention "Put arguments/parameters on separate lines" doesn't respect the "Place ')' on new line" Kotlin code style setting
|
||||
- [`KT-21799`](https://youtrack.jetbrains.com/issue/KT-21799) Quickfix "Change function signature" for receiver type doesn't change it
|
||||
- [`KT-22665`](https://youtrack.jetbrains.com/issue/KT-22665) "Create object" quick fix produce wrong code for enum
|
||||
- [`KT-23934`](https://youtrack.jetbrains.com/issue/KT-23934) IntelliJ suggest "merge map to joinToString" even when such action is impossible due to suspending actions in map
|
||||
- [`KT-30894`](https://youtrack.jetbrains.com/issue/KT-30894) Wrong results of intention "Add names to call arguments" when backticked argument starts from digit
|
||||
- [`KT-31523`](https://youtrack.jetbrains.com/issue/KT-31523) ReplaceWith introduces additional argument name for lambda when named argument is used on call-site
|
||||
- [`KT-31833`](https://youtrack.jetbrains.com/issue/KT-31833) JavaMapForEachInspection should report for expression with implicit receiver
|
||||
- [`KT-33096`](https://youtrack.jetbrains.com/issue/KT-33096) Turn 'MapGetWithNotNullAssertionOperator' into an intention
|
||||
- [`KT-33212`](https://youtrack.jetbrains.com/issue/KT-33212) False positive "map.put() should be converted to assignment" inspection when class inherited from MutableMap has "set" method
|
||||
- [`KT-34270`](https://youtrack.jetbrains.com/issue/KT-34270) False negative "Join declaration and assignment" with constructor call
|
||||
- [`KT-34859`](https://youtrack.jetbrains.com/issue/KT-34859) False positive "Should be replaced with Kotlin function" inspection for Character.toString(int) function
|
||||
- [`KT-34959`](https://youtrack.jetbrains.com/issue/KT-34959) False positive "Redundant overriding method" with different implemented/overridden signatures
|
||||
- [`KT-35051`](https://youtrack.jetbrains.com/issue/KT-35051) False positive "Remove redundant backticks" if variable inside the string and isn't followed by space
|
||||
- [`KT-35097`](https://youtrack.jetbrains.com/issue/KT-35097) False positive "Call replaceable with binary operator" on explicit 'equals' call on a platform type value
|
||||
- [`KT-35165`](https://youtrack.jetbrains.com/issue/KT-35165) "Replace 'if' with elvis operator": don't suggest if val initializer is a complex expression
|
||||
- [`KT-35346`](https://youtrack.jetbrains.com/issue/KT-35346) False positive 'Make internal' suggestion for function inside interface
|
||||
- [`KT-35357`](https://youtrack.jetbrains.com/issue/KT-35357) "Move lambda argument out of parentheses" does not preserve block comments
|
||||
- [`KT-38349`](https://youtrack.jetbrains.com/issue/KT-38349) Invalid suggestion to fold to elvis when having a var-variable
|
||||
- [`KT-40704`](https://youtrack.jetbrains.com/issue/KT-40704) False negative "Redundant semicolon" at start of line
|
||||
- [`KT-40861`](https://youtrack.jetbrains.com/issue/KT-40861) "Convert to secondary constructor" intention expected on class name
|
||||
- [`KT-40879`](https://youtrack.jetbrains.com/issue/KT-40879) False positive "Redundant 'inner' modifier" when calling another inner class with empty constructor
|
||||
- [`KT-40985`](https://youtrack.jetbrains.com/issue/KT-40985) "Remove explicit type arguments" is suggested when type has an annotation
|
||||
- [`KT-41223`](https://youtrack.jetbrains.com/issue/KT-41223) False positive "Redundant inner modifier" inspection ignores constructor arguments of object expressions
|
||||
- [`KT-41246`](https://youtrack.jetbrains.com/issue/KT-41246) False positive "Receiver parameter is never used" with anonymous function expression
|
||||
- [`KT-41298`](https://youtrack.jetbrains.com/issue/KT-41298) "Remove redundant 'with' call" intention works incorrectly with non-local returns and single-expression functions
|
||||
- [`KT-41311`](https://youtrack.jetbrains.com/issue/KT-41311) False positive "Redundant inner modifier" when deriving from a nested Java class
|
||||
- [`KT-41499`](https://youtrack.jetbrains.com/issue/KT-41499) "Convert receiver to parameter" produces code with incorrect order of generic type and function invocation in case of generic function with lambda as a parameter
|
||||
- [`KT-41680`](https://youtrack.jetbrains.com/issue/KT-41680) False positive "Redundant inner modifier" when deriving from class with non-empty constructor and value passed to it from enclosing class
|
||||
- [`KT-42201`](https://youtrack.jetbrains.com/issue/KT-42201) Add Opt-In action doesn't work if there is already OptIn annotation
|
||||
- [`KT-42255`](https://youtrack.jetbrains.com/issue/KT-42255) "Replace elvis expression with 'if' expression" intention shouldn't introduce unnecessary variable if 'error' expression is used
|
||||
|
||||
### IDE. JS
|
||||
|
||||
- [`KT-43760`](https://youtrack.jetbrains.com/issue/KT-43760) KJS: Debugging Kotlin code for Node.js runtime doesn't work
|
||||
|
||||
### IDE. Misc
|
||||
|
||||
- [`KT-44018`](https://youtrack.jetbrains.com/issue/KT-44018) Sealed interfaces: IDE side implementation for hierarchy provider
|
||||
|
||||
### IDE. Multiplatform
|
||||
|
||||
- [`KT-40814`](https://youtrack.jetbrains.com/issue/KT-40814) MISSING_DEPENDENCY_CLASS when consuming native-shared library in a source-set with fewer targets than library has
|
||||
|
||||
### IDE. Run Configurations
|
||||
|
||||
- [`KT-34535`](https://youtrack.jetbrains.com/issue/KT-34535) Unable to run common tests on Android via gutter icon in a multiplatform project
|
||||
|
||||
### IDE. Scratch
|
||||
|
||||
- [`KT-25038`](https://youtrack.jetbrains.com/issue/KT-25038) Scratch: Destructuring declaration produces an unresolved reference
|
||||
- [`KT-43415`](https://youtrack.jetbrains.com/issue/KT-43415) Kotlin scratch file could not be run and could lead to dead lock
|
||||
|
||||
### IDE. Script
|
||||
|
||||
- [`KT-44117`](https://youtrack.jetbrains.com/issue/KT-44117) IDE / Scripts: custom kotlin script definitions aren't loaded
|
||||
|
||||
### JavaScript
|
||||
|
||||
#### Fixes
|
||||
|
||||
- [`KT-31072`](https://youtrack.jetbrains.com/issue/KT-31072) Don't use non-reified arguments to specialize type operations in IR inliner
|
||||
- [`KT-39964`](https://youtrack.jetbrains.com/issue/KT-39964) Throwable incorrectly implements constructor for (null, cause) args in K/JS-IR
|
||||
- [`KT-40090`](https://youtrack.jetbrains.com/issue/KT-40090) KJS: IR. Invalid behaviour for optional parameters (redundant tail undefined parameters)
|
||||
- [`KT-40686`](https://youtrack.jetbrains.com/issue/KT-40686) KJS: Uncaught ReferenceError caused by external class as type inside eventListener in init block
|
||||
- [`KT-40771`](https://youtrack.jetbrains.com/issue/KT-40771) KJS / IR: "ReferenceError: Metadata is not defined" caused by default parameter value in inner class constructor
|
||||
- [`KT-41032`](https://youtrack.jetbrains.com/issue/KT-41032) KJS / IR: "AssertionError: Assertion failed" caused by class that is delegated to inherited interface
|
||||
- [`KT-41076`](https://youtrack.jetbrains.com/issue/KT-41076) KJS / IR: "AssertionError: Assertion failed" caused by overridden extensiion function in child class
|
||||
- [`KT-41771`](https://youtrack.jetbrains.com/issue/KT-41771) KJS / IR: IndexOutOfBoundsException "Index 0 out of bounds for length 0" caused by inline class with List in primary constructor and vararg in secondary
|
||||
- [`KT-42025`](https://youtrack.jetbrains.com/issue/KT-42025) KJS / IR: IrConstructorCallImpl: No such type argument slot: 0
|
||||
- [`KT-42112`](https://youtrack.jetbrains.com/issue/KT-42112) KJS: StackOverflowError on @JsExport in case of name clash with function with Enum parameter with star-projection
|
||||
- [`KT-42262`](https://youtrack.jetbrains.com/issue/KT-42262) KJS: `break`-statements without label are ignored in a `when`
|
||||
- [`KT-42357`](https://youtrack.jetbrains.com/issue/KT-42357) KotlinJS - external class constructor with vararg does not correctly handle spread operator.
|
||||
- [`KT-42364`](https://youtrack.jetbrains.com/issue/KT-42364) KJS: Properties of interface delegate are non-configurable
|
||||
- [`KT-43212`](https://youtrack.jetbrains.com/issue/KT-43212) JS IR: support `init` blocks inside inline classes
|
||||
- [`KT-43222`](https://youtrack.jetbrains.com/issue/KT-43222) KJS IR: prototype lazy initialization for top-level properties like in JVM
|
||||
- [`KT-43313`](https://youtrack.jetbrains.com/issue/KT-43313) KJS / IR: "Can't find name for declaration FUN" for secondary constructor
|
||||
- [`KT-43901`](https://youtrack.jetbrains.com/issue/KT-43901) Call to enum values() method from enum companion object leads to non-initialized enum instances
|
||||
|
||||
### KMM Plugin
|
||||
|
||||
- [`KT-41677`](https://youtrack.jetbrains.com/issue/KT-41677) Could not launch iOS project with custom display name
|
||||
- [`KT-42463`](https://youtrack.jetbrains.com/issue/KT-42463) Launch common tests for Android on local JVM via run gutter
|
||||
- [`KT-43188`](https://youtrack.jetbrains.com/issue/KT-43188) NoSuchMethodError in New Module Wizard of KMM Project
|
||||
|
||||
### Libraries
|
||||
|
||||
- [`KT-41112`](https://youtrack.jetbrains.com/issue/KT-41112) Docs: add more details about bit shift operations
|
||||
- [`KT-41278`](https://youtrack.jetbrains.com/issue/KT-41278) map.entries.contains can return false if the argument is not MutableEntry
|
||||
- [`KT-41356`](https://youtrack.jetbrains.com/issue/KT-41356) Incorrect documentation for `rangeTo` function
|
||||
- [`KT-44456`](https://youtrack.jetbrains.com/issue/KT-44456) Introduce locale-agnostic API for case conversions
|
||||
- [`KT-44458`](https://youtrack.jetbrains.com/issue/KT-44458) Introduce new Char-to-code and Char-to-digit conversions
|
||||
|
||||
### Middle-end. IR
|
||||
|
||||
- [`KT-41765`](https://youtrack.jetbrains.com/issue/KT-41765) [Native/IR] Could not resolveFakeOverride()
|
||||
- [`KT-42054`](https://youtrack.jetbrains.com/issue/KT-42054) Psi2ir: "RuntimeException: IrSimpleFunctionSymbolImpl is already bound" when using result of function with overload resolution by lambda return type
|
||||
|
||||
### Native. C and ObjC Import
|
||||
|
||||
- [`KT-42412`](https://youtrack.jetbrains.com/issue/KT-42412) [C-interop] Modality of generated property accessors is always FINAL
|
||||
|
||||
### Native. ObjC Export
|
||||
|
||||
- [`KT-38530`](https://youtrack.jetbrains.com/issue/KT-38530) Native: values() method of enum classes is not exposed to Objective-C/Swift
|
||||
- [`KT-43599`](https://youtrack.jetbrains.com/issue/KT-43599) K/N: Unbound symbols not allowed
|
||||
|
||||
### Native. Platform libraries
|
||||
|
||||
- [`KT-43597`](https://youtrack.jetbrains.com/issue/KT-43597) Support for Xcode 12.2 SDK
|
||||
|
||||
### Native. Platforms
|
||||
|
||||
- [`KT-43276`](https://youtrack.jetbrains.com/issue/KT-43276) Support watchos_x64 target
|
||||
|
||||
### Native. Runtime
|
||||
|
||||
- [`KT-42822`](https://youtrack.jetbrains.com/issue/KT-42822) Kotlin/Native Worker leaks ObjC/Swift autorelease references (and indirectly bridged K/N references) on Darwin targets
|
||||
|
||||
### Native. Stdlib
|
||||
|
||||
- [`KT-42172`](https://youtrack.jetbrains.com/issue/KT-42172) Kotlin/Native: StableRef.dispose race condition on Kotlin deinitRuntime
|
||||
- [`KT-42428`](https://youtrack.jetbrains.com/issue/KT-42428) Inconsistent behavior of map.entries on Kotlin.Native
|
||||
|
||||
### Reflection
|
||||
|
||||
- [`KT-34024`](https://youtrack.jetbrains.com/issue/KT-34024) "KotlinReflectionInternalError: Inconsistent number of parameters" with `javaMethod` on suspending functions with inline class in function signature or inside the function
|
||||
|
||||
### Tools. CLI
|
||||
|
||||
- [`KT-43294`](https://youtrack.jetbrains.com/issue/KT-43294) Support `-no-stdlib` option for the `kotlin` runner
|
||||
- [`KT-43406`](https://youtrack.jetbrains.com/issue/KT-43406) JVM: produce deterministic jar files if -d option value is a .jar file
|
||||
|
||||
### Tools. CLI. Native
|
||||
|
||||
- [`KT-40670`](https://youtrack.jetbrains.com/issue/KT-40670) Allow to override konan.properties via CLI
|
||||
|
||||
### Tools. Compiler Plugins
|
||||
|
||||
- [`KT-41764`](https://youtrack.jetbrains.com/issue/KT-41764) KJS /IR IllegalStateException: "Symbol for public kotlin/arrayOf is unbound" with serialization plugin
|
||||
- [`KT-42976`](https://youtrack.jetbrains.com/issue/KT-42976) kotlinx.serialization + JVM IR: NPE on annotation with @SerialInfo
|
||||
- [`KT-43725`](https://youtrack.jetbrains.com/issue/KT-43725) Prohibit inner and local classes in kotlin-noarg
|
||||
|
||||
### Tools. Gradle
|
||||
|
||||
- [`KT-38692`](https://youtrack.jetbrains.com/issue/KT-38692) KaptGenerateStubs Gradle task will not clean up outputs when sources are empty and not an incremental build
|
||||
- [`KT-40140`](https://youtrack.jetbrains.com/issue/KT-40140) kotlin-android plugin eagerly creates several Gradle tasks
|
||||
- [`KT-41295`](https://youtrack.jetbrains.com/issue/KT-41295) Kotlin Gradle Plugin 1.4.20 Configuration Caching bug due to friendPath provider
|
||||
- [`KT-42058`](https://youtrack.jetbrains.com/issue/KT-42058) Support moduleName option in Kotlin Gradle plugin for JVM
|
||||
- [`KT-43054`](https://youtrack.jetbrains.com/issue/KT-43054) Implementation of `AbstractKotlinTarget#buildAdhocComponentsFromKotlinVariants` breaks configuration caching
|
||||
- [`KT-43489`](https://youtrack.jetbrains.com/issue/KT-43489) Incremental compilation - unable to find history files causing full recompilation
|
||||
- [`KT-43740`](https://youtrack.jetbrains.com/issue/KT-43740) Gradle out-of-process runner fails with unclear diagnostics if build directory does not exist
|
||||
- [`KT-43895`](https://youtrack.jetbrains.com/issue/KT-43895) Fix cacheability warnings for the Kotlin plugins
|
||||
|
||||
### Tools. Gradle. JS
|
||||
|
||||
- [`KT-42400`](https://youtrack.jetbrains.com/issue/KT-42400) Kotlin/JS: Gradle DSL: customField() is rejected in Groovy build.gradle
|
||||
- [`KT-42462`](https://youtrack.jetbrains.com/issue/KT-42462) NPM dependency declaration with Groovy interpolated string
|
||||
- [`KT-42954`](https://youtrack.jetbrains.com/issue/KT-42954) Kotlin/JS: IDE import after changing `kotlin.js.externals.output.format` does not re-generate externals
|
||||
- [`KT-43535`](https://youtrack.jetbrains.com/issue/KT-43535) Common webpack configuration breaks on lambda serialization in some cases
|
||||
- [`KT-43668`](https://youtrack.jetbrains.com/issue/KT-43668) PackageJson task use file dependencies as is (files and directories), but only files necessary
|
||||
- [`KT-43793`](https://youtrack.jetbrains.com/issue/KT-43793) nodeArgs in NodeJsExec task
|
||||
- [`KT-43842`](https://youtrack.jetbrains.com/issue/KT-43842) KJS: Invalid `output.library` support for `null` value
|
||||
- [`KT-44104`](https://youtrack.jetbrains.com/issue/KT-44104) KJS / Gradle: An ability to pass jvm args to K2JSDce process
|
||||
|
||||
### Tools. Gradle. Multiplatform
|
||||
|
||||
- [`KT-42269`](https://youtrack.jetbrains.com/issue/KT-42269) Setup default dependsOn edges for Android source sets
|
||||
- [`KT-42413`](https://youtrack.jetbrains.com/issue/KT-42413) [MPP/gradle] `withJava` breaks build on 1.4.20-M1
|
||||
- [`KT-43141`](https://youtrack.jetbrains.com/issue/KT-43141) Gradle / Configuration cache: NPE from org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon.getKotlinOptions() on reusing configuration cache for task compileCommonMainKotlinMetadata
|
||||
- [`KT-43329`](https://youtrack.jetbrains.com/issue/KT-43329) Gradle / Configuration cache: IAE “Parameter specified as non-null is null: method KotlinMetadataTargetConfiguratorKt.isCompatibilityMetadataVariantEnabled, parameter $this$isCompatibilityMetadataVariantEnabled” on reusing configuration cache for task compileKotlinMetadata
|
||||
- [`KT-44298`](https://youtrack.jetbrains.com/issue/KT-44298) Kotlin 1.4.20+ MPP "root" module publication does not include the source JAR that used to be published in the -metadata modules
|
||||
|
||||
### Tools. Gradle. Native
|
||||
|
||||
- [`KT-39564`](https://youtrack.jetbrains.com/issue/KT-39564) Make kotlin-native Gradle tasks Cacheable
|
||||
- [`KT-42485`](https://youtrack.jetbrains.com/issue/KT-42485) Fail on cinterop: clang_indexTranslationUnit returned 1
|
||||
- [`KT-42550`](https://youtrack.jetbrains.com/issue/KT-42550) Adding subspec dependency with git location failed
|
||||
- [`KT-42849`](https://youtrack.jetbrains.com/issue/KT-42849) Gradle / Configuration cache: tasks nativeMetadataJar, runReleaseExecutableNative, runDebugExecutableNative are unsupported and fails on reusing configuration cache
|
||||
- [`KT-42938`](https://youtrack.jetbrains.com/issue/KT-42938) CocoaPods Gradle plugin: podBuildDependencies doesn't properly report xcodebuild failures
|
||||
- [`KT-43151`](https://youtrack.jetbrains.com/issue/KT-43151) Gradle / Configuration cache: UPAE “lateinit property binary has not been initialized” on reusing configuration cache for linkDebugExecutableNative, linkDebugTestNative, linkReleaseExecutableNative tasks
|
||||
- [`KT-43516`](https://youtrack.jetbrains.com/issue/KT-43516) Failed to resolve Kotin library [Multiple Multiplatform modules]
|
||||
|
||||
### Tools. Incremental Compile
|
||||
|
||||
- [`KT-42937`](https://youtrack.jetbrains.com/issue/KT-42937) another compilation fail (problem with compilation caches?)
|
||||
|
||||
### Tools. JPS
|
||||
|
||||
- [`KT-39536`](https://youtrack.jetbrains.com/issue/KT-39536) JPS compilation fails with IOException "storage is already closed"
|
||||
|
||||
### Tools. Parcelize
|
||||
|
||||
- [`KT-41553`](https://youtrack.jetbrains.com/issue/KT-41553) JVM IR, Parcelize: IrStarProjectionImpl cannot be cast to class IrTypeProjection
|
||||
|
||||
### Tools. Scripts
|
||||
|
||||
- [`KT-43534`](https://youtrack.jetbrains.com/issue/KT-43534) Allow running "main.kts" script that does not end in a "main.kts" filename (would allow kotlin scripting on GitHub Actions)
|
||||
|
||||
### Tools. kapt
|
||||
|
||||
- [`KT-34340`](https://youtrack.jetbrains.com/issue/KT-34340) Incremental annotation processor recompile all files (only if KAPT enabled).
|
||||
- [`KT-36667`](https://youtrack.jetbrains.com/issue/KT-36667) Kapt: Add a flag to strip kotlin.Metadata() annotations from stubs
|
||||
- [`KT-40493`](https://youtrack.jetbrains.com/issue/KT-40493) KAPT does not support aggregating annotations processors in incremental mode
|
||||
- [`KT-40882`](https://youtrack.jetbrains.com/issue/KT-40882) Kapt stub generation is non-deterministic for incremental compilation
|
||||
- [`KT-41788`](https://youtrack.jetbrains.com/issue/KT-41788) NullPointerException: Random crashes of build using gradle and kapt because of not calling Processor.init()
|
||||
- [`KT-42182`](https://youtrack.jetbrains.com/issue/KT-42182) KAPT: Does not consider generated sources for incremental compilation.
|
||||
|
||||
|
||||
## 1.4.20
|
||||
|
||||
### Android
|
||||
@@ -2822,7 +2387,7 @@
|
||||
|
||||
|
||||
## Recent ChangeLogs:
|
||||
### [ChangeLog-1.3.X](docs/changelogs/ChangeLog-1.3.X.md)
|
||||
### [ChangeLog-1.2.X](docs/changelogs/ChangeLog-1.2.X.md)
|
||||
### [ChangeLog-1.1.X](docs/changelogs/ChangeLog-1.1.X.md)
|
||||
### [ChangeLog-1.0.X](docs/changelogs/ChangeLog-1.0.X.md)
|
||||
### [ChangeLog-1.3.X](ChangeLog-1.3.X.md)
|
||||
### [ChangeLog-1.2.X](ChangeLog-1.2.X.md)
|
||||
### [ChangeLog-1.1.X](ChangeLog-1.1.X.md)
|
||||
### [ChangeLog-1.0.X](ChangeLog-1.0.X.md)
|
||||
12
ReadMe.md
12
ReadMe.md
@@ -2,7 +2,6 @@
|
||||
[](https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_Compiler?branch=%3Cdefault%3E&buildTypeTab=overview&mode=builds)
|
||||
[](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](https://ge.jetbrains.com/scans?search.rootProjectNames=Kotlin)
|
||||
|
||||
# Kotlin Programming Language
|
||||
|
||||
@@ -18,7 +17,6 @@ Some handy links:
|
||||
* [Issue Tracker](https://youtrack.jetbrains.com/issues/KT)
|
||||
* [Forum](https://discuss.kotlinlang.org/)
|
||||
* [Kotlin Blog](https://blog.jetbrains.com/kotlin/)
|
||||
* [Subscribe to Kotlin YouTube channel](https://www.youtube.com/channel/UCP7uiEZIqci43m22KDl0sNw)
|
||||
* [Follow Kotlin on Twitter](https://twitter.com/kotlin)
|
||||
* [Public Slack channel](https://slack.kotlinlang.org/)
|
||||
* [TeamCity CI build](https://teamcity.jetbrains.com/project.html?tab=projectOverview&projectId=Kotlin)
|
||||
@@ -59,8 +57,8 @@ You also can use [Gradle properties](https://docs.gradle.org/current/userguide/b
|
||||
Note: The JDK 6 for MacOS is not available on Oracle's site. You can install it by
|
||||
|
||||
```bash
|
||||
$ brew tap homebrew/cask-versions
|
||||
$ brew install --cask java6
|
||||
$ brew tap caskroom/versions
|
||||
$ brew cask install java6
|
||||
```
|
||||
|
||||
On Windows you might need to add long paths setting to the repo:
|
||||
@@ -109,13 +107,13 @@ Refer to [libraries/ReadMe.md](libraries/ReadMe.md) for details.
|
||||
|
||||
### Building for different versions of IntelliJ IDEA and Android Studio
|
||||
|
||||
Kotlin plugin is intended to work with several recent versions of IntelliJ IDEA and Android Studio. Each platform is allowed to have a different set of features and might provide a slightly different API. Instead of using several parallel Git branches, the project stores everything in a single branch, but files may have counterparts with version extensions (\*.as32, \*.172, \*.181). The primary file is expected to be replaced with its counterpart when targeting a non-default platform.
|
||||
Kotlin plugin is intended to work with several recent versions of IntelliJ IDEA and Android Studio. Each platform is allowed to have a different set of features and might provide a slightly different API. Instead of using several parallel Git branches, project stores everything in a single branch, but files may have counterparts with version extensions (\*.as32, \*.172, \*.181). The primary file is expected to be replaced with its counterpart when targeting non-default platform.
|
||||
|
||||
A More detailed description of this scheme can be found at https://github.com/JetBrains/bunches/blob/master/ReadMe.md.
|
||||
More detailed description of this scheme can be found at https://github.com/JetBrains/bunches/blob/master/ReadMe.md.
|
||||
|
||||
Usually, there's no need to care about multiple platforms as all features are enabled everywhere by default. Additional counterparts should be created if there's an expected difference in behavior or an incompatible API usage is required **and** there's no reasonable workaround to save source compatibility. Kotlin plugin contains a pre-commit check that shows a warning if a file has been updated without its counterparts.
|
||||
|
||||
Development for some particular platform is possible after 'switching' that can be done with the [Bunch Tool](https://github.com/JetBrains/bunches/releases) from the command line.
|
||||
Development for some particular platform is possible after 'switching' that can be done with [Bunch Tool](https://github.com/JetBrains/bunches/releases) from the command line.
|
||||
|
||||
```sh
|
||||
cd kotlin-project-dir
|
||||
|
||||
@@ -16,24 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.ant
|
||||
|
||||
import org.apache.tools.ant.BuildException
|
||||
import org.apache.tools.ant.taskdefs.Execute
|
||||
import org.apache.tools.ant.taskdefs.Redirector
|
||||
import org.apache.tools.ant.types.*
|
||||
import org.apache.tools.ant.types.Path
|
||||
import org.apache.tools.ant.types.Reference
|
||||
import java.io.File.pathSeparator
|
||||
import java.io.File.separator
|
||||
|
||||
class Kotlin2JvmTask : KotlinCompilerBaseTask() {
|
||||
override val compilerFqName = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
|
||||
|
||||
var includeRuntime: Boolean = false
|
||||
var includeRuntime: Boolean = true
|
||||
var moduleName: String? = null
|
||||
|
||||
var noReflect: Boolean = false
|
||||
|
||||
private val cmdl = CommandlineJava()
|
||||
var fork: Boolean = false
|
||||
|
||||
private var compileClasspath: Path? = null
|
||||
|
||||
fun setClasspath(classpath: Path) {
|
||||
@@ -79,47 +73,4 @@ class Kotlin2JvmTask : KotlinCompilerBaseTask() {
|
||||
if (noReflect) args.add("-no-reflect")
|
||||
if (includeRuntime) args.add("-include-runtime")
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
if (!fork)
|
||||
super.execute()
|
||||
else {
|
||||
exec()
|
||||
}
|
||||
}
|
||||
|
||||
private fun exec() {
|
||||
val javaHome = System.getProperty("java.home")
|
||||
val javaBin = javaHome + separator + "bin" + separator + "java"
|
||||
val redirector = Redirector(this)
|
||||
|
||||
fillArguments()
|
||||
|
||||
val command = ArrayList<String>()
|
||||
command.add(javaBin)
|
||||
command.addAll(cmdl.vmCommand.arguments) // jvm args
|
||||
command.add("-Dorg.jetbrains.kotlin.cliMessageRenderer=FullPath") // same MessageRenderer as non-forking mode
|
||||
command.add("-cp")
|
||||
command.add(KotlinAntTaskUtil.compilerJar.canonicalPath)
|
||||
command.add(compilerFqName)
|
||||
command.addAll(args) // compiler args
|
||||
|
||||
// streamHandler: used to handle the input and output streams of the subprocess.
|
||||
// watchdog: a watchdog for the subprocess or <code>null</code> to disable a timeout for the subprocess.
|
||||
// TODO: support timeout for the subprocess
|
||||
val exe = Execute(redirector.createHandler(), null)
|
||||
exe.setAntRun(getProject())
|
||||
exe.commandline = command.toTypedArray()
|
||||
log("Executing command: ${command.joinToString(" ")}", LogLevel.DEBUG.level)
|
||||
log("Compiling ${src!!.list().toList()} => [${output!!.canonicalPath}]")
|
||||
val exitCode = exe.execute()
|
||||
redirector.complete()
|
||||
if (failOnError && exitCode != 0) {
|
||||
throw BuildException("Compile failed; see the compiler error output for details.")
|
||||
}
|
||||
}
|
||||
|
||||
fun createJvmarg(): Commandline.Argument {
|
||||
return cmdl.createVmArgument()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ abstract class KotlinCompilerBaseTask : Task() {
|
||||
fillSpecificArguments()
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
final override fun execute() {
|
||||
fillArguments()
|
||||
|
||||
val compilerClass = KotlinAntTaskUtil.getOrCreateClassLoader().loadClass(compilerFqName)
|
||||
|
||||
@@ -17,6 +17,9 @@ interface BuildMetaInfo {
|
||||
val compilerBuildVersion: String
|
||||
val languageVersionString: String
|
||||
val apiVersionString: String
|
||||
val coroutinesEnable: Boolean
|
||||
val coroutinesWarn: Boolean
|
||||
val coroutinesError: Boolean
|
||||
val multiplatformEnable: Boolean
|
||||
val metadataVersionMajor: Int
|
||||
val metadataVersionMinor: Int
|
||||
@@ -32,6 +35,9 @@ abstract class BuildMetaInfoFactory<T : BuildMetaInfo>(private val metaInfoClass
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
@@ -47,6 +53,9 @@ abstract class BuildMetaInfoFactory<T : BuildMetaInfo>(private val metaInfoClass
|
||||
compilerBuildVersion = KotlinCompilerVersion.VERSION,
|
||||
languageVersionString = languageVersion.versionString,
|
||||
apiVersionString = args.apiVersion ?: languageVersion.versionString,
|
||||
coroutinesEnable = args.coroutinesState == CommonCompilerArguments.ENABLE,
|
||||
coroutinesWarn = args.coroutinesState == CommonCompilerArguments.WARN,
|
||||
coroutinesError = args.coroutinesState == CommonCompilerArguments.ERROR,
|
||||
multiplatformEnable = args.multiPlatform,
|
||||
ownVersion = OWN_VERSION,
|
||||
coroutinesVersion = COROUTINES_VERSION,
|
||||
|
||||
@@ -15,6 +15,9 @@ data class CommonBuildMetaInfo(
|
||||
override val compilerBuildVersion: String,
|
||||
override val languageVersionString: String,
|
||||
override val apiVersionString: String,
|
||||
override val coroutinesEnable: Boolean,
|
||||
override val coroutinesWarn: Boolean,
|
||||
override val coroutinesError: Boolean,
|
||||
override val multiplatformEnable: Boolean,
|
||||
override val metadataVersionMajor: Int,
|
||||
override val metadataVersionMinor: Int,
|
||||
@@ -29,6 +32,9 @@ data class CommonBuildMetaInfo(
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
@@ -41,6 +47,9 @@ data class CommonBuildMetaInfo(
|
||||
compilerBuildVersion = compilerBuildVersion,
|
||||
languageVersionString = languageVersionString,
|
||||
apiVersionString = apiVersionString,
|
||||
coroutinesEnable = coroutinesEnable,
|
||||
coroutinesWarn = coroutinesWarn,
|
||||
coroutinesError = coroutinesError,
|
||||
multiplatformEnable = multiplatformEnable,
|
||||
metadataVersionMajor = metadataVersion.major,
|
||||
metadataVersionMinor = metadataVersion.minor,
|
||||
|
||||
@@ -15,6 +15,9 @@ data class JsBuildMetaInfo(
|
||||
override val compilerBuildVersion: String,
|
||||
override val languageVersionString: String,
|
||||
override val apiVersionString: String,
|
||||
override val coroutinesEnable: Boolean,
|
||||
override val coroutinesWarn: Boolean,
|
||||
override val coroutinesError: Boolean,
|
||||
override val multiplatformEnable: Boolean,
|
||||
override val metadataVersionMajor: Int,
|
||||
override val metadataVersionMinor: Int,
|
||||
@@ -29,6 +32,9 @@ data class JsBuildMetaInfo(
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
@@ -41,6 +47,9 @@ data class JsBuildMetaInfo(
|
||||
compilerBuildVersion = compilerBuildVersion,
|
||||
languageVersionString = languageVersionString,
|
||||
apiVersionString = apiVersionString,
|
||||
coroutinesEnable = coroutinesEnable,
|
||||
coroutinesWarn = coroutinesWarn,
|
||||
coroutinesError = coroutinesError,
|
||||
multiplatformEnable = multiplatformEnable,
|
||||
metadataVersionMajor = metadataVersion.major,
|
||||
metadataVersionMinor = metadataVersion.minor,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmBytecodeBinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,9 @@ data class JvmBuildMetaInfo(
|
||||
override val compilerBuildVersion: String,
|
||||
override val languageVersionString: String,
|
||||
override val apiVersionString: String,
|
||||
override val coroutinesEnable: Boolean,
|
||||
override val coroutinesWarn: Boolean,
|
||||
override val coroutinesError: Boolean,
|
||||
override val multiplatformEnable: Boolean,
|
||||
override val metadataVersionMajor: Int,
|
||||
override val metadataVersionMinor: Int,
|
||||
@@ -43,6 +47,9 @@ data class JvmBuildMetaInfo(
|
||||
compilerBuildVersion: String,
|
||||
languageVersionString: String,
|
||||
apiVersionString: String,
|
||||
coroutinesEnable: Boolean,
|
||||
coroutinesWarn: Boolean,
|
||||
coroutinesError: Boolean,
|
||||
multiplatformEnable: Boolean,
|
||||
ownVersion: Int,
|
||||
coroutinesVersion: Int,
|
||||
@@ -55,6 +62,9 @@ data class JvmBuildMetaInfo(
|
||||
compilerBuildVersion = compilerBuildVersion,
|
||||
languageVersionString = languageVersionString,
|
||||
apiVersionString = apiVersionString,
|
||||
coroutinesEnable = coroutinesEnable,
|
||||
coroutinesWarn = coroutinesWarn,
|
||||
coroutinesError = coroutinesError,
|
||||
multiplatformEnable = multiplatformEnable,
|
||||
metadataVersionMajor = metadataVersion.major,
|
||||
metadataVersionMinor = metadataVersion.minor,
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.build
|
||||
|
||||
/**
|
||||
* Bytecode version was in the Kotlin metadata ([Metadata.bytecodeVersion]) since 1.0, but it was never used meaningfully in the compiler,
|
||||
* outside of one very special case regarding experimental coroutines, which is now obsolete. It is still used in incremental compilation
|
||||
* caches though. We should probably just pretend that the bytecode version of any Kotlin file from now on is equal to the latest observed
|
||||
* bytecode version, `1.0.3` (see [INSTANCE]).
|
||||
*/
|
||||
class JvmBytecodeBinaryVersion(vararg numbers: Int) {
|
||||
val major: Int = numbers.getOrNull(0) ?: -1
|
||||
val minor: Int = numbers.getOrNull(1) ?: -1
|
||||
val patch: Int = numbers.getOrNull(2) ?: -1
|
||||
|
||||
override fun toString(): String = buildString {
|
||||
append(major)
|
||||
if (minor != -1) {
|
||||
append(".$minor")
|
||||
if (patch != -1) append(".$patch")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val INSTANCE = JvmBytecodeBinaryVersion(1, 0, 3)
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.incremental
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.supertypes
|
||||
@@ -35,15 +34,12 @@ interface IncrementalCacheCommon {
|
||||
val thisWithDependentCaches: Iterable<AbstractIncrementalCache<*>>
|
||||
fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName>
|
||||
fun getSubtypesOf(className: FqName): Sequence<FqName>
|
||||
fun getSupertypesOf(className: FqName): Sequence<FqName>
|
||||
fun getSourceFileIfClass(fqName: FqName): File?
|
||||
fun markDirty(removedAndCompiledSources: Collection<File>)
|
||||
fun clearCacheForRemovedClasses(changesCollector: ChangesCollector)
|
||||
fun getComplementaryFilesRecursive(dirtyFiles: Collection<File>): Collection<File>
|
||||
fun updateComplementaryFiles(dirtyFiles: Collection<File>, expectActualTracker: ExpectActualTrackerImpl)
|
||||
fun dump(): String
|
||||
|
||||
fun isSealed(className: FqName): Boolean?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +50,6 @@ abstract class AbstractIncrementalCache<ClassName>(
|
||||
protected val pathConverter: FileToPathConverter
|
||||
) : BasicMapsOwner(workingDir), IncrementalCacheCommon {
|
||||
companion object {
|
||||
private val CLASS_ATTRIBUTES = "class-attributes"
|
||||
private val SUBTYPES = "subtypes"
|
||||
private val SUPERTYPES = "supertypes"
|
||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||
@@ -76,7 +71,6 @@ abstract class AbstractIncrementalCache<ClassName>(
|
||||
result
|
||||
}
|
||||
|
||||
internal val classAttributesMap = registerMap(ClassAttributesMap(CLASS_ATTRIBUTES.storageFile))
|
||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile, pathConverter))
|
||||
@@ -96,14 +90,6 @@ abstract class AbstractIncrementalCache<ClassName>(
|
||||
override fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||
subtypesMap[className].asSequence()
|
||||
|
||||
override fun getSupertypesOf(className: FqName): Sequence<FqName> {
|
||||
return supertypesMap[className].asSequence()
|
||||
}
|
||||
|
||||
override fun isSealed(className: FqName): Boolean? {
|
||||
return classAttributesMap[className]?.isSealed
|
||||
}
|
||||
|
||||
override fun getSourceFileIfClass(fqName: FqName): File? =
|
||||
classFqNameToSourceMap[fqName]
|
||||
|
||||
@@ -132,7 +118,6 @@ abstract class AbstractIncrementalCache<ClassName>(
|
||||
|
||||
supertypesMap[child] = parents
|
||||
classFqNameToSourceMap[child] = srcFile
|
||||
classAttributesMap[child] = ICClassesAttributes(ProtoBuf.Modality.SEALED == Flags.MODALITY.get(proto.flags))
|
||||
}
|
||||
|
||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>, changesCollector: ChangesCollector) {
|
||||
@@ -167,17 +152,14 @@ abstract class AbstractIncrementalCache<ClassName>(
|
||||
}
|
||||
}
|
||||
|
||||
removedFqNames.forEach {
|
||||
classFqNameToSourceMap.remove(it)
|
||||
classAttributesMap.remove(it)
|
||||
}
|
||||
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
|
||||
}
|
||||
|
||||
protected class ClassFqNameToSourceMap(
|
||||
storageFile: File,
|
||||
private val pathConverter: FileToPathConverter
|
||||
) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
||||
|
||||
) :
|
||||
BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
||||
operator fun set(fqName: FqName, sourceFile: File) {
|
||||
storage[fqName.asString()] = pathConverter.toPath(sourceFile)
|
||||
}
|
||||
|
||||
@@ -19,14 +19,12 @@ package org.jetbrains.kotlin.incremental
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.supertypes
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
|
||||
class ChangesCollector {
|
||||
private val removedMembers = hashMapOf<FqName, MutableSet<String>>()
|
||||
private val changedParents = hashMapOf<FqName, MutableSet<FqName>>()
|
||||
private val changedMembers = hashMapOf<FqName, MutableSet<String>>()
|
||||
private val areSubclassesAffected = hashMapOf<FqName, Boolean>()
|
||||
|
||||
@@ -49,10 +47,6 @@ class ChangesCollector {
|
||||
changes.add(ChangeInfo.SignatureChanged(fqName, areSubclassesAffected))
|
||||
}
|
||||
|
||||
for ((fqName, changedParents) in changedParents) {
|
||||
changes.add(ChangeInfo.ParentsChanged(fqName, changedParents))
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
@@ -85,12 +79,12 @@ class ChangesCollector {
|
||||
}
|
||||
|
||||
if (oldData == null) {
|
||||
newData!!.collectAll(isRemoved = false, isAdded = true, collectAllMembersForNewClass = collectAllMembersForNewClass)
|
||||
newData!!.collectAll(isRemoved = false, collectAllMembersForNewClass = collectAllMembersForNewClass)
|
||||
return
|
||||
}
|
||||
|
||||
if (newData == null) {
|
||||
oldData.collectAll(isRemoved = true, isAdded = false)
|
||||
oldData.collectAll(isRemoved = true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -104,7 +98,6 @@ class ChangesCollector {
|
||||
collectSignature(oldData, diff.areSubclassesAffected)
|
||||
}
|
||||
collectChangedMembers(fqName, diff.changedMembersNames)
|
||||
addChangedParents(fqName, diff.changedSupertypes)
|
||||
}
|
||||
is PackagePartProtoData -> {
|
||||
collectSignature(oldData, areSubclassesAffected = true)
|
||||
@@ -128,11 +121,10 @@ class ChangesCollector {
|
||||
private fun <T> T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List<MessageLite>): Set<String> =
|
||||
members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet()
|
||||
|
||||
//TODO remember all sealed parent classes
|
||||
private fun ProtoData.collectAll(isRemoved: Boolean, isAdded: Boolean, collectAllMembersForNewClass: Boolean = false) =
|
||||
private fun ProtoData.collectAll(isRemoved: Boolean, collectAllMembersForNewClass: Boolean = false) =
|
||||
when (this) {
|
||||
is PackagePartProtoData -> collectAllFromPackage(isRemoved)
|
||||
is ClassProtoData -> collectAllFromClass(isRemoved, isAdded, collectAllMembersForNewClass)
|
||||
is ClassProtoData -> collectAllFromClass(isRemoved, collectAllMembersForNewClass)
|
||||
}
|
||||
|
||||
private fun PackagePartProtoData.collectAllFromPackage(isRemoved: Boolean) {
|
||||
@@ -151,7 +143,7 @@ class ChangesCollector {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean, isAdded: Boolean, collectAllMembersForNewClass: Boolean = false) {
|
||||
private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean, collectAllMembersForNewClass: Boolean = false) {
|
||||
val classFqName = nameResolver.getClassId(proto.fqName).asSingleFqName()
|
||||
val kind = Flags.CLASS_KIND.get(proto.flags)
|
||||
|
||||
@@ -170,23 +162,6 @@ class ChangesCollector {
|
||||
|
||||
collectSignature(classFqName, areSubclassesAffected = true)
|
||||
}
|
||||
|
||||
if (isRemoved || isAdded) {
|
||||
collectChangedParents(classFqName, proto.supertypeList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addChangedParents(fqName: FqName, parents: Collection<FqName>) {
|
||||
if (parents.isNotEmpty()) {
|
||||
changedParents.getOrPut(fqName) { HashSet() }.addAll(parents)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassProtoData.collectChangedParents(fqName: FqName, parents: Collection<ProtoBuf.Type>) {
|
||||
val changedParentsFqNames = parents.map { type ->
|
||||
nameResolver.getClassId(type.className).asSingleFqName()
|
||||
}
|
||||
addChangedParents(fqName, changedParentsFqNames)
|
||||
}
|
||||
|
||||
private fun ClassProtoData.getNonPrivateMemberNames(): Set<String> {
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.name.parentOrNull
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
@@ -327,7 +326,7 @@ private class ProtoDataProvider(private val serializerProtocol: SerializerExtens
|
||||
proto.`package`.apply {
|
||||
val packageNameId = getExtensionOrNull(serializerProtocol.packageFqName)
|
||||
val packageFqName = packageNameId?.let { FqName(nameResolver.getPackageFqName(it)) } ?: FqName.ROOT
|
||||
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalizeAsciiOnly() + "Kt"))
|
||||
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalize() + "Kt"))
|
||||
classes[packagePartClassId] = PackagePartProtoData(this, nameResolver, packageFqName)
|
||||
}
|
||||
|
||||
@@ -348,7 +347,7 @@ fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData>
|
||||
|
||||
proto.`package`.apply {
|
||||
val packageFqName = getExtensionOrNull(JsProtoBuf.packageFqName)?.let(nameResolver::getPackageFqName)?.let(::FqName) ?: FqName.ROOT
|
||||
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalizeAsciiOnly() + "Kt"))
|
||||
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalize() + "Kt"))
|
||||
classes[packagePartClassId] = PackagePartProtoData(this, nameResolver, packageFqName)
|
||||
}
|
||||
|
||||
@@ -413,4 +412,4 @@ private class PackageMetadataMap(storageFile: File) : BasicStringMap<ByteArray>(
|
||||
operator fun get(packageName: String) = storage[packageName]
|
||||
|
||||
override fun dumpValue(value: ByteArray): String = "Package metadata: ${value.md5()}"
|
||||
}
|
||||
}
|
||||
@@ -94,10 +94,6 @@ open class IncrementalJvmCache(
|
||||
fun sourcesByInternalName(internalName: String): Collection<File> =
|
||||
internalNameToSource[internalName]
|
||||
|
||||
fun getAllPartsOfMultifileFacade(facade: JvmClassName): Collection<String>? {
|
||||
return multifileFacadeToParts[facade]
|
||||
}
|
||||
|
||||
fun isMultifileFacade(className: JvmClassName): Boolean =
|
||||
className in multifileFacadeToParts
|
||||
|
||||
@@ -149,7 +145,6 @@ open class IncrementalJvmCache(
|
||||
}
|
||||
protoMap.remove(className, changesCollector)
|
||||
classFqNameToSourceMap.remove(className.fqNameForClassNameWithoutDollars)
|
||||
classAttributesMap.remove(className.fqNameForClassNameWithoutDollars)
|
||||
internalNameToSource.remove(className.internalName)
|
||||
|
||||
// TODO NO_CHANGES? (delegates only)
|
||||
@@ -276,7 +271,6 @@ open class IncrementalJvmCache(
|
||||
|
||||
private inner class ProtoMap(storageFile: File) : BasicStringMap<ProtoMapValue>(storageFile, ProtoMapValueExternalizer) {
|
||||
|
||||
@Synchronized
|
||||
fun process(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
return put(kotlinClass, changesCollector)
|
||||
}
|
||||
@@ -288,12 +282,10 @@ open class IncrementalJvmCache(
|
||||
// from files compiled during last round.
|
||||
// However there is no need to compare old and new data in this case
|
||||
// (also that would fail with exception).
|
||||
@Synchronized
|
||||
fun storeModuleMapping(className: JvmClassName, bytes: ByteArray) {
|
||||
storage[className.internalName] = ProtoMapValue(isPackageFacade = false, bytes = bytes, strings = emptyArray())
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun put(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
val header = kotlinClass.classHeader
|
||||
|
||||
@@ -316,7 +308,6 @@ open class IncrementalJvmCache(
|
||||
operator fun get(className: JvmClassName): ProtoMapValue? =
|
||||
storage[className.internalName]
|
||||
|
||||
@Synchronized
|
||||
fun remove(className: JvmClassName, changesCollector: ChangesCollector) {
|
||||
val key = className.internalName
|
||||
val oldValue = storage[key] ?: return
|
||||
@@ -333,8 +324,6 @@ open class IncrementalJvmCache(
|
||||
|
||||
private inner class JavaSourcesProtoMap(storageFile: File) :
|
||||
BasicStringMap<SerializedJavaClass>(storageFile, JavaClassProtoMapValueExternalizer) {
|
||||
|
||||
@Synchronized
|
||||
fun process(jvmClassName: JvmClassName, newData: SerializedJavaClass, changesCollector: ChangesCollector) {
|
||||
val key = jvmClassName.internalName
|
||||
val oldData = storage[key]
|
||||
@@ -346,7 +335,6 @@ open class IncrementalJvmCache(
|
||||
)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun remove(className: JvmClassName, changesCollector: ChangesCollector) {
|
||||
val key = className.internalName
|
||||
val oldValue = storage[key] ?: return
|
||||
@@ -386,7 +374,6 @@ open class IncrementalJvmCache(
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
@Synchronized
|
||||
fun process(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
val key = kotlinClass.className.internalName
|
||||
val oldMap = storage[key] ?: emptyMap()
|
||||
@@ -403,7 +390,6 @@ open class IncrementalJvmCache(
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
@@ -429,8 +415,6 @@ open class IncrementalJvmCache(
|
||||
|
||||
private inner class MultifileClassFacadeMap(storageFile: File) :
|
||||
BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||
|
||||
@Synchronized
|
||||
operator fun set(className: JvmClassName, partNames: Collection<String>) {
|
||||
storage[className.internalName] = partNames
|
||||
}
|
||||
@@ -441,7 +425,6 @@ open class IncrementalJvmCache(
|
||||
operator fun contains(className: JvmClassName): Boolean =
|
||||
className.internalName in storage
|
||||
|
||||
@Synchronized
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
@@ -451,8 +434,6 @@ open class IncrementalJvmCache(
|
||||
|
||||
private inner class MultifileClassPartMap(storageFile: File) :
|
||||
BasicStringMap<String>(storageFile, EnumeratorStringDescriptor.INSTANCE) {
|
||||
|
||||
@Synchronized
|
||||
fun set(partName: String, facadeName: String) {
|
||||
storage[partName] = facadeName
|
||||
}
|
||||
@@ -460,7 +441,6 @@ open class IncrementalJvmCache(
|
||||
fun get(partName: JvmClassName): String? =
|
||||
storage[partName.internalName]
|
||||
|
||||
@Synchronized
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
@@ -542,7 +522,6 @@ open class IncrementalJvmCache(
|
||||
return result
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun process(kotlinClass: LocalFileKotlinClass, changesCollector: ChangesCollector) {
|
||||
val key = kotlinClass.className.internalName
|
||||
val oldMap = storage[key] ?: emptyMap()
|
||||
@@ -568,7 +547,6 @@ open class IncrementalJvmCache(
|
||||
private fun functionNameBySignature(signature: String): String =
|
||||
signature.substringBefore("(")
|
||||
|
||||
@Synchronized
|
||||
fun remove(className: JvmClassName) {
|
||||
storage.remove(className.internalName)
|
||||
}
|
||||
@@ -590,7 +568,6 @@ sealed class ChangeInfo(val fqName: FqName) {
|
||||
|
||||
class SignatureChanged(fqName: FqName, val areSubclassesAffected: Boolean) : ChangeInfo(fqName)
|
||||
|
||||
class ParentsChanged(fqName: FqName, val parentsChanged: Collection<FqName>) : ChangeInfo(fqName)
|
||||
|
||||
protected open fun toStringProperties(): String = "fqName = $fqName"
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ data class IncrementalModuleEntry(
|
||||
|
||||
class IncrementalModuleInfo(
|
||||
val projectRoot: File,
|
||||
val rootProjectBuildDir: File,
|
||||
val dirToModule: Map<File, IncrementalModuleEntry>,
|
||||
val nameToModules: Map<String, Set<IncrementalModuleEntry>>,
|
||||
val jarToClassListFile: Map<File, File>,
|
||||
@@ -29,6 +28,6 @@ class IncrementalModuleInfo(
|
||||
val jarToModule: Map<File, IncrementalModuleEntry>
|
||||
) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID = 1L
|
||||
private const val serialVersionUID = 0L
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,19 @@
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.util.containers.StringInterner
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.components.Position
|
||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||
import org.jetbrains.kotlin.incremental.storage.*
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.createStringInterner
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
|
||||
open class LookupStorage(
|
||||
targetDataDir: File,
|
||||
pathConverter: FileToPathConverter
|
||||
@@ -211,8 +212,8 @@ open class LookupStorage(
|
||||
|
||||
class LookupTrackerImpl(private val delegate: LookupTracker) : LookupTracker {
|
||||
val lookups = MultiMap.createSet<LookupSymbol, String>()
|
||||
val pathInterner = createStringInterner()
|
||||
private val interner = createStringInterner()
|
||||
val pathInterner = StringInterner()
|
||||
private val interner = StringInterner()
|
||||
|
||||
override val requiresPosition: Boolean
|
||||
get() = delegate.requiresPosition
|
||||
|
||||
@@ -136,8 +136,7 @@ fun LookupStorage.update(
|
||||
|
||||
data class DirtyData(
|
||||
val dirtyLookupSymbols: Collection<LookupSymbol> = emptyList(),
|
||||
val dirtyClassesFqNames: Collection<FqName> = emptyList(),
|
||||
val dirtyClassesFqNamesForceRecompile: Collection<FqName> = emptyList()
|
||||
val dirtyClassesFqNames: Collection<FqName> = emptyList()
|
||||
)
|
||||
|
||||
fun ChangesCollector.getDirtyData(
|
||||
@@ -147,9 +146,6 @@ fun ChangesCollector.getDirtyData(
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
val dirtyClassesFqNames = HashSet<FqName>()
|
||||
|
||||
val sealedParents = HashMap<FqName, MutableSet<FqName>>()
|
||||
val notSealedParents = HashSet<FqName>()
|
||||
|
||||
for (change in changes()) {
|
||||
reporter.reportVerbose { "Process $change" }
|
||||
|
||||
@@ -174,35 +170,10 @@ fun ChangesCollector.getDirtyData(
|
||||
}
|
||||
|
||||
fqNames.mapTo(dirtyLookupSymbols) { LookupSymbol(SAM_LOOKUP_NAME.asString(), it.asString()) }
|
||||
} else if (change is ChangeInfo.ParentsChanged) {
|
||||
fun FqName.isSealed(): Boolean {
|
||||
if (notSealedParents.contains(this)) return false
|
||||
if (sealedParents.containsKey(this)) return true
|
||||
return isSealed(this, caches).also { sealed ->
|
||||
if (sealed) {
|
||||
sealedParents[this] = HashSet()
|
||||
} else {
|
||||
notSealedParents.add(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
change.parentsChanged.forEach { parent ->
|
||||
if (parent.isSealed()) {
|
||||
sealedParents.getOrPut(parent) { HashSet() }.add(change.fqName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val forceRecompile = HashSet<FqName>().apply {
|
||||
addAll(sealedParents.keys)
|
||||
//we should recompile all inheritors with parent sealed class: add known subtypes
|
||||
addAll(sealedParents.keys.flatMap { withSubtypes(it, caches) })
|
||||
//we should recompile all inheritors with parent sealed class: add new subtypes
|
||||
addAll(sealedParents.values.flatten())
|
||||
}
|
||||
|
||||
return DirtyData(dirtyLookupSymbols, dirtyClassesFqNames, forceRecompile)
|
||||
return DirtyData(dirtyLookupSymbols, dirtyClassesFqNames)
|
||||
}
|
||||
|
||||
fun mapLookupSymbolsToFiles(
|
||||
@@ -246,11 +217,6 @@ fun mapClassesFqNamesToFiles(
|
||||
return fqNameToAffectedFiles.values.flattenTo(HashSet())
|
||||
}
|
||||
|
||||
fun isSealed(
|
||||
fqName: FqName,
|
||||
caches: Iterable<IncrementalCacheCommon>
|
||||
): Boolean = caches.any { it.isSealed(fqName) ?: false }
|
||||
|
||||
fun withSubtypes(
|
||||
typeFqName: FqName,
|
||||
caches: Iterable<IncrementalCacheCommon>
|
||||
|
||||
@@ -28,14 +28,12 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptorVisibility
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import java.util.*
|
||||
|
||||
data class Difference(
|
||||
val isClassAffected: Boolean = false,
|
||||
val areSubclassesAffected: Boolean = false,
|
||||
val changedMembersNames: Set<String> = emptySet(),
|
||||
val changedSupertypes: Set<FqName> = emptySet()
|
||||
val changedMembersNames: Set<String> = emptySet()
|
||||
)
|
||||
|
||||
sealed class ProtoData
|
||||
@@ -189,7 +187,6 @@ class DifferenceCalculatorForClass(
|
||||
|
||||
var isClassAffected = false
|
||||
var areSubclassesAffected = false
|
||||
val changedSupertypes = HashSet<FqName>()
|
||||
val names = hashSetOf<String>()
|
||||
val classIsSealed = newProto.isSealed && oldProto.isSealed
|
||||
|
||||
@@ -250,21 +247,12 @@ class DifferenceCalculatorForClass(
|
||||
ProtoBufClassKind.FLAGS,
|
||||
ProtoBufClassKind.FQ_NAME,
|
||||
ProtoBufClassKind.TYPE_PARAMETER_LIST,
|
||||
ProtoBufClassKind.SUPERTYPE_LIST,
|
||||
ProtoBufClassKind.SUPERTYPE_ID_LIST,
|
||||
ProtoBufClassKind.JS_EXT_CLASS_ANNOTATION_LIST -> {
|
||||
isClassAffected = true
|
||||
areSubclassesAffected = true
|
||||
}
|
||||
|
||||
ProtoBufClassKind.SUPERTYPE_LIST,
|
||||
ProtoBufClassKind.SUPERTYPE_ID_LIST -> {
|
||||
isClassAffected = true
|
||||
areSubclassesAffected = true
|
||||
|
||||
val oldSupertypes = oldProto.supertypeList.map { oldNameResolver.getClassId(it.className).asSingleFqName() }
|
||||
val newSupertypes = newProto.supertypeList.map { newNameResolver.getClassId(it.className).asSingleFqName() }
|
||||
val changed = (oldSupertypes union newSupertypes) subtract (oldSupertypes intersect newSupertypes)
|
||||
changedSupertypes.addAll(changed)
|
||||
}
|
||||
ProtoBufClassKind.JVM_EXT_CLASS_MODULE_NAME,
|
||||
ProtoBufClassKind.JS_EXT_CLASS_CONTAINING_FILE_ID -> {
|
||||
// TODO
|
||||
@@ -293,7 +281,7 @@ class DifferenceCalculatorForClass(
|
||||
}
|
||||
}
|
||||
|
||||
return Difference(isClassAffected, areSubclassesAffected, names, changedSupertypes)
|
||||
return Difference(isClassAffected, areSubclassesAffected, names)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ open class BasicMapsOwner(val cachesDir: File) {
|
||||
protected val String.storageFile: File
|
||||
get() = File(cachesDir, this + "." + CACHE_EXTENSION)
|
||||
|
||||
@Synchronized
|
||||
protected fun <K, V, M : BasicMap<K, V>> registerMap(map: M): M {
|
||||
maps.add(map)
|
||||
return map
|
||||
@@ -48,7 +47,6 @@ open class BasicMapsOwner(val cachesDir: File) {
|
||||
forEachMapSafe("flush") { it.flush(memoryCachesOnly) }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun forEachMapSafe(actionName: String, action: (BasicMap<*, *>) -> Unit) {
|
||||
val actionExceptions = LinkedHashMap<String, Exception>()
|
||||
maps.forEach {
|
||||
@@ -68,6 +66,5 @@ open class BasicMapsOwner(val cachesDir: File) {
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@Synchronized
|
||||
fun dump(): String = maps.joinToString("\n\n") { it.dump() }
|
||||
}
|
||||
@@ -17,11 +17,9 @@
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.IOUtil
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import com.intellij.util.io.PersistentHashMap
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
/**
|
||||
@@ -32,6 +30,7 @@ class CachingLazyStorage<K, V>(
|
||||
private val keyDescriptor: KeyDescriptor<K>,
|
||||
private val valueExternalizer: DataExternalizer<V>
|
||||
) : LazyStorage<K, V> {
|
||||
@Volatile
|
||||
private var storage: PersistentHashMap<K, V>? = null
|
||||
|
||||
@Synchronized
|
||||
@@ -81,10 +80,8 @@ class CachingLazyStorage<K, V>(
|
||||
try {
|
||||
storage?.close()
|
||||
} finally {
|
||||
PersistentHashMap.deleteFilesStartingWith(storageFile)
|
||||
storage = null
|
||||
if (!IOUtil.deleteAllFilesStartingWith(storageFile)) {
|
||||
throw IOException("Could not delete internal storage: ${storageFile.absolutePath}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.io.File
|
||||
|
||||
internal data class ICClassesAttributes(val isSealed: Boolean)
|
||||
|
||||
internal object ICClassesAttributesExternalizer : DataExternalizer<ICClassesAttributes> {
|
||||
override fun read(input: DataInput): ICClassesAttributes {
|
||||
return ICClassesAttributes(input.readBoolean())
|
||||
}
|
||||
|
||||
override fun save(output: DataOutput, value: ICClassesAttributes) {
|
||||
output.writeBoolean(value.isSealed)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class ClassAttributesMap(
|
||||
storageFile: File
|
||||
) : BasicStringMap<ICClassesAttributes>(storageFile, ICClassesAttributesExternalizer) {
|
||||
override fun dumpValue(value: ICClassesAttributes): String = value.toString()
|
||||
|
||||
operator fun set(key: FqName, value: ICClassesAttributes) {
|
||||
storage[key.asString()] = value
|
||||
}
|
||||
|
||||
operator fun get(key: FqName): ICClassesAttributes? = storage[key.asString()]
|
||||
|
||||
fun remove(key: FqName) {
|
||||
storage.remove(key.asString())
|
||||
}
|
||||
}
|
||||
@@ -20,18 +20,18 @@ import org.jetbrains.kotlin.incremental.dumpCollection
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.File
|
||||
|
||||
internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||
internal open class ClassOneToManyMap(
|
||||
storageFile: File
|
||||
) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
||||
|
||||
@Synchronized
|
||||
fun add(key: FqName, value: FqName) {
|
||||
storage.append(key.asString(), listOf(value.asString()))
|
||||
}
|
||||
|
||||
operator fun get(key: FqName): Collection<FqName> =
|
||||
storage[key.asString()]?.map(::FqName) ?: setOf()
|
||||
storage[key.asString()]?.map(::FqName) ?: setOf()
|
||||
|
||||
@Synchronized
|
||||
operator fun set(key: FqName, values: Collection<FqName>) {
|
||||
if (values.isEmpty()) {
|
||||
remove(key)
|
||||
@@ -41,14 +41,10 @@ internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collec
|
||||
storage[key.asString()] = values.map(FqName::asString)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun remove(key: FqName) {
|
||||
storage.remove(key.asString())
|
||||
}
|
||||
|
||||
// Access to caches could be done from multiple threads (e.g. JPS worker and RMI). The underlying collection is already synchronized,
|
||||
// thus we need synchronization of this method and all modification methods.
|
||||
@Synchronized
|
||||
fun removeValues(key: FqName, removed: Set<FqName>) {
|
||||
val notRemoved = this[key].filter { it !in removed }
|
||||
this[key] = notRemoved
|
||||
|
||||
@@ -25,7 +25,8 @@ internal class DirtyClassesJvmNameMap(storageFile: File) : AbstractDirtyClassesM
|
||||
internal class DirtyClassesFqNameMap(storageFile: File) : AbstractDirtyClassesMap<FqName>(FqNameTransformer, storageFile)
|
||||
|
||||
internal abstract class AbstractDirtyClassesMap<Name>(
|
||||
private val nameTransformer: NameTransformer<Name>, storageFile: File
|
||||
private val nameTransformer: NameTransformer<Name>,
|
||||
storageFile: File
|
||||
) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||
fun markDirty(className: Name) {
|
||||
storage[nameTransformer.asString(className)] = true
|
||||
@@ -36,10 +37,10 @@ internal abstract class AbstractDirtyClassesMap<Name>(
|
||||
}
|
||||
|
||||
fun getDirtyOutputClasses(): Collection<Name> =
|
||||
storage.keys.map { nameTransformer.asName(it) }
|
||||
storage.keys.map { nameTransformer.asName(it) }
|
||||
|
||||
fun isDirty(className: Name): Boolean =
|
||||
storage.contains(nameTransformer.asString(className))
|
||||
storage.contains(nameTransformer.asString(className))
|
||||
|
||||
override fun dumpValue(value: Boolean) = ""
|
||||
}
|
||||
|
||||
@@ -17,11 +17,9 @@
|
||||
package org.jetbrains.kotlin.incremental.storage
|
||||
|
||||
import com.intellij.util.io.DataExternalizer
|
||||
import com.intellij.util.io.IOUtil
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import com.intellij.util.io.PersistentHashMap
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
class NonCachingLazyStorage<K, V>(
|
||||
@@ -29,6 +27,7 @@ class NonCachingLazyStorage<K, V>(
|
||||
private val keyDescriptor: KeyDescriptor<K>,
|
||||
private val valueExternalizer: DataExternalizer<V>
|
||||
) : LazyStorage<K, V> {
|
||||
@Volatile
|
||||
private var storage: PersistentHashMap<K, V>? = null
|
||||
|
||||
@Synchronized
|
||||
@@ -77,12 +76,11 @@ class NonCachingLazyStorage<K, V>(
|
||||
override fun clean() {
|
||||
try {
|
||||
storage?.close()
|
||||
} finally {
|
||||
storage = null
|
||||
if (!IOUtil.deleteAllFilesStartingWith(storageFile)) {
|
||||
throw IOException("Could not delete internal storage: ${storageFile.absolutePath}")
|
||||
}
|
||||
} catch (ignored: Throwable) {
|
||||
}
|
||||
|
||||
PersistentHashMap.deleteFilesStartingWith(storageFile)
|
||||
storage = null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.build
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
@@ -33,7 +34,10 @@ class BuildMetaInfoTest : TestCase() {
|
||||
"bytecodeVersionMinor",
|
||||
"bytecodeVersionPatch",
|
||||
"compilerBuildVersion",
|
||||
"coroutinesEnable",
|
||||
"coroutinesError",
|
||||
"coroutinesVersion",
|
||||
"coroutinesWarn",
|
||||
"isEAP",
|
||||
"languageVersionString",
|
||||
"metadataVersionMajor",
|
||||
@@ -67,12 +71,14 @@ class BuildMetaInfoTest : TestCase() {
|
||||
@Test
|
||||
fun testJvmEquals() {
|
||||
val args1 = K2JVMCompilerArguments()
|
||||
args1.coroutinesState = CommonCompilerArguments.ENABLE
|
||||
val info1 = JvmBuildMetaInfo.create(args1)
|
||||
|
||||
val args2 = K2JVMCompilerArguments()
|
||||
args2.coroutinesState = CommonCompilerArguments.WARN
|
||||
val info2 = JvmBuildMetaInfo.create(args2)
|
||||
|
||||
assertEquals(info1, info2)
|
||||
assertEquals(info1, info2.copy())
|
||||
assertNotEquals(info1, info2)
|
||||
assertEquals(info1, info2.copy(coroutinesEnable = true, coroutinesWarn = false))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ data class BuildLogFinder(
|
||||
private val isDataContainerBuildLogEnabled: Boolean = false,
|
||||
private val isGradleEnabled: Boolean = false,
|
||||
private val isJsEnabled: Boolean = false,
|
||||
private val isScopeExpansionEnabled: Boolean = false,
|
||||
private val isKlibEnabled: Boolean = false
|
||||
private val isJsIrEnabled: Boolean = false, // TODO rename as it is used for metadata-only test
|
||||
private val isScopeExpansionEnabled: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
private const val JS_LOG = "js-build.log"
|
||||
private const val KLIB_LOG = "klib-build.log"
|
||||
private const val JS_IR_LOG = "js-ir-build.log"
|
||||
private const val SCOPE_EXPANDING_LOG = "build-with-scope-expansion.log"
|
||||
private const val GRADLE_LOG = "gradle-build.log"
|
||||
private const val DATA_CONTAINER_LOG = "data-container-version-build.log"
|
||||
@@ -43,7 +43,7 @@ data class BuildLogFinder(
|
||||
val files = names.filter { File(dir, it).isFile }.toSet()
|
||||
val matchedName = when {
|
||||
isScopeExpansionEnabled && SCOPE_EXPANDING_LOG in files -> SCOPE_EXPANDING_LOG
|
||||
isKlibEnabled && KLIB_LOG in files -> KLIB_LOG
|
||||
isJsIrEnabled && JS_IR_LOG in files -> JS_IR_LOG
|
||||
isJsEnabled && JS_LOG in files -> JS_LOG
|
||||
isGradleEnabled && GRADLE_LOG in files -> GRADLE_LOG
|
||||
isJsEnabled && JS_JPS_LOG in files -> JS_JPS_LOG
|
||||
|
||||
@@ -151,35 +151,29 @@ private fun classFileToString(classFile: File): String {
|
||||
val traceVisitor = TraceClassVisitor(PrintWriter(out))
|
||||
ClassReader(classFile.readBytes()).accept(traceVisitor, 0)
|
||||
|
||||
val classHeader = LocalFileKotlinClass.create(classFile)?.classHeader ?: return ""
|
||||
if (!classHeader.metadataVersion.isCompatible()) {
|
||||
error("Incompatible class ($classHeader): $classFile")
|
||||
}
|
||||
val classHeader = LocalFileKotlinClass.create(classFile)?.classHeader
|
||||
|
||||
when (classHeader.kind) {
|
||||
KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.CLASS, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
|
||||
ByteArrayInputStream(BitEncoding.decodeBytes(classHeader.data!!)).use { input ->
|
||||
out.write("\n------ string table types proto -----\n${DebugJvmProtoBuf.StringTableTypes.parseDelimitedFrom(input)}")
|
||||
val annotationDataEncoded = classHeader?.data
|
||||
if (annotationDataEncoded != null) {
|
||||
ByteArrayInputStream(BitEncoding.decodeBytes(annotationDataEncoded)).use {
|
||||
input ->
|
||||
|
||||
when (classHeader.kind) {
|
||||
KotlinClassHeader.Kind.FILE_FACADE ->
|
||||
out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
||||
KotlinClassHeader.Kind.CLASS ->
|
||||
out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ->
|
||||
out.write("\n------ multi-file part proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
||||
else -> error(classHeader.kind)
|
||||
}
|
||||
out.write("\n------ string table types proto -----\n${DebugJvmProtoBuf.StringTableTypes.parseDelimitedFrom(input)}")
|
||||
|
||||
if (!classHeader.metadataVersion.isCompatible()) {
|
||||
error("Incompatible class ($classHeader): $classFile")
|
||||
}
|
||||
|
||||
when (classHeader.kind) {
|
||||
KotlinClassHeader.Kind.FILE_FACADE ->
|
||||
out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
||||
KotlinClassHeader.Kind.CLASS ->
|
||||
out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ->
|
||||
out.write("\n------ multi-file part proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS -> {
|
||||
out.write("\n------ multi-file facade data -----\n")
|
||||
out.write(classHeader.data!!.joinToString("\n"))
|
||||
}
|
||||
KotlinClassHeader.Kind.SYNTHETIC_CLASS -> {
|
||||
// Synthetic class has no metadata, thus there can be no differences in it.
|
||||
}
|
||||
KotlinClassHeader.Kind.UNKNOWN -> error("Should not meet unknown classes here: $classFile")
|
||||
}
|
||||
|
||||
return out.toString()
|
||||
|
||||
100
build.gradle.kts
100
build.gradle.kts
@@ -52,6 +52,7 @@ pill {
|
||||
excludedDirs(
|
||||
"out",
|
||||
"buildSrc/build",
|
||||
"buildSrc/prepare-deps/android-dx/build",
|
||||
"buildSrc/prepare-deps/intellij-sdk/build"
|
||||
)
|
||||
}
|
||||
@@ -73,7 +74,7 @@ val kotlinVersion by extra(
|
||||
} ?: buildNumber
|
||||
)
|
||||
|
||||
val kotlinLanguageVersion by extra("1.5")
|
||||
val kotlinLanguageVersion by extra("1.4")
|
||||
|
||||
allprojects {
|
||||
group = "org.jetbrains.kotlin"
|
||||
@@ -130,7 +131,6 @@ extra["JDK_18"] = jdkPath("1.8")
|
||||
extra["JDK_9"] = jdkPath("9")
|
||||
extra["JDK_10"] = jdkPath("10")
|
||||
extra["JDK_11"] = jdkPath("11")
|
||||
extra["JDK_15"] = jdkPath("15")
|
||||
|
||||
// allow opening the project without setting up all env variables (see KT-26413)
|
||||
if (!kotlinBuildProperties.isInIdeaSync) {
|
||||
@@ -166,12 +166,13 @@ extra["versions.jansi"] = "1.16"
|
||||
extra["versions.jline"] = "3.3.1"
|
||||
extra["versions.junit"] = "4.12"
|
||||
extra["versions.javaslang"] = "2.0.6"
|
||||
extra["versions.ant"] = "1.10.7"
|
||||
extra["versions.ant"] = "1.8.2"
|
||||
extra["versions.android"] = "2.3.1"
|
||||
extra["versions.kotlinx-coroutines-core"] = "1.3.8"
|
||||
extra["versions.kotlinx-coroutines-jdk8"] = "1.3.8"
|
||||
extra["versions.json"] = "20160807"
|
||||
extra["versions.native-platform"] = "0.14"
|
||||
extra["versions.ant-launcher"] = "1.8.0"
|
||||
extra["versions.robolectric"] = "4.0"
|
||||
extra["versions.org.springframework"] = "4.2.0.RELEASE"
|
||||
extra["versions.jflex"] = "1.7.0"
|
||||
@@ -187,14 +188,13 @@ extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
|
||||
extra["versions.ktor-network"] = "1.0.1"
|
||||
|
||||
if (!project.hasProperty("versions.kotlin-native")) {
|
||||
extra["versions.kotlin-native"] = "1.5-dev-17775"
|
||||
extra["versions.kotlin-native"] = "1.4.30-dev-17200"
|
||||
}
|
||||
|
||||
val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled)
|
||||
val effectSystemEnabled by extra(project.getBooleanProperty("kotlin.compiler.effectSystemEnabled") ?: false)
|
||||
val newInferenceEnabled by extra(project.getBooleanProperty("kotlin.compiler.newInferenceEnabled") ?: false)
|
||||
val useJvmIrBackend by extra(project.kotlinBuildProperties.useIR)
|
||||
val useJvmFir by extra(project.kotlinBuildProperties.useFir)
|
||||
|
||||
val intellijSeparateSdks = project.getBooleanProperty("intellijSeparateSdks") ?: false
|
||||
|
||||
@@ -230,7 +230,6 @@ extra["compilerModules"] = arrayOf(
|
||||
":compiler:frontend",
|
||||
":compiler:frontend.common",
|
||||
":compiler:frontend.java",
|
||||
":compiler:frontend:cfg",
|
||||
":compiler:cli-common",
|
||||
":compiler:ir.tree",
|
||||
":compiler:ir.tree.impl",
|
||||
@@ -294,7 +293,6 @@ extra["compilerModules"] = arrayOf(
|
||||
":compiler:fir:checkers",
|
||||
":compiler:fir:entrypoint",
|
||||
":compiler:fir:analysis-tests",
|
||||
":compiler:fir:analysis-tests:legacy-fir-tests",
|
||||
":wasm:wasm.ir"
|
||||
)
|
||||
|
||||
@@ -321,24 +319,12 @@ extra["compilerModulesForJps"] = listOf(
|
||||
":compiler:compiler.version"
|
||||
)
|
||||
|
||||
// TODO: fix remaining warnings and remove this property.
|
||||
extra["tasksWithWarnings"] = listOf(
|
||||
":kotlin-stdlib:compileTestKotlin",
|
||||
":kotlin-stdlib-jdk7:compileTestKotlin",
|
||||
":kotlin-stdlib-jdk8:compileTestKotlin",
|
||||
":plugins:uast-kotlin:compileKotlin",
|
||||
":plugins:uast-kotlin:compileTestKotlin"
|
||||
)
|
||||
|
||||
val tasksWithWarnings: List<String> by extra
|
||||
|
||||
val coreLibProjects = listOfNotNull(
|
||||
":kotlin-stdlib",
|
||||
":kotlin-stdlib-common",
|
||||
":kotlin-stdlib-js",
|
||||
":kotlin-stdlib-jdk7",
|
||||
":kotlin-stdlib-jdk8",
|
||||
":kotlin-test",
|
||||
":kotlin-test:kotlin-test-annotations-common",
|
||||
":kotlin-test:kotlin-test-common",
|
||||
":kotlin-test:kotlin-test-jvm",
|
||||
@@ -346,7 +332,8 @@ val coreLibProjects = listOfNotNull(
|
||||
":kotlin-test:kotlin-test-junit5",
|
||||
":kotlin-test:kotlin-test-testng",
|
||||
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
|
||||
":kotlin-reflect"
|
||||
":kotlin-reflect",
|
||||
":kotlin-coroutines-experimental-compat"
|
||||
)
|
||||
|
||||
val gradlePluginProjects = listOf(
|
||||
@@ -420,7 +407,8 @@ allprojects {
|
||||
jcenter()
|
||||
maven(protobufRepo)
|
||||
maven(intellijRepo)
|
||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
|
||||
maven("https://dl.bintray.com/kotlin/ktor")
|
||||
maven("https://kotlin.bintray.com/kotlin-dependencies")
|
||||
maven("https://jetbrains.bintray.com/intellij-third-party-dependencies")
|
||||
maven("https://dl.google.com/dl/android/maven2")
|
||||
bootstrapKotlinRepo?.let(::maven)
|
||||
@@ -456,26 +444,7 @@ allprojects {
|
||||
|
||||
if (useJvmIrBackend) {
|
||||
useIR = true
|
||||
}
|
||||
|
||||
if (useJvmFir) {
|
||||
freeCompilerArgs += "-Xuse-fir"
|
||||
freeCompilerArgs += "-Xabi-stability=stable"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!kotlinBuildProperties.isInJpsBuildIdeaSync && !kotlinBuildProperties.useFir && !kotlinBuildProperties.disableWerror) {
|
||||
// For compiler and stdlib, allWarningsAsErrors is configured in the corresponding "root" projects
|
||||
// (compiler/build.gradle.kts and libraries/commonConfiguration.gradle).
|
||||
val projectsWithWarningsAsErrors = listOf("core", "plugins").map { File(it).absoluteFile }
|
||||
if (projectsWithWarningsAsErrors.any(projectDir::startsWith)) {
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
|
||||
if (path !in tasksWithWarnings) {
|
||||
kotlinOptions {
|
||||
allWarningsAsErrors = true
|
||||
}
|
||||
}
|
||||
freeCompilerArgs += "-Xir-binary-with-stable-abi"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -498,7 +467,7 @@ allprojects {
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KTI-112") { true }
|
||||
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KT-37089") { true }
|
||||
}
|
||||
|
||||
normalization {
|
||||
@@ -582,11 +551,10 @@ gradle.taskGraph.whenReady {
|
||||
|
||||
val proguardMessage = "proguard is ${kotlinBuildProperties.proguard.toOnOff()}"
|
||||
val jarCompressionMessage = "jar compression is ${kotlinBuildProperties.jarCompression.toOnOff()}"
|
||||
val profileMessage = "$profile build profile is active ($proguardMessage, $jarCompressionMessage). " +
|
||||
"Use -Pteamcity=<true|false> to reproduce CI/local build"
|
||||
|
||||
logger.warn(
|
||||
"$profile build profile is active ($proguardMessage, $jarCompressionMessage). " +
|
||||
"Use -Pteamcity=<true|false> to reproduce CI/local build"
|
||||
)
|
||||
logger.warn("\n\n$profileMessage")
|
||||
|
||||
allTasks.filterIsInstance<org.gradle.jvm.tasks.Jar>().forEach { task ->
|
||||
task.entryCompression = if (kotlinBuildProperties.jarCompression)
|
||||
@@ -601,7 +569,7 @@ val dist = tasks.register("dist") {
|
||||
}
|
||||
|
||||
val syncMutedTests = tasks.register("syncMutedTests") {
|
||||
dependsOn(":compiler:tests-mutes:tc-integration:run")
|
||||
dependsOn(":compiler:tests-mutes:run")
|
||||
}
|
||||
|
||||
val copyCompilerToIdeaPlugin by task<Copy> {
|
||||
@@ -631,10 +599,7 @@ tasks {
|
||||
|
||||
listOf("clean", "assemble", "install").forEach { taskName ->
|
||||
register("coreLibs${taskName.capitalize()}") {
|
||||
for (projectName in coreLibProjects) {
|
||||
if (projectName.startsWith(":kotlin-test:") && taskName == "install") continue
|
||||
dependsOn("$projectName:$taskName")
|
||||
}
|
||||
coreLibProjects.forEach { projectName -> dependsOn("$projectName:$taskName") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,7 +630,6 @@ tasks {
|
||||
dependsOn("dist")
|
||||
dependsOn(
|
||||
":compiler:test",
|
||||
":compiler:tests-common-new:test",
|
||||
":compiler:container:test",
|
||||
":compiler:tests-java8:test",
|
||||
":compiler:tests-spec:test",
|
||||
@@ -702,7 +666,6 @@ tasks {
|
||||
dependsOn(":compiler:fir:raw-fir:psi2fir:test")
|
||||
dependsOn(":compiler:fir:raw-fir:light-tree2fir:test")
|
||||
dependsOn(":compiler:fir:analysis-tests:test")
|
||||
dependsOn(":compiler:fir:analysis-tests:legacy-fir-tests:test")
|
||||
dependsOn(":compiler:fir:fir2ir:test")
|
||||
}
|
||||
|
||||
@@ -712,7 +675,6 @@ tasks {
|
||||
":compiler:fir:raw-fir:psi2fir:test",
|
||||
":compiler:fir:raw-fir:light-tree2fir:test",
|
||||
":compiler:fir:analysis-tests:test",
|
||||
":compiler:fir:analysis-tests:legacy-fir-tests:test",
|
||||
":compiler:fir:fir2ir:test",
|
||||
":plugins:fir:fir-plugin-prototype:test"
|
||||
)
|
||||
@@ -748,6 +710,7 @@ tasks {
|
||||
}
|
||||
|
||||
register("miscCompilerTest") {
|
||||
dependsOn("wasmCompilerTest")
|
||||
dependsOn("nativeCompilerTest")
|
||||
dependsOn("firCompilerTest")
|
||||
|
||||
@@ -766,7 +729,6 @@ tasks {
|
||||
register("toolsTest") {
|
||||
dependsOn(":tools:kotlinp:test")
|
||||
dependsOn(":native:kotlin-klib-commonizer:test")
|
||||
dependsOn(":native:kotlin-klib-commonizer-api:test")
|
||||
}
|
||||
|
||||
register("examplesTest") {
|
||||
@@ -813,6 +775,7 @@ tasks {
|
||||
|
||||
if (Ide.IJ()) {
|
||||
register("idea-new-project-wizard-tests") {
|
||||
dependsOn("dist")
|
||||
dependsOn(
|
||||
":libraries:tools:new-project-wizard:test",
|
||||
":libraries:tools:new-project-wizard:new-project-wizard-cli:test",
|
||||
@@ -885,24 +848,12 @@ tasks {
|
||||
":generators:test"
|
||||
)
|
||||
if (Ide.IJ()) {
|
||||
dependsOn(
|
||||
":libraries:tools:new-project-wizard:test",
|
||||
":libraries:tools:new-project-wizard:new-project-wizard-cli:test",
|
||||
":idea:idea-new-project-wizard:test" // Temporary here. Remove after enabling builds for ideaIntegrationsTests
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
register("ideaIntegrationsTests") {
|
||||
if (Ide.IJ()) {
|
||||
dependsOn(":idea:idea-new-project-wizard:test")
|
||||
dependsOn("idea-new-project-wizard-tests")
|
||||
}
|
||||
}
|
||||
|
||||
register("kaptIdeTest") {
|
||||
dependsOn(":kotlin-annotation-processing:test")
|
||||
dependsOn(":kotlin-annotation-processing-base:test")
|
||||
dependsOn(":kotlin-annotation-processing-cli:test")
|
||||
}
|
||||
|
||||
register("gradleIdeTest") {
|
||||
@@ -917,7 +868,6 @@ tasks {
|
||||
":idea:idea-gradle:test",
|
||||
":idea:test",
|
||||
":compiler:test",
|
||||
":compiler:container:test",
|
||||
":js:js.tests:test"
|
||||
)
|
||||
|
||||
@@ -946,17 +896,12 @@ tasks {
|
||||
}
|
||||
}
|
||||
|
||||
register("publishGradlePluginArtifacts") {
|
||||
idePluginDependency {
|
||||
dependsOnKotlinGradlePluginPublish()
|
||||
}
|
||||
}
|
||||
|
||||
register("publishIdeArtifacts") {
|
||||
idePluginDependency {
|
||||
dependsOn(
|
||||
":prepare:ide-plugin-dependencies:android-extensions-compiler-plugin-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:allopen-compiler-plugin-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:allopen-compiler-plugin-tests-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:incremental-compilation-impl-tests-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:kotlin-build-common-tests-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:kotlin-compiler-for-ide:publish",
|
||||
@@ -978,7 +923,10 @@ tasks {
|
||||
":kotlin-stdlib-jdk7:publish",
|
||||
":kotlin-stdlib-jdk8:publish",
|
||||
":kotlin-reflect:publish",
|
||||
":kotlin-main-kts:publish"
|
||||
":kotlin-main-kts:publish",
|
||||
":kotlin-stdlib-js:publish",
|
||||
":kotlin-test:kotlin-test-js:publish",
|
||||
":kotlin-coroutines-experimental-compat:publish"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ buildscript {
|
||||
repositories {
|
||||
if (cacheRedirectorEnabled) {
|
||||
maven("https://cache-redirector.jetbrains.com/jcenter.bintray.com")
|
||||
maven("https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
|
||||
maven("https://cache-redirector.jetbrains.com/kotlin.bintray.com/kotlin-dependencies")
|
||||
} else {
|
||||
jcenter()
|
||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
|
||||
maven("https://kotlin.bintray.com/kotlin-dependencies")
|
||||
}
|
||||
|
||||
project.bootstrapKotlinRepo?.let {
|
||||
@@ -81,12 +81,14 @@ extra["intellijReleaseType"] = when {
|
||||
else -> "releases"
|
||||
}
|
||||
|
||||
extra["versions.androidDxSources"] = "5.0.0_r2"
|
||||
|
||||
extra["customDepsOrg"] = "kotlin.build"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://jetbrains.bintray.com/intellij-third-party-dependencies/")
|
||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
|
||||
maven("https://kotlin.bintray.com/kotlin-dependencies")
|
||||
gradlePluginPortal()
|
||||
|
||||
extra["bootstrapKotlinRepo"]?.let {
|
||||
@@ -112,7 +114,6 @@ dependencies {
|
||||
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.5")
|
||||
|
||||
implementation("org.gradle:test-retry-gradle-plugin:1.1.9")
|
||||
implementation("com.gradle.enterprise:test-distribution-gradle-plugin:1.2.1")
|
||||
}
|
||||
|
||||
samWithReceiver {
|
||||
@@ -128,9 +129,8 @@ java {
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
kotlinOptions.freeCompilerArgs += listOf(
|
||||
"-Xopt-in=kotlin.RequiresOptIn", "-Xskip-runtime-version-check", "-Xsuppress-version-warnings"
|
||||
)
|
||||
kotlinOptions.freeCompilerArgs +=
|
||||
listOf("-Xopt-in=kotlin.RequiresOptIn", "-Xskip-runtime-version-check")
|
||||
}
|
||||
|
||||
tasks["build"].dependsOn(":prepare-deps:build")
|
||||
|
||||
@@ -14,9 +14,9 @@ pluginManagement {
|
||||
buildscript {
|
||||
repositories {
|
||||
if (cacheRedirectorEnabled == 'true') {
|
||||
maven { url "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies" }
|
||||
maven { url "https://cache-redirector.jetbrains.com/kotlin.bintray.com/kotlin-dependencies" }
|
||||
} else {
|
||||
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies" }
|
||||
maven { url "https://kotlin.bintray.com/kotlin-dependencies" }
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
|
||||
@@ -18,5 +18,3 @@ val KotlinBuildProperties.proguard: Boolean get() = postProcessing && getBoolean
|
||||
val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.build.jar.compression", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignoreTestFailures", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.disableWerror: Boolean get() = getBoolean("kotlin.build.disable.werror", false)
|
||||
|
||||
@@ -54,12 +54,11 @@ var Project.javaHome: String?
|
||||
extra["javaHome"] = v
|
||||
}
|
||||
|
||||
fun Project.generator(fqName: String, sourceSet: SourceSet? = null, configure: JavaExec.() -> Unit = {}) = smartJavaExec {
|
||||
fun Project.generator(fqName: String, sourceSet: SourceSet? = null) = smartJavaExec {
|
||||
classpath = (sourceSet ?: testSourceSet).runtimeClasspath
|
||||
mainClass.set(fqName)
|
||||
workingDir = rootDir
|
||||
systemProperty("line.separator", "\n")
|
||||
configure()
|
||||
}
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
|
||||
@@ -9,13 +9,10 @@
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.gradle.kotlin.dsl.project
|
||||
import java.io.File
|
||||
@@ -115,50 +112,6 @@ fun DependencyHandler.projectTests(name: String): ProjectDependency = project(na
|
||||
fun DependencyHandler.projectRuntimeJar(name: String): ProjectDependency = project(name, configuration = "runtimeJar")
|
||||
fun DependencyHandler.projectArchives(name: String): ProjectDependency = project(name, configuration = "archives")
|
||||
|
||||
fun Project.testApiJUnit5(
|
||||
vintageEngine: Boolean = false,
|
||||
runner: Boolean = false,
|
||||
suiteApi: Boolean = false
|
||||
) {
|
||||
with(dependencies) {
|
||||
val platformVersion = commonVer("org.junit", "junit-bom")
|
||||
testApi(platform("org.junit:junit-bom:$platformVersion"))
|
||||
testApi("org.junit.jupiter:junit-jupiter")
|
||||
if (vintageEngine) {
|
||||
testApi("org.junit.vintage:junit-vintage-engine:$platformVersion")
|
||||
}
|
||||
val componentsVersion = commonVer("org.junit.platform", "")
|
||||
|
||||
val components = mutableListOf(
|
||||
"org.junit.platform:junit-platform-commons",
|
||||
"org.junit.platform:junit-platform-launcher"
|
||||
)
|
||||
if (runner) {
|
||||
components += "org.junit.platform:junit-platform-runner"
|
||||
}
|
||||
if (suiteApi) {
|
||||
components += "org.junit.platform:junit-platform-suite-api"
|
||||
}
|
||||
|
||||
for (component in components) {
|
||||
testApi("$component:$componentsVersion")
|
||||
}
|
||||
|
||||
addDependencyTo<ExternalModuleDependency>(this, "testImplementation", intellijDep()) {
|
||||
// This dependency is needed only for FileComparisonFailure
|
||||
includeJars("idea_rt", rootProject = rootProject)
|
||||
isTransitive = false
|
||||
}
|
||||
|
||||
// This is needed only for using FileComparisonFailure, which relies on JUnit 3 classes
|
||||
add("testRuntimeOnly", commonDep("junit:junit"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun DependencyHandler.testApi(dependencyNotation: Any) {
|
||||
add("testApi", dependencyNotation)
|
||||
}
|
||||
|
||||
val Project.protobufVersion: String get() = findProperty("versions.protobuf") as String
|
||||
|
||||
val Project.protobufRepo: String
|
||||
|
||||
@@ -10,12 +10,12 @@ import net.rubygrapefruit.platform.WindowsRegistry.Key.HKEY_LOCAL_MACHINE
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
enum class JdkMajorVersion(private val mandatory: Boolean = true) {
|
||||
JDK_16, JDK_17, JDK_18, JDK_9, JDK_10(false), JDK_11(false), /*15.0*/JDK_15(false);
|
||||
JDK_16, JDK_17, JDK_18, JDK_9, JDK_10(false), JDK_11(false);
|
||||
|
||||
fun isMandatory(): Boolean = mandatory
|
||||
}
|
||||
|
||||
val jdkAlternativeVarNames = mapOf(JdkMajorVersion.JDK_9 to listOf("JDK_19"), JdkMajorVersion.JDK_15 to listOf("JDK_15_0"))
|
||||
val jdkAlternativeVarNames = mapOf(JdkMajorVersion.JDK_9 to listOf("JDK_19"))
|
||||
|
||||
data class JdkId(val explicit: Boolean, val majorVersion: JdkMajorVersion, var version: String, var homeDir: File)
|
||||
|
||||
@@ -101,12 +101,8 @@ fun MutableCollection<JdkId>.discoverJdks(project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
private val macOsJavaHomeOutRegexes =
|
||||
listOf(
|
||||
Regex("""\s+(\S+),\s+(\S+):\s+".*?"\s+(.+)"""),
|
||||
Regex("""\s+(\S+)\s+\((.*?)\):\s+(.+)"""),
|
||||
Regex("""\s+(\S+)\s+\((.*?)\)\s+"[^"]*"\s+-\s+"[^"]*"\s(.+)""")
|
||||
)
|
||||
private val macOsJavaHomeOutRegexes = listOf(Regex("""\s+(\S+),\s+(\S+):\s+".*?"\s+(.+)"""),
|
||||
Regex("""\s+(\S+)\s+\((.*?)\):\s+(.+)"""))
|
||||
|
||||
fun MutableCollection<JdkId>.discoverJdksOnMacOS(project: Project) {
|
||||
val procBuilder = ProcessBuilder("/usr/libexec/java_home", "-V").redirectErrorStream(true)
|
||||
|
||||
@@ -76,6 +76,8 @@ fun Project.jpsStandalone() = "kotlin.build:jps-standalone:${rootProject.extra["
|
||||
|
||||
fun Project.nodeJSPlugin() = "kotlin.build:NodeJS:${rootProject.extra["versions.idea.NodeJS"]}"
|
||||
|
||||
fun Project.androidDxJar() = "org.jetbrains.kotlin:android-dx:${rootProject.extra["versions.androidBuildTools"]}"
|
||||
|
||||
fun Project.jpsBuildTest() = "com.jetbrains.intellij.idea:jps-build-test:${rootProject.extra["versions.intellijSdk"]}"
|
||||
|
||||
fun Project.kotlinxCollectionsImmutable() = "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:${rootProject.extra["versions.kotlinx-collections-immutable"]}"
|
||||
|
||||
@@ -20,10 +20,6 @@ internal const val PLUGIN_MARKER_SUFFIX = ".gradle.plugin"
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
|
||||
|
||||
fun Project.isSonatypePublish(): Boolean =
|
||||
hasProperty("isSonatypePublish") && property("isSonatypePublish") as Boolean
|
||||
|
||||
val pluginDevelopment = extensions.getByType<PluginBundleExtension>()
|
||||
val publishingExtension = extensions.getByType<PublishingExtension>()
|
||||
val mainPublication = publishingExtension.publications[KotlinBuildPublishingPlugin.PUBLICATION_NAME] as MavenPublication
|
||||
@@ -36,12 +32,7 @@ fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
|
||||
|
||||
tasks.named<PublishToMavenRepository>(
|
||||
"publish${markerPublication.name.capitalize(Locale.ROOT)}PublicationTo${KotlinBuildPublishingPlugin.REPOSITORY_NAME}Repository"
|
||||
).apply {
|
||||
configureRepository()
|
||||
configure {
|
||||
onlyIf { !isSonatypePublish() }
|
||||
}
|
||||
}
|
||||
).configureRepository()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ open class DexMethodCount : DefaultTask() {
|
||||
dependsOn(jar)
|
||||
}
|
||||
|
||||
@Internal // plain output properties are not supported, mark as internal to suppress warning from validatePlugins
|
||||
@Internal // plain output properties are not supported, mark as internal to suppress warning from validateTaskProperties
|
||||
lateinit var counts: Counts
|
||||
|
||||
@get:OutputFile
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -71,11 +71,62 @@ class KotlinBuildPublishingPlugin @Inject constructor(
|
||||
create<MavenPublication>(PUBLICATION_NAME) {
|
||||
from(kotlinLibraryComponent)
|
||||
|
||||
configureKotlinPomAttributes(project)
|
||||
pom {
|
||||
packaging = "jar"
|
||||
name.set(humanReadableName(project))
|
||||
description.set(project.description ?: humanReadableName(project))
|
||||
url.set("https://kotlinlang.org/")
|
||||
licenses {
|
||||
license {
|
||||
name.set("The Apache License, Version 2.0")
|
||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url.set("https://github.com/JetBrains/kotlin")
|
||||
connection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
developerConnection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
name.set("Kotlin Team")
|
||||
organization.set("JetBrains")
|
||||
organizationUrl.set("https://www.jetbrains.com")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = REPOSITORY_NAME
|
||||
url = file("${project.rootDir}/build/repo").toURI()
|
||||
}
|
||||
}
|
||||
}
|
||||
configureDefaultPublishing()
|
||||
|
||||
val signingRequired = provider {
|
||||
project.findProperty("signingRequired")?.toString()?.toBoolean()
|
||||
?: project.property("isSonatypeRelease") as Boolean
|
||||
}
|
||||
|
||||
configure<SigningExtension> {
|
||||
setRequired(signingRequired)
|
||||
sign(extensions.getByType<PublishingExtension>().publications[PUBLICATION_NAME])
|
||||
useGpgCmd()
|
||||
}
|
||||
|
||||
tasks.withType<Sign>().configureEach {
|
||||
setOnlyIf { signingRequired.get() }
|
||||
}
|
||||
|
||||
tasks.register("install") {
|
||||
dependsOn(tasks.named("publishToMavenLocal"))
|
||||
}
|
||||
|
||||
tasks.named<PublishToMavenRepository>("publish${PUBLICATION_NAME}PublicationTo${REPOSITORY_NAME}Repository")
|
||||
.configureRepository()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -86,84 +137,13 @@ class KotlinBuildPublishingPlugin @Inject constructor(
|
||||
const val COMPILE_CONFIGURATION = "publishedCompile"
|
||||
const val RUNTIME_CONFIGURATION = "publishedRuntime"
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun humanReadableName(project: Project) =
|
||||
project.name.split("-").joinToString(separator = " ") { it.capitalize(Locale.ROOT) }
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun humanReadableName(name: String) =
|
||||
name.split("-").joinToString(separator = " ") { it.capitalize(Locale.ROOT) }
|
||||
|
||||
fun MavenPublication.configureKotlinPomAttributes(project: Project, explicitDescription: String? = null) {
|
||||
val publication = this
|
||||
pom {
|
||||
packaging = "jar"
|
||||
name.set(humanReadableName(publication.artifactId))
|
||||
description.set(explicitDescription ?: project.description ?: humanReadableName(publication.artifactId))
|
||||
url.set("https://kotlinlang.org/")
|
||||
licenses {
|
||||
license {
|
||||
name.set("The Apache License, Version 2.0")
|
||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url.set("https://github.com/JetBrains/kotlin")
|
||||
connection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
developerConnection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
name.set("Kotlin Team")
|
||||
organization.set("JetBrains")
|
||||
organizationUrl.set("https://www.jetbrains.com")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Project.configureDefaultPublishing() {
|
||||
configure<PublishingExtension> {
|
||||
repositories {
|
||||
maven {
|
||||
name = KotlinBuildPublishingPlugin.REPOSITORY_NAME
|
||||
url = file("${project.rootDir}/build/repo").toURI()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configureSigning()
|
||||
|
||||
tasks.register("install") {
|
||||
dependsOn(tasks.named("publishToMavenLocal"))
|
||||
}
|
||||
|
||||
tasks.withType<PublishToMavenRepository>()
|
||||
.matching { it.name.endsWith("PublicationTo${KotlinBuildPublishingPlugin.REPOSITORY_NAME}Repository") }
|
||||
.all { configureRepository() }
|
||||
}
|
||||
|
||||
private fun Project.configureSigning() {
|
||||
val signingRequired = provider {
|
||||
project.findProperty("signingRequired")?.toString()?.toBoolean()
|
||||
?: project.property("isSonatypeRelease") as Boolean
|
||||
}
|
||||
|
||||
configure<SigningExtension> {
|
||||
setRequired(signingRequired)
|
||||
sign(extensions.getByType<PublishingExtension>().publications) // all publications
|
||||
useGpgCmd()
|
||||
}
|
||||
|
||||
tasks.withType<Sign>().configureEach {
|
||||
setOnlyIf { signingRequired.get() }
|
||||
}
|
||||
}
|
||||
|
||||
fun TaskProvider<PublishToMavenRepository>.configureRepository() =
|
||||
configure { configureRepository() }
|
||||
|
||||
private fun PublishToMavenRepository.configureRepository() {
|
||||
fun TaskProvider<PublishToMavenRepository>.configureRepository() = configure {
|
||||
dependsOn(project.rootProject.tasks.named("preparePublication"))
|
||||
doFirst {
|
||||
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
|
||||
|
||||
@@ -30,7 +30,6 @@ val SourceSet.projectDefault: Project.() -> Unit
|
||||
}
|
||||
"test" -> {
|
||||
java.srcDirs("test", "tests")
|
||||
this@projectDefault.resources.srcDir("testResources")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -20,65 +31,51 @@ import java.lang.Character.isUpperCase
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
val kotlinGradlePluginAndItsRequired = arrayOf(
|
||||
":kotlin-allopen",
|
||||
":kotlin-noarg",
|
||||
":kotlin-sam-with-receiver",
|
||||
":kotlin-android-extensions",
|
||||
":kotlin-parcelize-compiler",
|
||||
":kotlin-build-common",
|
||||
":kotlin-compiler-embeddable",
|
||||
":native:kotlin-native-utils",
|
||||
":kotlin-util-klib",
|
||||
":kotlin-util-io",
|
||||
":kotlin-compiler-runner",
|
||||
":kotlin-daemon-embeddable",
|
||||
":kotlin-daemon-client",
|
||||
":kotlin-gradle-plugin-api",
|
||||
":kotlin-gradle-plugin",
|
||||
":kotlin-gradle-plugin-model",
|
||||
":kotlin-reflect",
|
||||
":kotlin-annotation-processing-gradle",
|
||||
":kotlin-test",
|
||||
":kotlin-gradle-subplugin-example",
|
||||
":kotlin-stdlib-common",
|
||||
":kotlin-stdlib",
|
||||
":kotlin-stdlib-jdk8",
|
||||
":kotlin-stdlib-js",
|
||||
":examples:annotation-processor-example",
|
||||
":kotlin-script-runtime",
|
||||
":kotlin-scripting-common",
|
||||
":kotlin-scripting-jvm",
|
||||
":kotlin-scripting-compiler-embeddable",
|
||||
":kotlin-scripting-compiler-impl-embeddable",
|
||||
":kotlin-test-js-runner",
|
||||
":native:kotlin-klib-commonizer-embeddable",
|
||||
":native:kotlin-klib-commonizer-api"
|
||||
)
|
||||
|
||||
fun Task.dependsOnKotlinGradlePluginInstall() {
|
||||
kotlinGradlePluginAndItsRequired.forEach {
|
||||
dependsOn("${it}:install")
|
||||
}
|
||||
fun Task.dependsOnKotlinPluginInstall() {
|
||||
dependsOn(
|
||||
":kotlin-allopen:install",
|
||||
":kotlin-noarg:install",
|
||||
":kotlin-sam-with-receiver:install",
|
||||
":kotlin-android-extensions:install",
|
||||
":kotlin-parcelize-compiler:install",
|
||||
":kotlin-build-common:install",
|
||||
":kotlin-compiler-embeddable:install",
|
||||
":native:kotlin-native-utils:install",
|
||||
":kotlin-util-klib:install",
|
||||
":kotlin-util-io:install",
|
||||
":kotlin-compiler-runner:install",
|
||||
":kotlin-daemon-embeddable:install",
|
||||
":kotlin-daemon-client:install",
|
||||
":kotlin-gradle-plugin-api:install",
|
||||
":kotlin-gradle-plugin:install",
|
||||
":kotlin-gradle-plugin-model:install",
|
||||
":kotlin-reflect:install",
|
||||
":kotlin-annotation-processing-gradle:install",
|
||||
":kotlin-test:kotlin-test-common:install",
|
||||
":kotlin-test:kotlin-test-annotations-common:install",
|
||||
":kotlin-test:kotlin-test-jvm:install",
|
||||
":kotlin-test:kotlin-test-js:install",
|
||||
":kotlin-test:kotlin-test-junit:install",
|
||||
":kotlin-gradle-subplugin-example:install",
|
||||
":kotlin-stdlib-common:install",
|
||||
":kotlin-stdlib:install",
|
||||
":kotlin-stdlib-jdk8:install",
|
||||
":kotlin-stdlib-js:install",
|
||||
":examples:annotation-processor-example:install",
|
||||
":kotlin-script-runtime:install",
|
||||
":kotlin-scripting-common:install",
|
||||
":kotlin-scripting-jvm:install",
|
||||
":kotlin-scripting-compiler-embeddable:install",
|
||||
":kotlin-scripting-compiler-impl-embeddable:install",
|
||||
":kotlin-test-js-runner:install",
|
||||
":native:kotlin-klib-commonizer-embeddable:install"
|
||||
)
|
||||
}
|
||||
|
||||
fun Task.dependsOnKotlinGradlePluginPublish() {
|
||||
kotlinGradlePluginAndItsRequired.forEach {
|
||||
project.rootProject.tasks.findByPath("${it}:publish")?.let { task ->
|
||||
dependsOn(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parallel is redundant if @param jUnit5Enabled is true, because
|
||||
* JUnit5 supports parallel test execution by itself, without gradle help
|
||||
*/
|
||||
fun Project.projectTest(
|
||||
taskName: String = "test",
|
||||
parallel: Boolean = false,
|
||||
shortenTempRootName: Boolean = false,
|
||||
jUnit5Enabled: Boolean = false,
|
||||
body: Test.() -> Unit = {}
|
||||
): TaskProvider<Test> = getOrCreateTask(taskName) {
|
||||
doFirst {
|
||||
@@ -112,29 +109,12 @@ fun Project.projectTest(
|
||||
}
|
||||
}
|
||||
|
||||
val parentNames = if (jUnit5Enabled) {
|
||||
/*
|
||||
* If we run test from inner test class with junit 5 we need
|
||||
* to include all containing classes of our class
|
||||
*/
|
||||
val nestedNames = classFileNameWithoutExtension.split("$")
|
||||
mutableListOf(nestedNames.first()).also {
|
||||
for (s in nestedNames.subList(1, nestedNames.size)) {
|
||||
it += "${it.last()}\$$s"
|
||||
}
|
||||
}
|
||||
} else emptyList()
|
||||
|
||||
include { treeElement ->
|
||||
val path = treeElement.path
|
||||
if (treeElement.isDirectory) {
|
||||
include {
|
||||
val path = it.path
|
||||
if (it.isDirectory) {
|
||||
classFileNameWithoutExtension.startsWith(path)
|
||||
} else {
|
||||
if (jUnit5Enabled) {
|
||||
path == classFileName || (path.endsWith(".class") && parentNames.any { path.startsWith(it) })
|
||||
} else {
|
||||
path == classFileName || (path.endsWith(".class") && path.startsWith("$classFileNameWithoutExtension$"))
|
||||
}
|
||||
path == classFileName || (path.endsWith(".class") && path.startsWith("$classFileNameWithoutExtension$"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,7 +177,7 @@ fun Project.projectTest(
|
||||
}
|
||||
}
|
||||
|
||||
if (parallel && !jUnit5Enabled) {
|
||||
if (parallel) {
|
||||
maxParallelForks =
|
||||
project.findProperty("kotlin.test.maxParallelForks")?.toString()?.toInt()
|
||||
?: (Runtime.getRuntime().availableProcessors() / if (kotlinBuildProperties.isTeamcityBuild) 2 else 4).coerceAtLeast(1)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import com.gradle.enterprise.gradleplugin.testdistribution.TestDistributionExtension
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
|
||||
fun Test.configureTestDistribution(configure: TestDistributionExtension.() -> Unit = {}) {
|
||||
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
|
||||
val testDistributionEnabled = project.findProperty("kotlin.build.test.distribution.enabled")?.toString()?.toBoolean()
|
||||
?: isTeamcityBuild
|
||||
|
||||
useJUnitPlatform()
|
||||
extensions.configure(TestDistributionExtension::class.java) {
|
||||
enabled.set(testDistributionEnabled)
|
||||
maxRemoteExecutors.set(20)
|
||||
if (isTeamcityBuild) {
|
||||
requirements.set(setOf("os=${OperatingSystem.current().familyName}"))
|
||||
} else {
|
||||
maxLocalExecutors.set(0)
|
||||
}
|
||||
configure()
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.isTestDistributionEnabled(): Boolean =
|
||||
extensions.findByType(TestDistributionExtension::class.java)?.enabled?.orNull ?: false
|
||||
@@ -1,11 +1,14 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
ext {
|
||||
isD8Enabled = project.findProperty('android.enableD8').toBoolean()
|
||||
}
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
}
|
||||
}
|
||||
apply plugin: 'com.android.application'
|
||||
@@ -17,7 +20,7 @@ repositories {
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "29.0.3"
|
||||
buildToolsVersion "28.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.jetbrains.kotlin.android.tests"
|
||||
@@ -37,6 +40,14 @@ android {
|
||||
|
||||
packagingOptions { exclude 'META-INF/build.txt' }
|
||||
|
||||
//TODO run under java 6, cause there is error on implicit 'stream' import in 'asWithMutable' test
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
incremental = false
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
dexInProcess false
|
||||
@@ -49,9 +60,11 @@ android {
|
||||
resultsDir = "build/test/results"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
if (isD8Enabled) {
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "box"
|
||||
@@ -73,20 +86,15 @@ android {
|
||||
dimension "box"
|
||||
}
|
||||
|
||||
common_ir0 {
|
||||
dimension "box"
|
||||
}
|
||||
|
||||
common_ir1 {
|
||||
dimension "box"
|
||||
}
|
||||
if (isD8Enabled) {
|
||||
jvm80 {
|
||||
dimension "box"
|
||||
}
|
||||
|
||||
common_ir2 {
|
||||
dimension "box"
|
||||
}
|
||||
|
||||
reflect_ir0 {
|
||||
dimension "box"
|
||||
reflectjvm80 {
|
||||
dimension "box"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
#don't try to download android specific tools within gradle: licence acceptance will be required
|
||||
android.builder.sdkDownload=false
|
||||
android.builder.sdkDownload=false
|
||||
android.enableD8=true
|
||||
@@ -19,10 +19,6 @@ dependencies {
|
||||
testCompile(project(":kotlin-reflect"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
testCompile(commonDep("junit:junit"))
|
||||
testApi(projectTests(":compiler:test-infrastructure"))
|
||||
testApi(projectTests(":compiler:test-infrastructure-utils"))
|
||||
testApi(projectTests(":compiler:tests-compiler-utils"))
|
||||
testApi(projectTests(":compiler:tests-common-new"))
|
||||
|
||||
testCompile(projectTests(":jps-plugin"))
|
||||
testCompile(commonDep("junit:junit"))
|
||||
@@ -41,8 +37,6 @@ dependencies {
|
||||
testCompile(intellijPluginDep("java")) { includeJars("jps-builders") }
|
||||
testCompile(jpsStandalone()) { includeJars("jps-model") }
|
||||
testCompile(jpsBuildTest())
|
||||
|
||||
testCompile("org.junit.platform:junit-platform-launcher:${commonVer("org.junit.platform", "")}")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.tests;
|
||||
|
||||
import org.jetbrains.kotlin.jps.build.BaseKotlinJpsBuildTestCase;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Ignore
|
||||
public class AndroidJpsBuildTestCase extends BaseKotlinJpsBuildTestCase {
|
||||
private static final String PROJECT_NAME = "android-module";
|
||||
private static final String SDK_NAME = "Android_SDK";
|
||||
|
||||
private final File workDir = new File(AndroidRunner.getPathManager().getTmpFolder());
|
||||
|
||||
public void doTest() {
|
||||
initProject();
|
||||
rebuildAllModules();
|
||||
buildAllModules().assertSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getProjectName() {
|
||||
return "android-module";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runTest() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "AndroidJpsTest";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File doGetProjectDir() throws IOException {
|
||||
return workDir;
|
||||
}
|
||||
|
||||
private void initProject() {
|
||||
addJdk(SDK_NAME, AndroidRunner.getPathManager().getPlatformFolderInAndroidSdk() + "/android.jar");
|
||||
loadProject(workDir.getAbsolutePath() + File.separator + PROJECT_NAME + ".ipr");
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import org.junit.runners.AllTests;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@RunWith(AllTests.class)
|
||||
//@RunWith(AllTests.class)
|
||||
public class AndroidRunner {
|
||||
|
||||
private static PathManager pathManager;
|
||||
@@ -46,8 +46,12 @@ public class AndroidRunner {
|
||||
|
||||
CodegenTestsOnAndroidGenerator.generate(pathManager);
|
||||
|
||||
System.out.println("Run tests on Android...");
|
||||
return CodegenTestsOnAndroidRunner.runTestsInEmulator(pathManager);
|
||||
System.out.println("Run tests on android...");
|
||||
TestSuite suite = CodegenTestsOnAndroidRunner.runTestsInEmulator(pathManager);
|
||||
//AndroidJpsBuildTestCase indirectly depends on UsefulTestCase which compiled against java 8
|
||||
//TODO: Need add separate run configuration for AndroidJpsBuildTestCase
|
||||
//suite.addTest(new AndroidJpsBuildTestCase());
|
||||
return suite;
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
|
||||
@@ -20,9 +20,7 @@ import com.intellij.openapi.util.Ref
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.sourceFileProvider
|
||||
import org.jetbrains.kotlin.test.KotlinBaseTest
|
||||
import java.io.File
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@@ -36,24 +34,28 @@ private data class OldPackageAndNew(val oldFqName: FqName, val newFqName: FqName
|
||||
|
||||
internal fun patchFilesAndAddTest(
|
||||
testFile: File,
|
||||
module: TestModule,
|
||||
services: TestServices,
|
||||
testFiles: List<KotlinBaseTest.TestFile>,
|
||||
filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter
|
||||
): FqName {
|
||||
): FqName? {
|
||||
if (testFiles.any { it.name.endsWith(".java") }) {
|
||||
//TODO support java files
|
||||
return null
|
||||
}
|
||||
val ktFiles = testFiles.filter { it.name.endsWith(".kt") }
|
||||
if (ktFiles.isEmpty()) return null
|
||||
|
||||
val newPackagePrefix = testFile.path.replace("\\\\|-|\\.|/".toRegex(), "_")
|
||||
val oldPackage = Ref<FqName>()
|
||||
val isJvmName = Ref<Boolean>(false)
|
||||
val testFiles = module.files
|
||||
val isSingle = testFiles.size == 1
|
||||
val resultFiles = testFiles.map {
|
||||
val fileName = if (isSingle) it.name else testFile.name.substringBeforeLast(".kt") + "/" + it.name
|
||||
val content = services.sourceFileProvider.getContentOfSourceFile(it)
|
||||
TestClassInfo(
|
||||
fileName,
|
||||
changePackage(newPackagePrefix, content, oldPackage, isJvmName),
|
||||
changePackage(newPackagePrefix, it.content, oldPackage, isJvmName),
|
||||
oldPackage.get(),
|
||||
isJvmName.get(),
|
||||
getGeneratedClassName(File(fileName), content, newPackagePrefix, oldPackage.get())
|
||||
getGeneratedClassName(File(fileName), it.content, newPackagePrefix, oldPackage.get())
|
||||
)
|
||||
}
|
||||
val packages =
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.tests
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
@@ -12,27 +13,16 @@ import com.intellij.openapi.util.io.FileUtilRt
|
||||
import org.jetbrains.kotlin.cli.common.output.writeAllTo
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestCase
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestFiles
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.model.DependencyKind
|
||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.impl.BackendKindExtractorImpl
|
||||
import org.jetbrains.kotlin.test.services.impl.TemporaryDirectoryManagerImpl
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsSourceFilesProvider
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.CodegenHelpersSourceFilesProvider
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
@@ -54,18 +44,17 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
//keep it globally to avoid test grouping on TC
|
||||
private val generatedTestNames = hashSetOf<String>()
|
||||
|
||||
private val COMMON = FlavorConfig(TargetBackend.ANDROID,"common", 3)
|
||||
private val REFLECT = FlavorConfig(TargetBackend.ANDROID, "reflect", 1)
|
||||
private val COMMON = FlavorConfig("common", 3);
|
||||
private val REFLECT = FlavorConfig("reflect", 1);
|
||||
private val JVM8 = FlavorConfig("jvm8", 1);
|
||||
private val JVM8REFLECT = FlavorConfig("reflectjvm8", 1);
|
||||
|
||||
private val COMMON_IR = FlavorConfig(TargetBackend.ANDROID_IR, "common_ir", 3)
|
||||
private val REFLECT_IR = FlavorConfig(TargetBackend.ANDROID_IR,"reflect_ir", 1)
|
||||
|
||||
class FlavorConfig(private val backend: TargetBackend, private val prefix: String, val limit: Int) {
|
||||
class FlavorConfig(private val prefix: String, val limit: Int) {
|
||||
|
||||
private var writtenFilesCount = 0
|
||||
|
||||
fun printStatistics() {
|
||||
println("FlavorTestCompiler for $backend: $prefix, generated file count: $writtenFilesCount")
|
||||
println("FlavorTestCompiler: $prefix, generated file count: $writtenFilesCount")
|
||||
}
|
||||
|
||||
fun getFlavorForNewFiles(newFilesCount: Int): String {
|
||||
@@ -111,7 +100,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
it.setExecutable(true)
|
||||
}
|
||||
}
|
||||
File("./gradlew.bat").copyTo(File(projectRoot, "gradlew.bat"))
|
||||
File("./gradlew.bat").copyTo(File(projectRoot, "gradlew.bat"));
|
||||
val file = File(target, "gradle-wrapper.properties")
|
||||
file.readLines().map {
|
||||
when {
|
||||
@@ -148,47 +137,27 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
private fun generateTestsAndFlavourSuites() {
|
||||
println("Generating test files...")
|
||||
|
||||
val folders = arrayOf(
|
||||
File("compiler/testData/codegen/box"),
|
||||
File("compiler/testData/codegen/boxInline")
|
||||
)
|
||||
|
||||
generateTestMethodsForDirectories(
|
||||
TargetBackend.ANDROID,
|
||||
COMMON,
|
||||
REFLECT,
|
||||
*folders
|
||||
)
|
||||
|
||||
generateTestMethodsForDirectories(
|
||||
TargetBackend.ANDROID_IR,
|
||||
COMMON_IR,
|
||||
REFLECT_IR,
|
||||
*folders
|
||||
)
|
||||
generateTestMethodsForDirectories(File("compiler/testData/codegen/box"), File("compiler/testData/codegen/boxInline"))
|
||||
|
||||
pendingUnitTestGenerators.values.forEach { it.generate() }
|
||||
}
|
||||
|
||||
private fun generateTestMethodsForDirectories(
|
||||
backend: TargetBackend,
|
||||
commonFlavor: FlavorConfig,
|
||||
reflectionFlavor: FlavorConfig,
|
||||
vararg dirs: File
|
||||
) {
|
||||
private fun generateTestMethodsForDirectories(vararg dirs: File) {
|
||||
val holders = mutableMapOf<ConfigurationKey, FilesWriter>()
|
||||
|
||||
for (dir in dirs) {
|
||||
val files = dir.listFiles() ?: error("Folder with testData is empty: ${dir.absolutePath}")
|
||||
processFiles(files, holders, backend, commonFlavor, reflectionFlavor)
|
||||
processFiles(files, holders)
|
||||
}
|
||||
|
||||
holders.values.forEach {
|
||||
it.writeFilesOnDisk()
|
||||
}
|
||||
|
||||
commonFlavor.printStatistics()
|
||||
reflectionFlavor.printStatistics()
|
||||
COMMON.printStatistics()
|
||||
REFLECT.printStatistics()
|
||||
JVM8.printStatistics()
|
||||
JVM8REFLECT.printStatistics()
|
||||
}
|
||||
|
||||
internal inner class FilesWriter(
|
||||
@@ -272,14 +241,10 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(TestInfrastructureInternals::class)
|
||||
@Throws(IOException::class)
|
||||
private fun processFiles(
|
||||
files: Array<File>,
|
||||
holders: MutableMap<ConfigurationKey, FilesWriter>,
|
||||
backend: TargetBackend,
|
||||
commmonFlavor: FlavorConfig,
|
||||
reflectionFlavor: FlavorConfig
|
||||
holders: MutableMap<ConfigurationKey, FilesWriter>
|
||||
) {
|
||||
holders.values.forEach {
|
||||
it.writeFilesOnDiskIfNeeded()
|
||||
@@ -289,7 +254,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
if (file.isDirectory) {
|
||||
val listFiles = file.listFiles()
|
||||
if (listFiles != null) {
|
||||
processFiles(listFiles, holders, backend, commmonFlavor, reflectionFlavor)
|
||||
processFiles(listFiles, holders)
|
||||
}
|
||||
} else if (FileUtilRt.getExtension(file.name) != KotlinFileType.EXTENSION) {
|
||||
// skip non kotlin files
|
||||
@@ -298,13 +263,14 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
continue
|
||||
}
|
||||
|
||||
if (!InTextDirectivesUtils.isPassingTarget(backend.compatibleWith, file) ||
|
||||
if (!InTextDirectivesUtils.isPassingTarget(TargetBackend.JVM, file) ||
|
||||
InTextDirectivesUtils.isIgnoredTarget(TargetBackend.ANDROID, file)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
val fullFileText = FileUtil.loadFile(file, true)
|
||||
val fullFileText =
|
||||
FileUtil.loadFile(file, true).replace("COROUTINES_PACKAGE", "kotlin.coroutines")
|
||||
|
||||
if (fullFileText.contains("// WITH_COROUTINES")) {
|
||||
if (fullFileText.contains("kotlin.coroutines.experimental")) continue
|
||||
@@ -314,106 +280,48 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
//TODO support JvmPackageName
|
||||
if (fullFileText.contains("@file:JvmPackageName(")) continue
|
||||
// TODO: Support jvm assertions
|
||||
if (fullFileText.contains("// ASSERTIONS_MODE: jvm")) continue
|
||||
if (fullFileText.contains("// MODULE: ")) continue
|
||||
if (fullFileText.contains("// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm")) continue
|
||||
val targets = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fullFileText, "// JVM_TARGET:")
|
||||
.also { it.remove(JvmTarget.JVM_1_6.description) }
|
||||
|
||||
val isAtLeastJvm8Target = !targets.contains(JvmTarget.JVM_1_6.description)
|
||||
|
||||
if (isAtLeastJvm8Target && fullFileText.contains("@Target(AnnotationTarget.TYPE)")) {
|
||||
//TODO: type annotations supported on sdk 26 emulator
|
||||
continue
|
||||
}
|
||||
val isJvm8Target =
|
||||
if (targets.isEmpty()) false
|
||||
else if (targets.contains(JvmTarget.JVM_1_8.description) && targets.size == 1) true
|
||||
else continue //TODO: support other targets on Android
|
||||
|
||||
// TODO: support SKIP_JDK6 on new platforms
|
||||
if (fullFileText.contains("// SKIP_JDK6")) continue
|
||||
|
||||
if (hasBoxMethod(fullFileText)) {
|
||||
val testConfiguration = createTestConfiguration(file, backend)
|
||||
val services = testConfiguration.testServices
|
||||
|
||||
val moduleStructure = try {
|
||||
testConfiguration.moduleStructureExtractor.splitTestDataByModules(
|
||||
file.path,
|
||||
testConfiguration.directives,
|
||||
).also {
|
||||
services.register(TestModuleStructure::class, it)
|
||||
}
|
||||
} catch (e: ExceptionFromModuleStructureTransformer) {
|
||||
continue
|
||||
}
|
||||
val module = moduleStructure.modules.singleOrNull() ?: continue
|
||||
if (module.files.any { it.isJavaFile || it.isKtsFile }) continue
|
||||
if (module.files.isEmpty()) continue
|
||||
services.registerDependencyProvider(DependencyProviderImpl(services, moduleStructure.modules))
|
||||
|
||||
val testFiles = createTestFiles(file, fullFileText)
|
||||
val kind = KotlinBaseTest.extractConfigurationKind(testFiles)
|
||||
val jdkKind = KotlinBaseTest.getTestJdkKind(testFiles)
|
||||
val keyConfiguration = CompilerConfiguration()
|
||||
val configuratorForFlags = JvmEnvironmentConfigurator(services)
|
||||
with(configuratorForFlags) {
|
||||
val extractor = DirectiveToConfigurationKeyExtractor()
|
||||
extractor.provideConfigurationKeys()
|
||||
extractor.configure(keyConfiguration, module.directives)
|
||||
}
|
||||
val kind = configuratorForFlags.extractConfigurationKind(module.directives)
|
||||
val jdkKind = configuratorForFlags.extractJdkKind(module.directives)
|
||||
|
||||
keyConfiguration.languageVersionSettings = module.languageVersionSettings
|
||||
KotlinBaseTest.updateConfigurationByDirectivesInTestFiles(testFiles, keyConfiguration)
|
||||
|
||||
val key = ConfigurationKey(kind, jdkKind, keyConfiguration.toString())
|
||||
val compiler = if (kind.withReflection) reflectionFlavor else commmonFlavor
|
||||
val compilerConfigurationProvider = services.compilerConfigurationProvider as CompilerConfigurationProviderImpl
|
||||
val compiler = if (isJvm8Target) {
|
||||
if (kind.withReflection) JVM8REFLECT else JVM8
|
||||
} else if (kind.withReflection) REFLECT else COMMON
|
||||
val filesHolder = holders.getOrPut(key) {
|
||||
FilesWriter(compiler, compilerConfigurationProvider.createCompilerConfiguration(module)).also {
|
||||
FilesWriter(compiler, KotlinTestUtils.newConfiguration(kind, jdkKind, KotlinTestUtils.getAnnotationsJar()).apply {
|
||||
println("Creating new configuration by $key")
|
||||
}
|
||||
KotlinBaseTest.updateConfigurationByDirectivesInTestFiles(testFiles, this)
|
||||
})
|
||||
}
|
||||
|
||||
patchFilesAndAddTest(file, module, services, filesHolder)
|
||||
patchFilesAndAddTest(file, testFiles, filesHolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTestConfiguration(testDataFile: File, backend: TargetBackend): TestConfiguration {
|
||||
return TestConfigurationBuilder().apply {
|
||||
configure(backend)
|
||||
testInfo = KotlinTestInfo(
|
||||
"org.jetbrains.kotlin.android.tests.AndroidRunner",
|
||||
"test${testDataFile.nameWithoutExtension.capitalize()}",
|
||||
emptySet()
|
||||
)
|
||||
}.build(testDataFile.path)
|
||||
}
|
||||
|
||||
private fun TestConfigurationBuilder.configure(backend: TargetBackend) {
|
||||
globalDefaults {
|
||||
frontend = FrontendKinds.ClassicFrontend
|
||||
targetBackend = backend
|
||||
targetPlatform = JvmPlatforms.defaultJvmPlatform
|
||||
dependencyKind = DependencyKind.Binary
|
||||
}
|
||||
|
||||
useConfigurators(
|
||||
::CommonEnvironmentConfigurator,
|
||||
::JvmEnvironmentConfigurator
|
||||
)
|
||||
|
||||
useAdditionalSourceProviders(
|
||||
::AdditionalDiagnosticsSourceFilesProvider,
|
||||
::CoroutineHelpersSourceFilesProvider,
|
||||
::CodegenHelpersSourceFilesProvider,
|
||||
)
|
||||
|
||||
assertions = JUnit5Assertions
|
||||
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
|
||||
useAdditionalService<BackendKindExtractor>(::BackendKindExtractorImpl)
|
||||
useSourcePreprocessor(*AbstractKotlinCompilerTest.defaultPreprocessors.toTypedArray())
|
||||
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
|
||||
}
|
||||
private fun createTestFiles(file: File, expectedText: String): List<KotlinBaseTest.TestFile> =
|
||||
CodegenTestCase.createTestFilesFromFile(file, expectedText, "kotlin.coroutines", false, TargetBackend.JVM)
|
||||
|
||||
companion object {
|
||||
const val GRADLE_VERSION = "6.8.1" // update GRADLE_SHA_256 on change
|
||||
const val GRADLE_SHA_256 = "fd591a34af7385730970399f473afabdb8b28d57fd97d6625c388d090039d6fd"
|
||||
const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change
|
||||
const val GRADLE_SHA_256 = "1f3067073041bc44554d0efe5d402a33bc3d3c93cc39ab684f308586d732a80d"
|
||||
const val testClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
const val testClassName = "CodegenTestCaseOnAndroid"
|
||||
const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
@@ -434,7 +342,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
|
||||
@Throws(IOException::class)
|
||||
internal fun writeAndroidSkdToLocalProperties(pathManager: PathManager) {
|
||||
val sdkRoot = KtTestUtil.getAndroidSdkSystemIndependentPath()
|
||||
val sdkRoot = KotlinTestUtils.getAndroidSdkSystemIndependentPath()
|
||||
println("Writing android sdk to local.properties: $sdkRoot")
|
||||
val file = File(pathManager.tmpFolder + "/local.properties")
|
||||
FileWriter(file).use { fw -> fw.write("sdk.dir=$sdkRoot") }
|
||||
|
||||
@@ -55,6 +55,16 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
runTestsOnEmulator(gradleRunner, TestSuite("D8")).apply {
|
||||
rootSuite.addTest(this)
|
||||
}
|
||||
|
||||
renameFlavorFolder()
|
||||
enableD8(false)
|
||||
runTestsOnEmulator(gradleRunner, TestSuite("DX")).apply {
|
||||
(0 until this.countTestCases()).forEach {
|
||||
val testCase = testAt(it) as TestCase
|
||||
testCase.name += "_DX"
|
||||
}
|
||||
rootSuite.addTest(this)
|
||||
}
|
||||
} catch (e: RuntimeException) {
|
||||
e.printStackTrace()
|
||||
throw e
|
||||
@@ -71,20 +81,25 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
return rootSuite
|
||||
}
|
||||
|
||||
private fun processReport(rootSuite: TestSuite, resultOutput: String) {
|
||||
private fun enableD8(enable: Boolean) {
|
||||
val file = File(pathManager.androidTmpFolder, "gradle.properties")
|
||||
val lines = file.readLines().map {
|
||||
if (it.startsWith("android.enableD8=")) {
|
||||
"android.enableD8=$enable"
|
||||
} else it
|
||||
}
|
||||
file.writeText(lines.joinToString("\n"))
|
||||
}
|
||||
|
||||
private fun processReport(suite: TestSuite, resultOutput: String) {
|
||||
val reportFolder = File(flavorFolder())
|
||||
try {
|
||||
val folders = reportFolder.listFiles()
|
||||
assertTrue(folders != null && folders.isNotEmpty(), "No folders in ${reportFolder.path}")
|
||||
|
||||
folders.forEach {
|
||||
assertTrue("${it.path} is not directory") { it.isDirectory }
|
||||
val isIr = it.name.contains("_ir")
|
||||
val testCases = parseSingleReportInFolder(it)
|
||||
testCases.forEach { aCase ->
|
||||
if (isIr) aCase.name += "_ir"
|
||||
rootSuite.addTest(aCase)
|
||||
}
|
||||
testCases.forEach { aCase -> suite.addTest(aCase) }
|
||||
Assert.assertNotEquals("There is no test results in report", 0, testCases.size.toLong())
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
@@ -92,6 +107,10 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
}
|
||||
}
|
||||
|
||||
private fun renameFlavorFolder() {
|
||||
val reportFolder = File(flavorFolder())
|
||||
reportFolder.renameTo(File(reportFolder.parentFile, reportFolder.name + "_d8"))
|
||||
}
|
||||
|
||||
private fun flavorFolder() = pathManager.tmpFolder + "/build/test/results/connected/flavors"
|
||||
|
||||
@@ -120,7 +139,7 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
|
||||
private fun cleanAndBuildProject(gradleRunner: GradleRunner) {
|
||||
gradleRunner.clean()
|
||||
gradleRunner.assembleAndroidTest()
|
||||
gradleRunner.build()
|
||||
}
|
||||
|
||||
@Throws(IOException::class, SAXException::class, ParserConfigurationException::class)
|
||||
@@ -139,14 +158,22 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
|
||||
return (0 until testCases.length).map { i ->
|
||||
val item = testCases.item(i) as Element
|
||||
val failure = item.getElementsByTagName("failure").takeIf { it.length != 0 }?.item(0)
|
||||
val failure = item.getElementsByTagName("failure")
|
||||
val name = item.getAttribute("name")
|
||||
val clazz = item.getAttribute("classname")
|
||||
|
||||
object : TestCase(name) {
|
||||
@Throws(Throwable::class)
|
||||
override fun runTest() {
|
||||
if (failure != null) {
|
||||
Assert.fail(failure.textContent)
|
||||
if (failure.length == 0) {
|
||||
object : TestCase(name) {
|
||||
@Throws(Throwable::class)
|
||||
override fun runTest() {
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object : TestCase(name) {
|
||||
@Throws(Throwable::class)
|
||||
override fun runTest() {
|
||||
Assert.fail(failure.item(0).textContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.tests;
|
||||
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -69,7 +69,7 @@ public class PathManager {
|
||||
}
|
||||
|
||||
public String getAndroidSdkRoot() {
|
||||
return KtTestUtil.getAndroidSdkSystemIndependentPath();
|
||||
return KotlinTestUtils.getAndroidSdkSystemIndependentPath();
|
||||
}
|
||||
|
||||
public String getAndroidModuleRoot() {
|
||||
|
||||
@@ -121,11 +121,8 @@ public class Emulator {
|
||||
|
||||
public void startEmulator() {
|
||||
startServer();
|
||||
System.out.println("Starting emulator with ANDROID_HOME/ANDROID_SDK_ROOT: " + pathManager.getAndroidSdkRoot());
|
||||
GeneralCommandLine startCommand = getStartCommand();
|
||||
startCommand.withEnvironment("ANDROID_SDK_ROOT", pathManager.getAndroidSdkRoot());
|
||||
startCommand.withEnvironment("ANDROID_HOME", pathManager.getAndroidSdkRoot());
|
||||
RunUtils.executeOnSeparateThread(new RunUtils.RunSettings(startCommand, null, false, "START: ", true));
|
||||
System.out.println("Starting emulator...");
|
||||
RunUtils.executeOnSeparateThread(new RunUtils.RunSettings(getStartCommand(), null, false, "START: ", true));
|
||||
printLog();
|
||||
}
|
||||
|
||||
@@ -147,7 +144,6 @@ public class Emulator {
|
||||
bootCheckCommand.addParameter("shell");
|
||||
bootCheckCommand.addParameter("getprop");
|
||||
bootCheckCommand.addParameter("sys.boot_completed");
|
||||
|
||||
int counter = 0;
|
||||
RunResult execute = RunUtils.execute(bootCheckCommand);
|
||||
while (counter < 20) {
|
||||
|
||||
@@ -45,9 +45,9 @@ public class GradleRunner {
|
||||
OutputUtils.checkResult(result);
|
||||
}
|
||||
|
||||
public void assembleAndroidTest() {
|
||||
public void build() {
|
||||
System.out.println("Building gradle project...");
|
||||
GeneralCommandLine build = generateCommandLine("assembleAndroidTest");
|
||||
GeneralCommandLine build = generateCommandLine("build");
|
||||
build.addParameter("--stacktrace");
|
||||
build.addParameter("--warn");
|
||||
RunResult result = RunUtils.execute(build);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
// This object should help compiling against different ASM versions in different bunch versions
|
||||
object VersionIndependentOpcodes {
|
||||
const val ACC_RECORD = Opcodes.ACC_RECORD
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
// This object should help compiling against different ASM versions from different bunch versions
|
||||
object VersionIndependentOpcodes {
|
||||
const val ACC_RECORD = 0
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class AsmTypes {
|
||||
private static final Map<Class<?>, Type> TYPES_MAP = new HashMap<>();
|
||||
|
||||
@@ -26,13 +26,13 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
|
||||
|
||||
public abstract class AbstractClassBuilder implements ClassBuilder {
|
||||
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
|
||||
public static final RecordComponentVisitor EMPTY_RECORD_VISITOR = new RecordComponentVisitor(Opcodes.API_VERSION) {};
|
||||
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
|
||||
|
||||
private String thisName;
|
||||
@@ -91,16 +91,6 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
|
||||
return visitor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RecordComponentVisitor newRecordComponent(@NotNull String name, @NotNull String desc, @Nullable String signature) {
|
||||
RecordComponentVisitor visitor = getVisitor().visitRecordComponent(name, desc, signature);
|
||||
if (visitor == null) {
|
||||
return EMPTY_RECORD_VISITOR;
|
||||
}
|
||||
return visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.FileMapping;
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
|
||||
|
||||
public abstract class AbstractClassBuilder implements ClassBuilder {
|
||||
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
|
||||
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
|
||||
|
||||
private String thisName;
|
||||
|
||||
private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
|
||||
|
||||
private String sourceName;
|
||||
|
||||
private String debugInfo;
|
||||
|
||||
public static class Concrete extends AbstractClassBuilder {
|
||||
private final ClassVisitor v;
|
||||
|
||||
public Concrete(@NotNull ClassVisitor v) {
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClassVisitor getVisitor() {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
FieldVisitor visitor = getVisitor().visitField(access, name, desc, signature, value);
|
||||
if (visitor == null) {
|
||||
return EMPTY_FIELD_VISITOR;
|
||||
}
|
||||
return visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
MethodVisitor visitor = getVisitor().visitMethod(access, name, desc, signature, exceptions);
|
||||
if (visitor == null) {
|
||||
return EMPTY_METHOD_VISITOR;
|
||||
}
|
||||
return visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
return serializationBindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
|
||||
return getVisitor().visitAnnotation(desc, visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
getVisitor().visitSource(sourceName, debugInfo);
|
||||
getVisitor().visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
) {
|
||||
thisName = name;
|
||||
getVisitor().visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(@NotNull String name, @Nullable String debug) {
|
||||
assert sourceName == null || sourceName.equals(name) : "inconsistent file name: " + sourceName + " vs " + name;
|
||||
sourceName = name;
|
||||
debugInfo = debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
|
||||
if (!GENERATE_SMAP) return;
|
||||
|
||||
List<FileMapping> fileMappings = smap.getResultMappings();
|
||||
if (fileMappings.isEmpty()) return;
|
||||
|
||||
visitSource(fileMappings.get(0).getName(), SMAPBuilder.INSTANCE.build(fileMappings, backwardsCompatibleSyntax));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
|
||||
getVisitor().visitOuterClass(owner, name, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
|
||||
getVisitor().visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getThisName() {
|
||||
assert thisName != null : "This name isn't set";
|
||||
return thisName;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -498,9 +497,6 @@ public abstract class AnnotationCodegen {
|
||||
public Void visitKClassValue(KClassValue value, Void data) {
|
||||
KotlinType classType = value.getArgumentType(module);
|
||||
innerClassConsumer.addInnerClassInfoFromAnnotation(DescriptorUtils.getClassDescriptorForType(classType));
|
||||
if (InlineClassesUtilsKt.isInlineClassType(classType)) {
|
||||
classType = TypeUtils.makeNullable(classType);
|
||||
}
|
||||
annotationVisitor.visit(name, typeMapper.mapType(classType));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
|
||||
class ArgumentAndDeclIndex(val arg: ResolvedValueArgument, val declIndex: Int)
|
||||
@@ -68,8 +70,12 @@ abstract class ArgumentGenerator {
|
||||
generateExpression(declIndex, argument)
|
||||
}
|
||||
is DefaultValueArgument -> {
|
||||
defaultArgs.mark(declIndex)
|
||||
generateDefault(declIndex, argument)
|
||||
if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) {
|
||||
generateDefaultJava(declIndex, argument)
|
||||
} else {
|
||||
defaultArgs.mark(declIndex)
|
||||
generateDefault(declIndex, argument)
|
||||
}
|
||||
}
|
||||
is VarargValueArgument -> {
|
||||
generateVararg(declIndex, argument)
|
||||
@@ -97,6 +103,10 @@ abstract class ArgumentGenerator {
|
||||
throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument")
|
||||
}
|
||||
|
||||
protected open fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
|
||||
throw UnsupportedOperationException("Unsupported default java argument #$i: $argument")
|
||||
}
|
||||
|
||||
protected open fun generateOther(i: Int, argument: ResolvedValueArgument) {
|
||||
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
|
||||
}
|
||||
@@ -106,6 +116,28 @@ abstract class ArgumentGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.defaultValueFromJava(index: Int): Boolean = DFS.ifAny(
|
||||
listOf(this),
|
||||
{ current -> current.original.overriddenDescriptors.map { it.original } },
|
||||
{ descriptor ->
|
||||
descriptor.original.overriddenDescriptors.isEmpty() &&
|
||||
descriptor is JavaCallableMemberDescriptor &&
|
||||
descriptor.valueParameters[index].declaresDefaultValue()
|
||||
}
|
||||
)
|
||||
|
||||
fun shouldInvokeDefaultArgumentsStub(resolvedCall: ResolvedCall<*>): Boolean {
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
val valueArgumentsByIndex = resolvedCall.valueArgumentsByIndex ?: return false
|
||||
for (index in valueArgumentsByIndex.indices) {
|
||||
val resolvedValueArgument = valueArgumentsByIndex[index]
|
||||
if (resolvedValueArgument is DefaultValueArgument && !descriptor.defaultValueFromJava(index)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getFunctionWithDefaultArguments(functionDescriptor: FunctionDescriptor): FunctionDescriptor {
|
||||
if (functionDescriptor.containingDeclaration !is ClassDescriptor) return functionDescriptor
|
||||
if (functionDescriptor.overriddenDescriptors.isEmpty()) return functionDescriptor
|
||||
@@ -123,4 +155,4 @@ fun getFunctionWithDefaultArguments(functionDescriptor: FunctionDescriptor): Fun
|
||||
function.valueParameters.any { valueParameter -> valueParameter.hasDefaultValue() }
|
||||
}
|
||||
?: functionDescriptor
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,12 @@ class CallBasedArgumentGenerator(
|
||||
callGenerator.putValueIfNeeded(getJvmKotlinType(i), lazyVararg, ValueKind.GENERAL_VARARG, i)
|
||||
}
|
||||
|
||||
override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
|
||||
val argumentValue = valueParameters[i].findJavaDefaultArgumentValue(valueParameterTypes[i], codegen.typeMapper)
|
||||
|
||||
callGenerator.putValueIfNeeded(getJvmKotlinType(i), argumentValue)
|
||||
}
|
||||
|
||||
override fun reorderArgumentsIfNeeded(args: List<ArgumentAndDeclIndex>) {
|
||||
callGenerator.reorderArgumentsIfNeeded(args, valueParameterTypes)
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ class CallableMethod(
|
||||
override val generateCalleeType: Type?,
|
||||
override val returnKotlinType: KotlinType?,
|
||||
val isInterfaceMethod: Boolean,
|
||||
private val isDefaultMethodInInterface: Boolean,
|
||||
private val boxInlineClassBeforeInvoke: Boolean
|
||||
private val isDefaultMethodInInterface: Boolean
|
||||
) : Callable {
|
||||
private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod)
|
||||
|
||||
@@ -50,9 +49,6 @@ class CallableMethod(
|
||||
get() = getAsmMethod().argumentTypes
|
||||
|
||||
override fun genInvokeInstruction(v: InstructionAdapter) {
|
||||
if (boxInlineClassBeforeInvoke) {
|
||||
StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v)
|
||||
}
|
||||
v.visitMethodInsn(
|
||||
invokeOpcode,
|
||||
owner.internalName,
|
||||
|
||||
@@ -19,10 +19,14 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.FileMapping;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface ClassBuilder {
|
||||
@NotNull
|
||||
@@ -45,12 +49,6 @@ public interface ClassBuilder {
|
||||
@Nullable String[] exceptions
|
||||
);
|
||||
|
||||
@NotNull RecordComponentVisitor newRecordComponent(
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature
|
||||
);
|
||||
|
||||
@NotNull
|
||||
JvmSerializationBindings getSerializationBindings();
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
public interface ClassBuilder {
|
||||
@NotNull
|
||||
FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
);
|
||||
|
||||
@NotNull
|
||||
MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
);
|
||||
|
||||
@NotNull
|
||||
JvmSerializationBindings getSerializationBindings();
|
||||
|
||||
@NotNull
|
||||
AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible);
|
||||
|
||||
void done();
|
||||
|
||||
@NotNull
|
||||
ClassVisitor getVisitor();
|
||||
|
||||
void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
);
|
||||
|
||||
void visitSource(@NotNull String name, @Nullable String debug);
|
||||
|
||||
void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax);
|
||||
|
||||
void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc);
|
||||
|
||||
void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access);
|
||||
|
||||
@NotNull
|
||||
String getThisName();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
fun ClassBuilder.addRecordComponent(name: String, desc: String, signature: String?) {
|
||||
newRecordComponent(name, desc, signature)
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
@Suppress("UNUSED_PARAMETER", "unused")
|
||||
fun ClassBuilder.addRecordComponent(name: String, desc: String, signature: String?) {
|
||||
// newRecordComponent(name, desc, signature)
|
||||
}
|
||||
@@ -264,7 +264,7 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
return new MultifileClassCodegenImpl(state, files, facadeFqName);
|
||||
}
|
||||
|
||||
public void registerSourceFiles(@NotNull Collection<KtFile> files) {
|
||||
private void registerSourceFiles(Collection<KtFile> files) {
|
||||
sourceFiles.addAll(toIoFilesIgnoringNonPhysical(files));
|
||||
}
|
||||
|
||||
@@ -272,7 +272,6 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
private static List<File> toIoFilesIgnoringNonPhysical(@NotNull Collection<? extends PsiFile> psiFiles) {
|
||||
List<File> result = new ArrayList<>(psiFiles.size());
|
||||
for (PsiFile psiFile : psiFiles) {
|
||||
if (psiFile == null) continue;
|
||||
VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
// We ignore non-physical files here, because this code is needed to tell the make what inputs affect which outputs
|
||||
// a non-physical file cannot be processed by make
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.jvm.InlineClassManglingRulesKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
@@ -117,9 +118,8 @@ public class ConstructorCodegen {
|
||||
}
|
||||
|
||||
private void registerAccessorForHiddenConstructorIfNeeded(ClassConstructorDescriptor descriptor) {
|
||||
if (DescriptorAsmUtil.isHiddenConstructor(descriptor)) {
|
||||
context.getAccessor(descriptor, AccessorKind.NORMAL, null, null);
|
||||
}
|
||||
if (!InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) return;
|
||||
context.getAccessor(descriptor, AccessorKind.NORMAL, null, null);
|
||||
}
|
||||
|
||||
public void generateSecondaryConstructor(
|
||||
@@ -371,13 +371,11 @@ public class ConstructorCodegen {
|
||||
JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind();
|
||||
if (delegatingKind == JvmMethodParameterKind.VALUE) {
|
||||
assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE:
|
||||
"Delegating constructor has not enough implicit parameters: " + delegatingConstructor;
|
||||
"Delegating constructor has not enough implicit parameters";
|
||||
break;
|
||||
}
|
||||
if (index >= parameters.size() || parameters.get(index).getKind() != delegatingKind) {
|
||||
throw new AssertionError(
|
||||
"Constructors of the same class should have the same set of implicit arguments: " + delegatingConstructor);
|
||||
}
|
||||
assert index < parameters.size() && parameters.get(index).getKind() == delegatingKind :
|
||||
"Constructors of the same class should have the same set of implicit arguments";
|
||||
JvmMethodParameterSignature parameter = parameters.get(index);
|
||||
|
||||
iv.load(offset, parameter.getAsmType());
|
||||
@@ -385,7 +383,7 @@ public class ConstructorCodegen {
|
||||
}
|
||||
|
||||
assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE :
|
||||
"Delegating constructor has not enough parameters: " + delegatingConstructor;
|
||||
"Delegating constructor has not enough parameters";
|
||||
|
||||
return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, delegatingConstructor.getValueParameters(),
|
||||
delegatingCallable.getValueParameterTypes());
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtPureElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
@@ -270,7 +269,6 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
if (classOrObject.isLocal) return false
|
||||
if (classDescriptor.isInlineClass()) return false
|
||||
if (shouldHideConstructorDueToInlineClassTypeValueParameters(constructorDescriptor)) return false
|
||||
if (DescriptorUtils.isSealedClass(classDescriptor)) return false
|
||||
|
||||
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
|
||||
|
||||
|
||||
@@ -19,10 +19,14 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.FileMapping;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public abstract class DelegatingClassBuilder implements ClassBuilder {
|
||||
@NotNull
|
||||
@@ -54,14 +58,6 @@ public abstract class DelegatingClassBuilder implements ClassBuilder {
|
||||
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RecordComponentVisitor newRecordComponent(
|
||||
@NotNull String name, @NotNull String desc, @Nullable String signature
|
||||
) {
|
||||
return getDelegate().newRecordComponent(name, desc, signature);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
public abstract class DelegatingClassBuilder implements ClassBuilder {
|
||||
@NotNull
|
||||
protected abstract ClassBuilder getDelegate();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
return getDelegate().newField(origin, access, name, desc, signature, value);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
return getDelegate().getSerializationBindings();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
|
||||
return getDelegate().newAnnotation(desc, visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
getDelegate().done();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassVisitor getVisitor() {
|
||||
return getDelegate().getVisitor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
) {
|
||||
getDelegate().defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(@NotNull String name, @Nullable String debug) {
|
||||
getDelegate().visitSource(name, debug);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
|
||||
getDelegate().visitSMAP(smap, backwardsCompatibleSyntax);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
|
||||
getDelegate().visitOuterClass(owner, name, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
|
||||
getDelegate().visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getThisName() {
|
||||
return getDelegate().getThisName();
|
||||
}
|
||||
}
|
||||
@@ -61,8 +61,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
|
||||
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineWithReified;
|
||||
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.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -369,18 +368,6 @@ public class DescriptorAsmUtil {
|
||||
return ACC_PRIVATE;
|
||||
}
|
||||
|
||||
// Sealed class constructors should be ACC_PRIVATE.
|
||||
// In 1.4 and before, sealed class constructors had PRIVATE visibility, and were represented as private methods in bytecode.
|
||||
// In 1.5 (+AllowSealedInheritorsInDifferentFilesOfSamePackage), sealed class constructors became INTERNAL,
|
||||
// but still should be represented as private methods in bytecode in order to prevent inheriting from sealed classes on JVM.
|
||||
if (memberDescriptor instanceof ConstructorDescriptor &&
|
||||
!(memberDescriptor instanceof AccessorForConstructorDescriptor) &&
|
||||
isSealedClass(((ConstructorDescriptor) memberDescriptor).getConstructedClass()) &&
|
||||
memberDescriptor.getVisibility() != DescriptorVisibilities.PUBLIC
|
||||
) {
|
||||
return ACC_PRIVATE;
|
||||
}
|
||||
|
||||
if (isInlineOnlyPrivateInBytecode(memberDescriptor)) {
|
||||
return ACC_PRIVATE;
|
||||
}
|
||||
@@ -906,19 +893,4 @@ public class DescriptorAsmUtil {
|
||||
//Trait always should have this descriptor
|
||||
return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1;
|
||||
}
|
||||
|
||||
public static boolean isHiddenConstructor(FunctionDescriptor descriptor) {
|
||||
if (!(descriptor instanceof ClassConstructorDescriptor)) return false;
|
||||
|
||||
ClassConstructorDescriptor classConstructorDescriptor = (ClassConstructorDescriptor) descriptor;
|
||||
if (InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) {
|
||||
return true;
|
||||
}
|
||||
if (isSealedClass(classConstructorDescriptor.getConstructedClass()) &&
|
||||
classConstructorDescriptor.getVisibility() != DescriptorVisibilities.PUBLIC
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
|
||||
@@ -56,13 +55,6 @@ class ErasedInlineClassBodyCodegen(
|
||||
generateUnboxMethod()
|
||||
generateFunctionsFromAny()
|
||||
generateSpecializedEqualsStub()
|
||||
generateJvmInlineAnnotation()
|
||||
}
|
||||
|
||||
private fun generateJvmInlineAnnotation() {
|
||||
if (descriptor.isInline) {
|
||||
v.newAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME.topLevelClassAsmType().descriptor, true).visitEnd()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateFunctionsFromAny() {
|
||||
|
||||
@@ -54,7 +54,6 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.DescriptorBasedTypeSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -74,10 +73,7 @@ import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmConstantsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
|
||||
import org.jetbrains.kotlin.resolve.jvm.*;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
@@ -745,11 +741,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// Some forms of for-loop can be optimized as post-condition loops.
|
||||
PseudoInsnsKt.fakeAlwaysFalseIfeq(v, continueLabel);
|
||||
|
||||
// Renew line number cause it could be reset by inline (resetLastLineNumber) in generator.checkPreCondition(loopExit).
|
||||
markStartLineNumber(generator.getForExpression());
|
||||
v.nop();
|
||||
generator.beforeBody();
|
||||
|
||||
blockStackElements.push(new LoopBlockStackElement(loopExit, continueLabel, targetLabel(generator.getForExpression())));
|
||||
generator.body();
|
||||
blockStackElements.pop();
|
||||
@@ -2412,14 +2404,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
fieldName = KotlinTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty);
|
||||
}
|
||||
|
||||
KotlinType propertyType = propertyDescriptor.getOriginal().getType();
|
||||
if (propertyDescriptor instanceof JavaPropertyDescriptor && InlineClassesUtilsKt.isInlineClassType(propertyType)) {
|
||||
propertyType = TypeUtils.makeNullable(propertyType);
|
||||
}
|
||||
|
||||
return StackValue.property(
|
||||
propertyDescriptor, backingFieldOwner,
|
||||
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyType),
|
||||
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
||||
isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall, skipLateinitAssertion,
|
||||
isDelegatedProperty && forceField ? delegateType : null
|
||||
);
|
||||
@@ -2526,39 +2513,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// $default method is not private, so you need no accessor to call it
|
||||
return descriptor;
|
||||
}
|
||||
else if (shouldForceAccessorForConstructor(descriptor.getOriginal())) {
|
||||
return createAccessorForHiddenConstructor(resolvedCall, descriptor);
|
||||
else if (InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor.getOriginal())) {
|
||||
// Constructors with inline class type value parameters should always be called using an accessor.
|
||||
// NB this will require accessors even if the constructor itself is in a different module.
|
||||
return new AccessorForConstructorDescriptor(
|
||||
(ClassConstructorDescriptor) descriptor.getOriginal(),
|
||||
descriptor.getContainingDeclaration(),
|
||||
getSuperCallTarget(resolvedCall.getCall()),
|
||||
AccessorKind.NORMAL
|
||||
);
|
||||
}
|
||||
else {
|
||||
return context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall()));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldForceAccessorForConstructor(FunctionDescriptor descriptor) {
|
||||
// Force using accessors on hidden constructors only
|
||||
if (!isHiddenConstructor(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
// Don't use accessor when calling hidden constructor from the same class.
|
||||
if (descriptor.getContainingDeclaration() == context.getContextDescriptor().getContainingDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AccessorForConstructorDescriptor createAccessorForHiddenConstructor(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
FunctionDescriptor descriptor
|
||||
) {
|
||||
return new AccessorForConstructorDescriptor(
|
||||
(ClassConstructorDescriptor) descriptor.getOriginal(),
|
||||
descriptor.getContainingDeclaration(),
|
||||
getSuperCallTarget(resolvedCall.getCall()),
|
||||
AccessorKind.NORMAL
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue invokeFunction(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
|
||||
return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver);
|
||||
@@ -2693,7 +2662,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall<?> resolvedCall) {
|
||||
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall resolvedCall) {
|
||||
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd);
|
||||
if (intrinsic != null) {
|
||||
return intrinsic.toCallable(fd, superCall, resolvedCall, this);
|
||||
@@ -2701,8 +2670,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
fd = SamCodegenUtil.resolveSamAdapter(fd);
|
||||
|
||||
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
|
||||
if (valueArguments != null && valueArguments.stream().anyMatch(it -> it instanceof DefaultValueArgument)) {
|
||||
if (ArgumentGeneratorKt.shouldInvokeDefaultArgumentsStub(resolvedCall)) {
|
||||
// When we invoke a function with some arguments mapped as defaults,
|
||||
// we later reroute this call to an overridden function in a base class that processes the default arguments.
|
||||
// If the base class is generic, this overridden function can have a different Kotlin signature
|
||||
@@ -4407,10 +4375,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
Type exprType = expressionType(expr);
|
||||
KotlinType exprKotlinType = kotlinType(expr);
|
||||
if (exprKotlinType != null && InlineClassesUtilsKt.isInlineClassType(exprKotlinType) &&
|
||||
FlexibleTypesKt.isNullabilityFlexible(exprKotlinType)) {
|
||||
exprKotlinType = TypeUtils.makeNullable(exprKotlinType);
|
||||
}
|
||||
StackValue value;
|
||||
if (compileTimeConstant != null) {
|
||||
value = StackValue.constant(compileTimeConstant.getValue(), exprType, exprKotlinType);
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.annotations.ThrowUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
@@ -1105,7 +1105,7 @@ public class FunctionCodegen {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(ThrowUtilKt.JVM_THROWS_ANNOTATION_FQ_NAME);
|
||||
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(AnnotationUtilKt.JVM_THROWS_ANNOTATION_FQ_NAME);
|
||||
if (annotation == null) return Collections.emptyList();
|
||||
|
||||
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
|
||||
@@ -1221,12 +1221,7 @@ public class FunctionCodegen {
|
||||
|
||||
// 'null' because the "could not find expected declaration" error has been already reported in isDefaultNeeded earlier
|
||||
List<ValueParameterDescriptor> valueParameters =
|
||||
functionDescriptor.isSuspend()
|
||||
? CollectionsKt.plus(
|
||||
CodegenUtil.getFunctionParametersForDefaultValueGeneration(
|
||||
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(functionDescriptor), null),
|
||||
CollectionsKt.last(functionDescriptor.getValueParameters()))
|
||||
: CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null);
|
||||
CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null);
|
||||
|
||||
boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
|
||||
FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic);
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
|
||||
@@ -222,10 +221,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
access |= ACC_ENUM;
|
||||
}
|
||||
|
||||
if (JvmAnnotationUtilKt.isJvmRecord(descriptor)) {
|
||||
access |= VersionIndependentOpcodes.ACC_RECORD;
|
||||
}
|
||||
|
||||
v.defineClass(
|
||||
myClass.getPsiOrParent(),
|
||||
state.getClassFileVersion(),
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl;
|
||||
@@ -84,9 +83,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
|
||||
|
||||
private final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<>();
|
||||
private final Collection<SyntheticInnerClassInfo> syntheticInnerClasses = new LinkedHashSet<>();
|
||||
|
||||
private ExpressionCodegen clInit;
|
||||
private NameGenerator inlineNameGenerator;
|
||||
@@ -319,10 +316,6 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
genClassOrObject(context, descriptor.getSyntheticDeclaration(), state, this, descriptor);
|
||||
}
|
||||
|
||||
public void addSyntheticAnonymousInnerClass(SyntheticInnerClassInfo syntheticInnerClassInfo) {
|
||||
syntheticInnerClasses.add(syntheticInnerClassInfo);
|
||||
}
|
||||
|
||||
private void writeInnerClasses() {
|
||||
// JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
|
||||
// for each enclosing class and for each immediate member
|
||||
@@ -338,9 +331,6 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
for (ClassDescriptor innerClass : innerClasses) {
|
||||
writeInnerClass(innerClass);
|
||||
}
|
||||
for (SyntheticInnerClassInfo syntheticInnerClass : syntheticInnerClasses) {
|
||||
v.visitInnerClass(syntheticInnerClass.getInternalName(), null, null, syntheticInnerClass.getFlags());
|
||||
}
|
||||
}
|
||||
|
||||
protected void addParentsToInnerClassesIfNeeded(@NotNull Collection<ClassDescriptor> innerClasses) {
|
||||
@@ -386,12 +376,18 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
|
||||
protected void writeOuterClassAndEnclosingMethod() {
|
||||
CodegenContext<?> context = getNonInlineOuterContext(this.context.getParentContext());
|
||||
CodegenContext context = this.context.getParentContext();
|
||||
|
||||
while (context instanceof InlineLambdaContext) {
|
||||
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
|
||||
//noinspection ConstantConditions
|
||||
context = context.getParentContext().getParentContext();
|
||||
}
|
||||
assert context != null : "Outermost context can't be null: " + this.context;
|
||||
|
||||
Type enclosingAsmType = computeOuterClass(typeMapper, state.getJvmDefaultMode(), element, context);
|
||||
Type enclosingAsmType = computeOuterClass(context);
|
||||
if (enclosingAsmType != null) {
|
||||
Method method = computeEnclosingMethod(typeMapper, context);
|
||||
Method method = computeEnclosingMethod(context);
|
||||
|
||||
v.visitOuterClass(
|
||||
enclosingAsmType.getInternalName(),
|
||||
@@ -401,31 +397,15 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
}
|
||||
|
||||
public static CodegenContext<?> getNonInlineOuterContext(CodegenContext<?> parentContext) {
|
||||
CodegenContext<?> context = parentContext;
|
||||
while (context instanceof InlineLambdaContext) {
|
||||
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
|
||||
//noinspection ConstantConditions
|
||||
context = context.getParentContext().getParentContext();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Type computeOuterClass(
|
||||
@NotNull KotlinTypeMapper typeMapper,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode,
|
||||
@NotNull KtPureElement element,
|
||||
@NotNull CodegenContext<?> context
|
||||
) {
|
||||
private Type computeOuterClass(@NotNull CodegenContext<?> context) {
|
||||
CodegenContext<? extends ClassOrPackageFragmentDescriptor> outermost = context.getClassOrPackageParentContext();
|
||||
if (outermost instanceof ClassContext) {
|
||||
ClassDescriptor classDescriptor = ((ClassContext) outermost).getContextDescriptor();
|
||||
if (context instanceof MethodContext) {
|
||||
FunctionDescriptor functionDescriptor = ((MethodContext) context).getFunctionDescriptor();
|
||||
if (isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||
!JvmAnnotationUtilKt.isCompiledToJvmDefault(functionDescriptor, jvmDefaultMode)
|
||||
) {
|
||||
if (isInterface(functionDescriptor.getContainingDeclaration()) && !JvmAnnotationUtilKt
|
||||
.isCompiledToJvmDefault(functionDescriptor, state.getJvmDefaultMode())) {
|
||||
return typeMapper.mapDefaultImpls(classDescriptor);
|
||||
}
|
||||
}
|
||||
@@ -445,7 +425,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Method computeEnclosingMethod(@NotNull KotlinTypeMapper typeMapper, @NotNull CodegenContext context) {
|
||||
private Method computeEnclosingMethod(@NotNull CodegenContext context) {
|
||||
if (context instanceof MethodContext) {
|
||||
FunctionDescriptor functionDescriptor = ((MethodContext) context).getFunctionDescriptor();
|
||||
if ("<clinit>".equals(functionDescriptor.getName().asString())) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
internal class ObjectSuperCallArgumentGenerator(
|
||||
@@ -64,6 +65,12 @@ internal class ObjectSuperCallArgumentGenerator(
|
||||
pushDefaultValueOnStack(type, iv)
|
||||
}
|
||||
|
||||
public override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
|
||||
val type = parameters[i].asmType
|
||||
val value = superValueParameters[i].findJavaDefaultArgumentValue(type, typeMapper)
|
||||
value.put(type, iv)
|
||||
}
|
||||
|
||||
public override fun generateVararg(i: Int, argument: VarargValueArgument) {
|
||||
generateSuperCallArgument(i)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class OriginCollectingClassBuilderFactory(private val builderMode: ClassBuilderM
|
||||
}
|
||||
|
||||
override fun asBytes(builder: ClassBuilder): ByteArray {
|
||||
val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES or ClassWriter.COMPUTE_MAXS)
|
||||
val classWriter = ClassWriter(0)
|
||||
(builder as OriginCollectingClassBuilder).classNode.accept(classWriter)
|
||||
return classWriter.toByteArray()
|
||||
}
|
||||
@@ -66,4 +66,4 @@ class OriginCollectingClassBuilderFactory(private val builderMode: ClassBuilderM
|
||||
override fun asText(builder: ClassBuilder) = throw UnsupportedOperationException()
|
||||
|
||||
override fun close() {}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
@@ -436,10 +435,9 @@ public class PropertyCodegen {
|
||||
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, new Pair<>(type, name));
|
||||
|
||||
if (isBackingFieldOwner) {
|
||||
String signature = isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor);
|
||||
FieldVisitor fv = builder.newField(
|
||||
JvmDeclarationOriginKt.OtherOrigin(propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
signature, defaultValue
|
||||
isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor), defaultValue
|
||||
);
|
||||
|
||||
if (annotatedField != null) {
|
||||
@@ -452,10 +450,6 @@ public class PropertyCodegen {
|
||||
AnnotationCodegen.forField(fv, memberCodegen, state, skipNullabilityAnnotations)
|
||||
.genAnnotations(annotatedField, type, propertyDescriptor.getType(), null, additionalVisibleAnnotations);
|
||||
}
|
||||
|
||||
if (propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor && JvmAnnotationUtilKt.isJvmRecord((ClassDescriptor) propertyDescriptor.getContainingDeclaration())) {
|
||||
ClassBuilderRecordKt.addRecordComponent(builder, name, type.getDescriptor(), signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,8 @@ import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
@@ -65,7 +62,6 @@ public class SamWrapperCodegen {
|
||||
private final SamType samType;
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final int visibility;
|
||||
private final int classFlags;
|
||||
public static final String SAM_WRAPPER_SUFFIX = "$0";
|
||||
|
||||
public SamWrapperCodegen(
|
||||
@@ -80,8 +76,6 @@ public class SamWrapperCodegen {
|
||||
this.samType = samType;
|
||||
this.parentCodegen = parentCodegen;
|
||||
visibility = isInsideInline ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE;
|
||||
int synth = state.getLanguageVersionSettings().supportsFeature(LanguageFeature.SamWrapperClassesAreSynthetic) ? ACC_SYNTHETIC : 0;
|
||||
classFlags = visibility | ACC_FINAL | ACC_SUPER | synth;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -127,7 +121,7 @@ public class SamWrapperCodegen {
|
||||
cv.defineClass(
|
||||
file,
|
||||
state.getClassFileVersion(),
|
||||
classFlags,
|
||||
ACC_FINAL | ACC_SUPER | visibility,
|
||||
asmType.getInternalName(),
|
||||
null,
|
||||
OBJECT_TYPE.getInternalName(),
|
||||
@@ -137,8 +131,6 @@ public class SamWrapperCodegen {
|
||||
|
||||
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv, state);
|
||||
|
||||
generateInnerClassInformation(file, asmType, cv);
|
||||
|
||||
// e.g. ASM type for Function2
|
||||
Type functionAsmType = typeMapper.mapType(functionType);
|
||||
|
||||
@@ -168,24 +160,6 @@ public class SamWrapperCodegen {
|
||||
return asmType;
|
||||
}
|
||||
|
||||
private void generateInnerClassInformation(@NotNull KtFile file, Type asmType, ClassBuilder cv) {
|
||||
parentCodegen.addSyntheticAnonymousInnerClass(new SyntheticInnerClassInfo(asmType.getInternalName(), classFlags));
|
||||
FieldOwnerContext<?> parentContext = parentCodegen.context;
|
||||
CodegenContext<?> outerContext = MemberCodegen.getNonInlineOuterContext(parentContext);
|
||||
assert outerContext != null :
|
||||
"Outer context for SAM wrapper " + asmType.getInternalName() + " is null, parentContext:" + parentContext;
|
||||
Type outerClassType = MemberCodegen.computeOuterClass(state.getTypeMapper(), state.getJvmDefaultMode(), file, outerContext);
|
||||
assert outerClassType != null :
|
||||
"Outer class for SAM wrapper " + asmType.getInternalName() + " is null, parentContext:" + parentContext;
|
||||
Method enclosingMethod = MemberCodegen.computeEnclosingMethod(state.getTypeMapper(), outerContext);
|
||||
cv.visitOuterClass(
|
||||
outerClassType.getInternalName(),
|
||||
enclosingMethod == null ? null : enclosingMethod.getName(),
|
||||
enclosingMethod == null ? null : enclosingMethod.getDescriptor()
|
||||
);
|
||||
cv.visitInnerClass(asmType.getInternalName(), null, null, classFlags);
|
||||
}
|
||||
|
||||
private void generateConstructor(Type ownerType, Type functionType, ClassBuilder cv) {
|
||||
MethodVisitor mv = cv.newMethod(JvmDeclarationOriginKt.OtherOrigin(samType.getClassDescriptor()),
|
||||
visibility, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), null, null);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.containers.LinkedMultiMap
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.codegen.state.JvmMethodExceptionTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
||||
@@ -48,7 +49,7 @@ abstract class SignatureCollectingClassBuilderFactory(
|
||||
|
||||
private lateinit var classInternalName: String
|
||||
|
||||
private val signatures = MultiMap.createLinked<RawSignature, JvmDeclarationOrigin>()
|
||||
private val signatures = LinkedMultiMap<RawSignature, JvmDeclarationOrigin>()
|
||||
|
||||
override fun defineClass(origin: PsiElement?, version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<out String>) {
|
||||
classInternalName = name
|
||||
|
||||
@@ -629,11 +629,7 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
public static void coerce(@NotNull Type fromType, @NotNull Type toType, @NotNull InstructionAdapter v) {
|
||||
coerce(fromType, toType, v, false);
|
||||
}
|
||||
|
||||
public static void coerce(@NotNull Type fromType, @NotNull Type toType, @NotNull InstructionAdapter v, boolean forceSelfCast) {
|
||||
if (toType.equals(fromType) && !forceSelfCast) return;
|
||||
if (toType.equals(fromType)) return;
|
||||
|
||||
if (toType.getSort() == Type.VOID) {
|
||||
pop(v, fromType);
|
||||
|
||||
@@ -5,7 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.unboxPrimitiveTypeOrNull
|
||||
import org.jetbrains.kotlin.codegen.StackValue.*
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.Constant
|
||||
import org.jetbrains.kotlin.load.java.EnumEntry
|
||||
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
|
||||
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getDefaultValueFromAnnotation
|
||||
import org.jetbrains.kotlin.load.java.lexicalCastFrom
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -75,3 +86,40 @@ class FunctionCallStackValue(
|
||||
resultKotlinType: KotlinType?,
|
||||
lambda: (v: InstructionAdapter) -> Unit
|
||||
) : OperationStackValue(resultType, resultKotlinType, lambda)
|
||||
|
||||
fun ValueParameterDescriptor.findJavaDefaultArgumentValue(targetType: Type, typeMapper: KotlinTypeMapper): StackValue {
|
||||
val descriptorWithDefaultValue = DFS.dfs(
|
||||
listOf(this.original),
|
||||
{ it.original.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
|
||||
object : DFS.AbstractNodeHandler<ValueParameterDescriptor, ValueParameterDescriptor?>() {
|
||||
var result: ValueParameterDescriptor? = null
|
||||
|
||||
override fun beforeChildren(current: ValueParameterDescriptor?): Boolean {
|
||||
if (current?.declaresDefaultValue() == true && current.getDefaultValueFromAnnotation() != null) {
|
||||
result = current
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun result(): ValueParameterDescriptor? = result
|
||||
}
|
||||
) ?: error("Should be at least one descriptor with default value: $this")
|
||||
|
||||
val defaultValue = descriptorWithDefaultValue.getDefaultValueFromAnnotation()
|
||||
if (defaultValue is NullDefaultValue) {
|
||||
return constant(null, targetType)
|
||||
}
|
||||
|
||||
val value = (defaultValue as StringDefaultValue).value
|
||||
val castResult = type.lexicalCastFrom(value) ?: error("Should be checked in frontend")
|
||||
|
||||
return when (castResult) {
|
||||
is EnumEntry -> enumEntry(castResult.descriptor, typeMapper)
|
||||
is Constant -> {
|
||||
val unboxedType = unboxPrimitiveTypeOrNull(targetType) ?: targetType
|
||||
return coercion(constant(castResult.value, unboxedType), targetType, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
data class SyntheticInnerClassInfo(val internalName: String, val flags: Int)
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.cfg.index
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
@@ -34,7 +35,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.indexOrMinusOne
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
@@ -263,7 +263,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
private fun ParameterDescriptor.isUnused(): Boolean =
|
||||
originalSuspendFunctionDescriptor is AnonymousFunctionDescriptor &&
|
||||
bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to indexOrMinusOne()] != true
|
||||
bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to index()] != true
|
||||
|
||||
private val generateErasedCreate: Boolean = allFunctionParameters().size <= 1
|
||||
|
||||
|
||||
@@ -1113,7 +1113,7 @@ inline fun withInstructionAdapter(block: InstructionAdapter.() -> Unit): InsnLis
|
||||
return tmpMethodNode.instructions
|
||||
}
|
||||
|
||||
fun Type.normalize() =
|
||||
internal fun Type.normalize() =
|
||||
when (sort) {
|
||||
Type.ARRAY, Type.OBJECT -> AsmTypes.OBJECT_TYPE
|
||||
else -> this
|
||||
@@ -1222,9 +1222,8 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
oldLvt += record
|
||||
}
|
||||
method.localVariables.clear()
|
||||
// Skip `this` for suspend lambda
|
||||
// Skip `this` for suspend lamdba
|
||||
val start = if (isForNamedFunction) 0 else 1
|
||||
val oldLvtNodeToLatestNewLvtNode = mutableMapOf<LocalVariableNode, LocalVariableNode>()
|
||||
for (variableIndex in start until method.maxLocals) {
|
||||
if (oldLvt.none { it.index == variableIndex }) continue
|
||||
var startLabel: LabelNode? = null
|
||||
@@ -1240,15 +1239,25 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue
|
||||
// startLabel can be null in case of parameters
|
||||
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
|
||||
// Attempt to extend existing local variable node corresponding to the record in
|
||||
// the original local variable table.
|
||||
var recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
|
||||
if (recordToExtend != null && InsnSequence(recordToExtend.end, startLabel).none { isBeforeSuspendMarker(it) }) {
|
||||
var recordToExtend: LocalVariableNode? = null
|
||||
for (record in method.localVariables) {
|
||||
if (record.name == lvtRecord.name &&
|
||||
record.desc == lvtRecord.desc &&
|
||||
record.signature == lvtRecord.signature &&
|
||||
record.index == lvtRecord.index
|
||||
) {
|
||||
if (InsnSequence(record.end, startLabel).none { isBeforeSuspendMarker(it) }) {
|
||||
recordToExtend = record
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (recordToExtend != null) {
|
||||
recordToExtend.end = endLabel
|
||||
} else {
|
||||
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
|
||||
method.localVariables.add(node)
|
||||
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
|
||||
method.localVariables.add(
|
||||
LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,10 +90,7 @@ class AnonymousObjectTransformer(
|
||||
val node = MethodNode(access, name, desc, signature, exceptions)
|
||||
if (name == "<init>") {
|
||||
if (constructor != null) {
|
||||
throw RuntimeException(
|
||||
"Lambda, SAM or anonymous object should have only one constructor.\n" +
|
||||
"First:\n${constructor.nodeText}\n\nSecond:\n${node.nodeText}\n"
|
||||
)
|
||||
throw RuntimeException("Lambda, SAM or anonymous object should have only one constructor")
|
||||
}
|
||||
constructor = node
|
||||
} else {
|
||||
@@ -322,7 +319,7 @@ class AnonymousObjectTransformer(
|
||||
), null
|
||||
)
|
||||
|
||||
val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
|
||||
val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, ReturnLabelOwner.NOT_APPLICABLE)
|
||||
result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify)
|
||||
deferringVisitor.visitMaxs(-1, -1)
|
||||
return result
|
||||
@@ -465,29 +462,6 @@ class AnonymousObjectTransformer(
|
||||
val indexToFunctionalArgument = transformationInfo.functionalArguments
|
||||
val capturedParams = HashSet<Int>()
|
||||
|
||||
// Possible cases where we need to add each lambda's captures separately:
|
||||
//
|
||||
// 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we
|
||||
// have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty
|
||||
// (already have the fields) or contains the parent lambda object (captures used to be read from it, but
|
||||
// the object will be removed and its contents inlined).
|
||||
//
|
||||
// 2. Top-level object in a named inline function. Again, there's no option but to add separate fields.
|
||||
// `capturedLambdas` contains all lambdas used by this object and nested objects.
|
||||
//
|
||||
// 3. Nested object, either in an inline lambda or an inline function. This case has two subcases:
|
||||
// * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda);
|
||||
// we *could* group them into `this$0` now, but choose not to. Lambdas are replaced by their captures to match.
|
||||
// * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in
|
||||
// inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is
|
||||
// empty anyway.
|
||||
//
|
||||
// The only remaining case is a top-level object inside a (crossinline) lambda that is inlined into another object.
|
||||
// Then, the reference to the soon-to-be-removed lambda class containing the captures (and it exists, or else the object
|
||||
// would not have needed regeneration in the first place) is simply replaced with a reference to the outer object, and
|
||||
// that object will contain loose fields for everything we need to capture.
|
||||
val topLevelInCrossinlineLambda = parentFieldRemapper is InlinedLambdaRemapper && !parentFieldRemapper.parent!!.isRoot
|
||||
|
||||
//load captured parameters and patch instruction list
|
||||
// NB: there is also could be object fields
|
||||
val toDelete = arrayListOf<AbstractInsnNode>()
|
||||
@@ -496,12 +470,10 @@ class AnonymousObjectTransformer(
|
||||
val parameterAload = fieldNode.previous as VarInsnNode
|
||||
val varIndex = parameterAload.`var`
|
||||
val functionalArgument = indexToFunctionalArgument[varIndex]
|
||||
// If an outer `this` is already captured by this object, rename it if any inline lambda will capture
|
||||
// one of the same type, causing the code below to create a clash. Note that the values can be different.
|
||||
// TODO: this is only really necessary if there will be a name *and* type clash.
|
||||
val shouldRename = !topLevelInCrossinlineLambda && isThis0(fieldName) &&
|
||||
indexToFunctionalArgument.values.any { it is LambdaInfo && it.capturedVars.any { it.fieldName == fieldName } }
|
||||
val newFieldName = if (shouldRename) addUniqueField(fieldName + INLINE_FUN_THIS_0_SUFFIX) else fieldName
|
||||
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToFunctionalArgument.values))
|
||||
getNewFieldName(fieldName, true)
|
||||
else
|
||||
fieldName
|
||||
val info = capturedParamBuilder.addCapturedParam(
|
||||
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
|
||||
Type.getType(fieldNode.desc), functionalArgument is LambdaInfo, null
|
||||
@@ -536,17 +508,35 @@ class AnonymousObjectTransformer(
|
||||
//For all inlined lambdas add their captured parameters
|
||||
//TODO: some of such parameters could be skipped - we should perform additional analysis
|
||||
val allRecapturedParameters = ArrayList<CapturedParamDesc>()
|
||||
if (!topLevelInCrossinlineLambda) {
|
||||
val capturedOuterThisTypes = mutableSetOf<String>()
|
||||
if (parentFieldRemapper !is InlinedLambdaRemapper || parentFieldRemapper.parent!!.isRoot) {
|
||||
// Possible cases:
|
||||
//
|
||||
// 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we
|
||||
// have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty
|
||||
// (already have the fields) or contains the parent lambda object (captures used to be read from it, but
|
||||
// the object will be removed and its contents inlined).
|
||||
//
|
||||
// 2. Top-level object in a named inline function. Again, there's no option but to add separate fields.
|
||||
// `capturedLambdas` contains all lambdas used by this object and nested objects.
|
||||
//
|
||||
// 3. Nested object, either in an inline lambda or an inline function. This case has two subcases:
|
||||
// * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda);
|
||||
// we could group them into `this$0` now, but choose not to. Lambdas are replaced by their captures.
|
||||
// * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in
|
||||
// inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is
|
||||
// empty and the choice doesn't matter.
|
||||
//
|
||||
val alreadyAdded = HashMap<String, CapturedParamInfo>()
|
||||
for (info in capturedLambdas) {
|
||||
for (desc in info.capturedVars) {
|
||||
// Merge all outer `this` of the same type captured by inlined lambdas, since they have to be the same
|
||||
// object. Outer `this` captured by the original object itself should have been renamed above,
|
||||
// and can have a different value even if the same type is captured by a lambda.
|
||||
val recapturedParamInfo = if (isThis0(desc.fieldName))
|
||||
capturedParamBuilder.addCapturedParam(desc, desc.fieldName, !capturedOuterThisTypes.add(desc.type.className))
|
||||
else
|
||||
capturedParamBuilder.addCapturedParam(desc, addUniqueField(desc.fieldName + INLINE_TRANSFORMATION_SUFFIX), false)
|
||||
val key = desc.fieldName + "$$$" + desc.type.className
|
||||
val alreadyAddedParam = alreadyAdded[key]
|
||||
|
||||
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(
|
||||
desc,
|
||||
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
|
||||
alreadyAddedParam != null
|
||||
)
|
||||
if (info is ExpressionLambda && info.isCapturedSuspend(desc)) {
|
||||
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend
|
||||
}
|
||||
@@ -561,6 +551,10 @@ class AnonymousObjectTransformer(
|
||||
allRecapturedParameters.add(desc)
|
||||
|
||||
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.newFieldName).remapValue = composed
|
||||
|
||||
if (isThis0(desc.fieldName)) {
|
||||
alreadyAdded.put(key, recapturedParamInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (capturedLambdas.isNotEmpty()) {
|
||||
@@ -585,6 +579,24 @@ class AnonymousObjectTransformer(
|
||||
return constructorAdditionalFakeParams
|
||||
}
|
||||
|
||||
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<FunctionalArgument>): Boolean {
|
||||
return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
|
||||
values.any { it is LambdaInfo && it.capturedVars.any { isThis0(it.fieldName) } }
|
||||
} else false
|
||||
}
|
||||
|
||||
private fun getNewFieldName(oldName: String, originalField: Boolean): String {
|
||||
if (AsmUtil.CAPTURED_THIS_FIELD == oldName) {
|
||||
return if (!originalField) {
|
||||
oldName
|
||||
} else {
|
||||
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
|
||||
addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX)
|
||||
}
|
||||
}
|
||||
return addUniqueField(oldName + INLINE_TRANSFORMATION_SUFFIX)
|
||||
}
|
||||
|
||||
private fun addUniqueField(name: String): String {
|
||||
val existNames = fieldNames.getOrPut(name) { LinkedList() }
|
||||
val suffix = if (existNames.isEmpty()) "" else "$" + existNames.size
|
||||
@@ -592,4 +604,7 @@ class AnonymousObjectTransformer(
|
||||
existNames.add(newName)
|
||||
return newName
|
||||
}
|
||||
|
||||
private fun isFirstDeclSiteLambdaFieldRemapper(parentRemapper: FieldRemapper): Boolean =
|
||||
parentRemapper !is RegeneratedLambdaFieldRemapper && parentRemapper !is InlinedLambdaRemapper
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.Position
|
||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -41,6 +41,8 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
import kotlin.math.max
|
||||
|
||||
abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
@@ -134,7 +136,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
) {
|
||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||
try {
|
||||
nodeAndSmap = createInlineMethodNode(mapDefaultSignature, typeArguments, typeSystem)
|
||||
nodeAndSmap = createInlineMethodNode(
|
||||
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
|
||||
)
|
||||
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
|
||||
} catch (e: CompilationException) {
|
||||
throw e
|
||||
@@ -240,10 +244,12 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
//hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain
|
||||
adapter.visitInsn(Opcodes.NOP)
|
||||
|
||||
val result = inliner.doInline(adapter, remapper, true, mapOf())
|
||||
val result = inliner.doInline(adapter, remapper, true, ReturnLabelOwner.SKIP_ALL)
|
||||
result.reifiedTypeParametersUsages.mergeAll(reificationResult)
|
||||
|
||||
val infos = MethodInliner.processReturns(adapter, sourceCompiler.getContextLabels(), null)
|
||||
val labels = sourceCompiler.getContextLabels()
|
||||
|
||||
val infos = MethodInliner.processReturns(adapter, ReturnLabelOwner { labels.contains(it) }, true, null)
|
||||
generateAndInsertFinallyBlocks(
|
||||
adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index
|
||||
)
|
||||
@@ -268,8 +274,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
|
||||
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
|
||||
|
||||
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
|
||||
|
||||
fun generateAndInsertFinallyBlocks(
|
||||
intoNode: MethodNode,
|
||||
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
|
||||
@@ -314,9 +318,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
frameMap.enterTemp(Type.INT_TYPE)
|
||||
}
|
||||
|
||||
sourceCompiler.generateFinallyBlocksIfNeeded(
|
||||
finallyCodegen, extension.returnType, extension.finallyIntervalEnd.label, extension.jumpTarget
|
||||
)
|
||||
sourceCompiler.generateFinallyBlocksIfNeeded(finallyCodegen, extension.returnType, extension.finallyIntervalEnd.label)
|
||||
|
||||
//Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
|
||||
insertNodeBefore(finallyNode, intoNode, curInstr)
|
||||
@@ -510,42 +512,38 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
}
|
||||
|
||||
|
||||
internal fun createInlineMethodNode(
|
||||
callDefault: Boolean,
|
||||
typeArguments: List<TypeParameterMarker>?,
|
||||
typeSystem: TypeSystemCommonBackendContext
|
||||
): SMAPAndMethodNode {
|
||||
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
|
||||
if (intrinsic != null) {
|
||||
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
|
||||
}
|
||||
|
||||
var asmMethod = mapMethod(callDefault)
|
||||
if (asmMethod.name.contains("-") &&
|
||||
!state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME) &&
|
||||
classFileContainsMethod(functionDescriptor, state, asmMethod) == false
|
||||
) {
|
||||
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = true
|
||||
asmMethod = mapMethod(callDefault)
|
||||
state.typeMapper.useOldManglingRulesForFunctionAcceptingInlineClass = false
|
||||
}
|
||||
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
|
||||
val node = sourceCompiler.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
|
||||
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
return node
|
||||
}
|
||||
|
||||
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
|
||||
}
|
||||
|
||||
private fun mapMethod(callDefault: Boolean): Method =
|
||||
if (callDefault) state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
|
||||
else mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
|
||||
|
||||
companion object {
|
||||
|
||||
internal fun createInlineMethodNode(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
methodOwner: Type,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
callDefault: Boolean,
|
||||
typeArguments: List<TypeParameterMarker>?,
|
||||
typeSystem: TypeSystemCommonBackendContext,
|
||||
state: GenerationState,
|
||||
sourceCompilerForInline: SourceCompilerForInline
|
||||
): SMAPAndMethodNode {
|
||||
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
|
||||
if (intrinsic != null) {
|
||||
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
|
||||
}
|
||||
|
||||
val asmMethod = if (callDefault)
|
||||
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
|
||||
else
|
||||
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
|
||||
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DescriptorWithContainerSource) {
|
||||
val node = sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
|
||||
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
return node
|
||||
}
|
||||
|
||||
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
|
||||
}
|
||||
|
||||
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
|
||||
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
|
||||
assert(directMember is DescriptorWithContainerSource) {
|
||||
@@ -579,8 +577,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod)
|
||||
else
|
||||
null
|
||||
result ?:
|
||||
throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
|
||||
result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
|
||||
}
|
||||
|
||||
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)
|
||||
@@ -636,17 +633,35 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
?: throw IllegalStateException("Couldn't find declaration file for $containerId")
|
||||
}
|
||||
|
||||
val methodNode = getMethodNodeInner(containerId, bytes, asmMethod, callableDescriptor) ?: return null
|
||||
|
||||
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
|
||||
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
||||
if (isLegacySuspendInlineFunction(callableDescriptor)) {
|
||||
insertLegacySuspendInlineMarks(methodNode.node)
|
||||
}
|
||||
|
||||
return methodNode
|
||||
}
|
||||
|
||||
private fun getMethodNodeInner(
|
||||
containerId: ClassId,
|
||||
bytes: ByteArray,
|
||||
asmMethod: Method,
|
||||
callableDescriptor: CallableMemberDescriptor
|
||||
): SMAPAndMethodNode? {
|
||||
val classType = AsmUtil.asmTypeByClassId(containerId)
|
||||
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType)
|
||||
var methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType)
|
||||
if (methodNode == null && requiresFunctionNameManglingForReturnType(callableDescriptor)) {
|
||||
val nameWithoutManglingSuffix = asmMethod.name.stripManglingSuffixOrNull()
|
||||
if (nameWithoutManglingSuffix != null) {
|
||||
val methodWithoutMangling = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType)
|
||||
if (methodWithoutMangling != null) return methodWithoutMangling
|
||||
methodNode = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType)
|
||||
}
|
||||
if (methodNode == null) {
|
||||
val nameWithImplSuffix = "$nameWithoutManglingSuffix-impl"
|
||||
methodNode = getMethodNode(bytes, nameWithImplSuffix, asmMethod.descriptor, classType)
|
||||
}
|
||||
return getMethodNode(bytes, "$nameWithoutManglingSuffix-impl", asmMethod.descriptor, classType)
|
||||
}
|
||||
|
||||
return methodNode
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class InlineCodegenForDefaultBody(
|
||||
@@ -39,10 +41,8 @@ class InlineCodegenForDefaultBody(
|
||||
}
|
||||
|
||||
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
||||
val nodeAndSmap = PsiInlineCodegen(
|
||||
codegen, state, function, methodOwner, jvmSignature, TypeParameterMappings(), sourceCompilerForInline
|
||||
).createInlineMethodNode(
|
||||
callDefault, null, codegen.typeSystem
|
||||
val nodeAndSmap = InlineCodegen.createInlineMethodNode(
|
||||
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline
|
||||
)
|
||||
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP)
|
||||
|
||||
|
||||
@@ -30,14 +30,17 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
interface FunctionalArgument
|
||||
|
||||
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument {
|
||||
abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument, ReturnLabelOwner {
|
||||
|
||||
abstract val isBoundCallableReference: Boolean
|
||||
|
||||
@@ -51,9 +54,6 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
|
||||
|
||||
abstract val capturedVars: List<CapturedParamDesc>
|
||||
|
||||
open val returnLabels: Map<String, Label?>
|
||||
get() = mapOf()
|
||||
|
||||
lateinit var node: SMAPAndMethodNode
|
||||
|
||||
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>)
|
||||
@@ -129,14 +129,15 @@ abstract class DefaultLambda(
|
||||
final override lateinit var capturedVars: List<CapturedParamDesc>
|
||||
private set
|
||||
|
||||
override fun isReturnFromMe(labelName: String): Boolean = false
|
||||
|
||||
var originalBoundReceiverType: Type? = null
|
||||
private set
|
||||
|
||||
override val isSuspend = parameterDescriptor.isSuspendLambda
|
||||
|
||||
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
|
||||
val classBytes = loadClassBytesByInternalName(sourceCompiler.state, lambdaClassType.internalName)
|
||||
val classReader = ClassReader(classBytes)
|
||||
val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName)
|
||||
var isPropertyReference = false
|
||||
var isFunctionReference = false
|
||||
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
||||
@@ -161,7 +162,12 @@ abstract class DefaultLambda(
|
||||
}
|
||||
|
||||
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||
val constructor = getMethodNode(classBytes, "<init>", descriptor, lambdaClassType)?.node
|
||||
val constructor = getMethodNode(
|
||||
classReader.b,
|
||||
"<init>",
|
||||
descriptor,
|
||||
lambdaClassType
|
||||
)?.node
|
||||
|
||||
assert(constructor != null || capturedArgs.isEmpty()) {
|
||||
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
|
||||
@@ -184,8 +190,13 @@ abstract class DefaultLambda(
|
||||
|
||||
val signature = mapAsmSignature(sourceCompiler)
|
||||
|
||||
node = getMethodNode(classBytes, methodName, signature.descriptor, lambdaClassType, signatureAmbiguity = true)
|
||||
?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
|
||||
node = getMethodNode(
|
||||
classReader.b,
|
||||
methodName,
|
||||
signature.descriptor,
|
||||
lambdaClassType,
|
||||
signatureAmbiguity = true
|
||||
) ?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
|
||||
|
||||
invokeMethod = Method(node.node.name, node.node.desc)
|
||||
|
||||
@@ -245,7 +256,7 @@ class PsiExpressionLambda(
|
||||
|
||||
val functionWithBodyOrCallableReference: KtExpression = (expression as? KtLambdaExpression)?.functionLiteral ?: expression
|
||||
|
||||
override val returnLabels: Map<String, Label?>
|
||||
private val labels: Set<String>
|
||||
|
||||
override val isSuspend: Boolean
|
||||
|
||||
@@ -282,7 +293,7 @@ class PsiExpressionLambda(
|
||||
closure = it!!
|
||||
}
|
||||
|
||||
returnLabels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
|
||||
labels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor)
|
||||
invokeMethod = typeMapper.mapAsmMethod(invokeMethodDescriptor)
|
||||
isSuspend = invokeMethodDescriptor.isSuspend
|
||||
}
|
||||
@@ -322,6 +333,10 @@ class PsiExpressionLambda(
|
||||
}
|
||||
}
|
||||
|
||||
override fun isReturnFromMe(labelName: String): Boolean {
|
||||
return labels.contains(labelName)
|
||||
}
|
||||
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user