Compare commits

..

3 Commits

Author SHA1 Message Date
Dmitry Petrov
ef461d4a3a JVM_IR KT-36646 fuze primitive equality with safe call 2021-04-27 16:22:53 +03:00
Dmitry Petrov
eaf870bfd4 JVM_IR update test for KT-36637 2021-04-27 16:22:52 +03:00
Dmitry Petrov
e8982765c8 JVM_IR use static 'hashCode' for boxed primitives on JVM 1.8+ 2021-04-27 16:22:52 +03:00
6923 changed files with 33406 additions and 134478 deletions

1
.gitignore vendored
View File

@@ -12,7 +12,6 @@
/android-studio/sdk
out/
/tmp
kotlin-ide/
workspace.xml
*.versionsBackup
/idea/testData/debugger/tinyApp/classes*

View File

@@ -1,677 +1,5 @@
# CHANGELOG
## 1.5.10
### Compiler
#### Fixes
- [`KT-41078`](https://youtrack.jetbrains.com/issue/KT-41078) Incorrect type substitution in contracts with type parameters
- [`KT-44770`](https://youtrack.jetbrains.com/issue/KT-44770) JVM / IR: "IllegalArgumentException: Unrecognized Type: [null]" Jackson doesn't recognize type
- [`KT-45084`](https://youtrack.jetbrains.com/issue/KT-45084) JVM IR: "NoSuchElementException: Sequence contains no element matching the predicate" when inline class is passed to lambda with >22 parameters
- [`KT-45779`](https://youtrack.jetbrains.com/issue/KT-45779) JVM / IR: java.lang.NoSuchMethodError: 'int java.lang.Integer.plus(int)' caused by function reference
- [`KT-45941`](https://youtrack.jetbrains.com/issue/KT-45941) JVM IR: local functions use generic type parameters of the outer class in the bytecode, which breaks Bytebuddy and MockK
- [`KT-46149`](https://youtrack.jetbrains.com/issue/KT-46149) Generate synthetic classes for SAM adapters with erased instead of generic supertype
- [`KT-46189`](https://youtrack.jetbrains.com/issue/KT-46189) JVM IR: tailrec function with capturing lambda in default parameter value leads to NoSuchMethodError at runtime
- [`KT-46214`](https://youtrack.jetbrains.com/issue/KT-46214) JVM / IR: "IllegalStateException: No mapping for symbol: VALUE_PARAMETER INSTANCE_RECEIVER" on a suspend function in an inner class
- [`KT-46238`](https://youtrack.jetbrains.com/issue/KT-46238) JVM IR: BootstrapMethodError in JDK 11+ on intersection type passed in arguments of SAM adapter where SAM interface's type parameter has a non-trivial upper bound
- [`KT-46259`](https://youtrack.jetbrains.com/issue/KT-46259) JVM IR: local function for adapted function reference is not declared as ACC_SYNTHETIC
- [`KT-46284`](https://youtrack.jetbrains.com/issue/KT-46284) JVM IR: "Unbound private symbol IrClassSymbol" on class reference to script class
- [`KT-46402`](https://youtrack.jetbrains.com/issue/KT-46402) IllegalAccessError: "CapturedLambdaInterpreter (in unnamed module @0x71b06418) cannot access class jdk.internal.org.objectweb.asm.Type" caused by inline function with a suspend parameter in Maven project
- [`KT-46408`](https://youtrack.jetbrains.com/issue/KT-46408) JVM IR: BootstrapMethodError due to missing bridge for subclass of generic Java interface
- [`KT-46426`](https://youtrack.jetbrains.com/issue/KT-46426) JVM IR: Corrupted .class file when passing Array constructor reference as (inline) lambda
- [`KT-46455`](https://youtrack.jetbrains.com/issue/KT-46455) OOM on parsing invalid code with string interpolation
- [`KT-46503`](https://youtrack.jetbrains.com/issue/KT-46503) JVM IR: "AssertionError: Unexpected variance in super type argument: out @1"
- [`KT-46505`](https://youtrack.jetbrains.com/issue/KT-46505) JVM IR: NullPointerException caused by a callable reference with nullable inline value class parameter
- [`KT-46512`](https://youtrack.jetbrains.com/issue/KT-46512) JVM / IR: NoSuchMethodError on SAM conversion of a function reference
- [`KT-46515`](https://youtrack.jetbrains.com/issue/KT-46515) IndexOutOfBoundsException: "Empty list doesn't contain element at index 0." on bad variable name in 1.5.0
- [`KT-46516`](https://youtrack.jetbrains.com/issue/KT-46516) JVM IR: "AnalyzerException: Expected I, but found R" on subclassing AbstractMutableList<Int>
- [`KT-46524`](https://youtrack.jetbrains.com/issue/KT-46524) Cannot use unsigned literals with api-version < 1.5 even with opt-in
- [`KT-46537`](https://youtrack.jetbrains.com/issue/KT-46537) JVM / IR: "IllegalStateException: No noarg super constructor for CLASS" caused by "No-arg" plugin with annotation on child class
- [`KT-46540`](https://youtrack.jetbrains.com/issue/KT-46540) JVM / IR: AnalyzerException: Expected an object reference, but found J caused by java.function.Supplier
- [`KT-46554`](https://youtrack.jetbrains.com/issue/KT-46554) JVM IR: "IllegalStateException: No mapping for symbol: VAR IR_TEMPORARY_VARIABLE" with value class constructor delegation call
- [`KT-46555`](https://youtrack.jetbrains.com/issue/KT-46555) JVM IR: IllegalAccessError when using Java method reference
- [`KT-46562`](https://youtrack.jetbrains.com/issue/KT-46562) Kotlin 1.5.0 generates non-serializable lambdas when they should be serializable
- [`KT-46568`](https://youtrack.jetbrains.com/issue/KT-46568) JVM IR: "AssertionError: IrCall expected inside JvmStatic wrapper" on compiling protected static function with return type Nothing inside companion object of abstract class
- [`KT-46574`](https://youtrack.jetbrains.com/issue/KT-46574) JVM / IR: ClassCastException caused by runBlocking awaiting call while returning Kotlin.Result type.
- [`KT-46579`](https://youtrack.jetbrains.com/issue/KT-46579) JVM IR: "IllegalArgumentException: Sequence contains more than one matching element" for Java enum with overloaded values() static method
- [`KT-46584`](https://youtrack.jetbrains.com/issue/KT-46584) JVM IR: Intrinsics.needClassReification (UnsupportedOperationException thrown). Property delegate provider crossinline lambda inlining/reification issue
- [`KT-46751`](https://youtrack.jetbrains.com/issue/KT-46751) JVM / IR:"ClassCastException: java.lang.String cannot be cast to java.lang.Void" in extension function in Kotlin 1.5
### IDE
- [`KT-45981`](https://youtrack.jetbrains.com/issue/KT-45981) failed to analyze: java.lang.AssertionError: diagnostic callback has been already registered: Code analysis get stuck in AS 2020.3.1.14 & Kotlin v1.5.0-M2
- [`KT-46622`](https://youtrack.jetbrains.com/issue/KT-46622) 60+ second freezes with Kotlin plugin 1.5.0: GetModuleInfoKt.findJvmStdlibAcrossDependencies
### IDE. Gradle Integration
- [`KT-46417`](https://youtrack.jetbrains.com/issue/KT-46417) [UNRESOLVED_REFERENCE] For project to project dependencies of native platform test source sets
### Libraries
- [`KT-46280`](https://youtrack.jetbrains.com/issue/KT-46280) JvmRecord annotation missing constructor in common
### Middle-end. IR
- [`KT-44013`](https://youtrack.jetbrains.com/issue/KT-44013) NPE: When calling constructor of a function type while inheriting from it, despite it's an interface
### Tools. Android Extensions
- [`KT-46590`](https://youtrack.jetbrains.com/issue/KT-46590) Kotlin Android Extensions 1.5.0 generates bad writeToParcel() method for nullable Array types
### Tools. Gradle
- [`KT-41142`](https://youtrack.jetbrains.com/issue/KT-41142) Kotlin version conflict when using Kotlin Gradle plugins in pre-compiled script plugin
- [`KT-46353`](https://youtrack.jetbrains.com/issue/KT-46353) Optimizations disabled in Gradle 7 for KAPT when generating sources
- [`KT-46368`](https://youtrack.jetbrains.com/issue/KT-46368) Memory leak with 1.5.0-RC when building with Gradle
- [`KT-46689`](https://youtrack.jetbrains.com/issue/KT-46689) Track -Xuse-old-backend flag usage
### Tools. Gradle. JS
- [`KT-46006`](https://youtrack.jetbrains.com/issue/KT-46006) KJS \ Gradle: Task without declaring an explicit or implicit dependency on `jsGenerateExternalsIntegrated` in Gradle 7
- [`KT-46162`](https://youtrack.jetbrains.com/issue/KT-46162) KJS: Exported items unavailable on dev server
- [`KT-46331`](https://youtrack.jetbrains.com/issue/KT-46331) KJS: With `kotlin.js.webpack.major.version=4` browserXRun tasks fail
### Tools. Parcelize
- [`KT-46567`](https://youtrack.jetbrains.com/issue/KT-46567) Kotlin 1.5.0 parcelize compilation fails in new backend when using TypeParceller with nested generics
### Tools. kapt
- [`KT-45532`](https://youtrack.jetbrains.com/issue/KT-45532) Do not create Kapt stubs directory during configuration time
## 1.5.0
### Backend. Native
- [`KT-42053`](https://youtrack.jetbrains.com/issue/KT-42053) Support compiler caches for linux_x64
- [`KT-43690`](https://youtrack.jetbrains.com/issue/KT-43690) Support compiler caches for ios_arm64
### Backend. IR
- [`KT-42684`](https://youtrack.jetbrains.com/issue/KT-42684) StackOverflowError on recursive inline arguments in inline fun
### Compiler
#### New Features
- [`KT-28791`](https://youtrack.jetbrains.com/issue/KT-28791) Kotlin serialization with inline classes
- [`KT-30222`](https://youtrack.jetbrains.com/issue/KT-30222) Support JVM target version selection in Kotlin bytecode tool window
- [`KT-41884`](https://youtrack.jetbrains.com/issue/KT-41884) Support 'file' target for JvmSynthetic annotation
- [`KT-43677`](https://youtrack.jetbrains.com/issue/KT-43677) Support for Java records
- [`KT-43920`](https://youtrack.jetbrains.com/issue/KT-43920) Support loading binary Java annotations on fields
- [`KT-44278`](https://youtrack.jetbrains.com/issue/KT-44278) Generate SAM-converted lambdas and function references using 'invokedynamic' on JDK 1.8+
- [`KT-44650`](https://youtrack.jetbrains.com/issue/KT-44650) Deprecate JVM target version 1.6
- [`KT-44787`](https://youtrack.jetbrains.com/issue/KT-44787) Suspend functions in fun interfaces
- [`KT-44865`](https://youtrack.jetbrains.com/issue/KT-44865) Allow to declare protected constructors in sealed classes
- [`KT-44869`](https://youtrack.jetbrains.com/issue/KT-44869) Compiling sealed interface with version less than 1.5: error message from future could be provided
#### Performance Improvements
- [`KT-6336`](https://youtrack.jetbrains.com/issue/KT-6336) Optimize generation of local functions
- [`KT-7307`](https://youtrack.jetbrains.com/issue/KT-7307) Optimize infix call of String.plus
- [`KT-18692`](https://youtrack.jetbrains.com/issue/KT-18692) Optimize '<optimizable_range> step x' for-in loop
- [`KT-19978`](https://youtrack.jetbrains.com/issue/KT-19978) Inefficient bytecode generated for function references undergoing Java SAM conversion
- [`KT-23565`](https://youtrack.jetbrains.com/issue/KT-23565) OperationsMapGenerated.kt generates unreasonable amount of bytecode
- [`KT-23825`](https://youtrack.jetbrains.com/issue/KT-23825) Tail suspend call utilizing elvis operator does not take advantage of suspend tail call optimization
- [`KT-23826`](https://youtrack.jetbrains.com/issue/KT-23826) A suspend function on the right side of a returned || condition is not tail call optimized
- [`KT-25348`](https://youtrack.jetbrains.com/issue/KT-25348) No compile time unsigned integer conversion when using hex literal
- [`KT-26060`](https://youtrack.jetbrains.com/issue/KT-26060) Support a compiler mode to compile lambda expressions using `invokedynamic` instruction
- [`KT-26590`](https://youtrack.jetbrains.com/issue/KT-26590) Do not generate create method for suspend lambdas if its arity >= 2
- [`KT-27427`](https://youtrack.jetbrains.com/issue/KT-27427) Optimize nullable check introduced with 'as' cast
- [`KT-28246`](https://youtrack.jetbrains.com/issue/KT-28246) Redundant boxing/unboxing isn't eliminated by the compiler in case of inline classes and javaClass intrinsic
- [`KT-30605`](https://youtrack.jetbrains.com/issue/KT-30605) Constant folding doesn't evaluate inv() function
- [`KT-36845`](https://youtrack.jetbrains.com/issue/KT-36845) Generate enum-based TABLESWITCH/LOOKUPSWITCH on a value with smart cast to enum in JVM_IR
- [`KT-39585`](https://youtrack.jetbrains.com/issue/KT-39585) JVM BE generates redundant accessor calls when accessing static final field lifted from companion
- [`KT-40886`](https://youtrack.jetbrains.com/issue/KT-40886) Old JVM BE unspills ACONST_NULL from continuation
- [`KT-42621`](https://youtrack.jetbrains.com/issue/KT-42621) Kotlin binary size considerably larger for code extensively using stream API
- [`KT-44153`](https://youtrack.jetbrains.com/issue/KT-44153) NI: Low Memory and IntelliJ hangs when quotes in split() are missed
- [`KT-45410`](https://youtrack.jetbrains.com/issue/KT-45410) JVM / IR: Extreme performance regression on arithmetic operations inside a loop
#### Fixes
- [`KT-6007`](https://youtrack.jetbrains.com/issue/KT-6007) Support changed return type of inlined generic function when lambda returns anonymous object
- [`KT-6055`](https://youtrack.jetbrains.com/issue/KT-6055) Failed invoke plus assign on array element accessed via several args through local get/set convention extensions
- [`KT-6879`](https://youtrack.jetbrains.com/issue/KT-6879) CompilationException when local classes hierarchy is placed within other local or inner declaration
- [`KT-8120`](https://youtrack.jetbrains.com/issue/KT-8120) NoSuchMethodError on local class constructor call inside a local class
- [`KT-8199`](https://youtrack.jetbrains.com/issue/KT-8199) "Cannot pop operand off an empty stack" for local class using a captured variable as default value for constructor parameter
- [`KT-10835`](https://youtrack.jetbrains.com/issue/KT-10835) "AssertionError: Non-outer parameter incorrectly mapped to outer" when inlining object literal extending inner class
- [`KT-12790`](https://youtrack.jetbrains.com/issue/KT-12790) Don't generate synthetic accessors for private inline function/properties
- [`KT-13213`](https://youtrack.jetbrains.com/issue/KT-13213) IllegalArgumentException in ByteVector.putUTF8 on attempt to compile file with moderately long string literal
- [`KT-14628`](https://youtrack.jetbrains.com/issue/KT-14628) "UnsupportedOperationException: Don't know how to generate outer expression" for nested class inheriting from inner class with a companion object
- [`KT-14833`](https://youtrack.jetbrains.com/issue/KT-14833) JVM internal error: Augment assignment and increment are not supported for local delegated properties and inline properties
- [`KT-15403`](https://youtrack.jetbrains.com/issue/KT-15403) Suspend operator get wrong code generated by BE (NoSuchMethodError)
- [`KT-15404`](https://youtrack.jetbrains.com/issue/KT-15404) Suspend operator set wrong code generated
- [`KT-16084`](https://youtrack.jetbrains.com/issue/KT-16084) Proguard can't find enclosing class of let closure inside apply closure
- [`KT-16151`](https://youtrack.jetbrains.com/issue/KT-16151) Internal compiler error when using plusAssign operator with mutable map
- [`KT-16221`](https://youtrack.jetbrains.com/issue/KT-16221) Support in/!in suspend operators
- [`KT-16282`](https://youtrack.jetbrains.com/issue/KT-16282) "Cannot pop operand off an empty stack" for plusAssign with default parameters in setter operator
- [`KT-16445`](https://youtrack.jetbrains.com/issue/KT-16445) `java.lang.VerifyError: Bad type on operand stack` when delegating an interface through a private reified function inside an object
- [`KT-16520`](https://youtrack.jetbrains.com/issue/KT-16520) Invalid bytecode semantics for set call by convention with default parameters
- [`KT-16567`](https://youtrack.jetbrains.com/issue/KT-16567) Inliner creates redundant objects on source inlining
- [`KT-16752`](https://youtrack.jetbrains.com/issue/KT-16752) Delegating function interface to function reference does not work
- [`KT-17554`](https://youtrack.jetbrains.com/issue/KT-17554) Incorrect cast to Unit generated on annotated when-expression with a single-branch if inside
- [`KT-17738`](https://youtrack.jetbrains.com/issue/KT-17738) Java cannot extend class implementing kotlin.collections.Map
- [`KT-17753`](https://youtrack.jetbrains.com/issue/KT-17753) Strange behavior of if and return statements
- [`KT-18583`](https://youtrack.jetbrains.com/issue/KT-18583) "ISE: Recursive call in a lazy value" for generic sealed class with nested subclass in a `when(this)` with inferred return type
- [`KT-19861`](https://youtrack.jetbrains.com/issue/KT-19861) "IllegalStateException: Label wasn't found during iterating through instructions" for `plusAssign` with safe call
- [`KT-20306`](https://youtrack.jetbrains.com/issue/KT-20306) Make 'when' over an 'expect' enum class non-exhaustive
- [`KT-20869`](https://youtrack.jetbrains.com/issue/KT-20869) kotlin.jvm.internal.DefaultConstructorMarker should be public
- [`KT-20996`](https://youtrack.jetbrains.com/issue/KT-20996) IllegalStateException: Cannot get FQ name of local class: class <no name provided> in metadata serialization for common code
- [`KT-21014`](https://youtrack.jetbrains.com/issue/KT-21014) Incorrect bytecode generated for 'PrimitiveArray::size'
- [`KT-21092`](https://youtrack.jetbrains.com/issue/KT-21092) Reference `javaClass` for generic property: "couldn't transform method node: get()"
- [`KT-21778`](https://youtrack.jetbrains.com/issue/KT-21778) "IllegalStateException: Couldn't build context" for inline function inside an anonymous object
- [`KT-21900`](https://youtrack.jetbrains.com/issue/KT-21900) VerifyError on equals on generic primitive type
- [`KT-22098`](https://youtrack.jetbrains.com/issue/KT-22098) "UnsupportedOperationException: Don't know how to generate outer expression" on extension function call inside lambda in anonymous object super constructor call
- [`KT-22488`](https://youtrack.jetbrains.com/issue/KT-22488) Bad line numbers generated for '&&' expression
- [`KT-22972`](https://youtrack.jetbrains.com/issue/KT-22972) A compiler bug(?) in Number class descendants
- [`KT-23619`](https://youtrack.jetbrains.com/issue/KT-23619) Transform stateless singleton lambda during inline
- [`KT-23881`](https://youtrack.jetbrains.com/issue/KT-23881) Declaration of lambda in inlined apply block holds reference to superfluous references causing leak
- [`KT-24135`](https://youtrack.jetbrains.com/issue/KT-24135) Calling invoke on crossinline suspend lambda leads to no state-machine
- [`KT-24193`](https://youtrack.jetbrains.com/issue/KT-24193) NoClassDefFoundError: java/lang/Cloneable$DefaultImpls on inheritance from Cloneable through an interface
- [`KT-24305`](https://youtrack.jetbrains.com/issue/KT-24305) ClassNotFoundException when using Java reflection on local class in an inlined lambda
- [`KT-24564`](https://youtrack.jetbrains.com/issue/KT-24564) Custom operator fun set on ByteArray resolves properly but is miscompiled
- [`KT-25400`](https://youtrack.jetbrains.com/issue/KT-25400) "NoClassDefFoundError: kotlin/KotlinPackage" with Turkish system locale on macOS
- [`KT-26130`](https://youtrack.jetbrains.com/issue/KT-26130) Incorrect method signature for a generic function with inline class as a type parameter upper bound
- [`KT-26360`](https://youtrack.jetbrains.com/issue/KT-26360) "Method from super interface has a different signature" for Interface that extends both interfaces with and without @JvmDefault
- [`KT-26473`](https://youtrack.jetbrains.com/issue/KT-26473) Error on compiling inline class with calls of super methods equals(), hashCode(), toString()
- [`KT-26474`](https://youtrack.jetbrains.com/issue/KT-26474) VE “Bad type on operand stack” at runtime on calling toString() method of inline class with calls of super methods (toString(), equals(), hashCode()) inside
- [`KT-26592`](https://youtrack.jetbrains.com/issue/KT-26592) Do not generate private suspend functions as synthetic package-private
- [`KT-27449`](https://youtrack.jetbrains.com/issue/KT-27449) NoSuchMethodError for local suspend function with suspend lambda parameter with default value
- [`KT-27469`](https://youtrack.jetbrains.com/issue/KT-27469) "Cannot pop operand off an empty stack" for compound assignment (plusAssign) with a `vararg` operator get
- [`KT-27825`](https://youtrack.jetbrains.com/issue/KT-27825) Gradually prohibit non-abstract classes containing abstract members invisible from that classes (internal/package-private)
- [`KT-27830`](https://youtrack.jetbrains.com/issue/KT-27830) "Incompatible stack heights" with suspend inline function in do while loop that executes suspend lambda
- [`KT-28042`](https://youtrack.jetbrains.com/issue/KT-28042) "Cannot pop operand off an empty stack" for a bound callable reference of lambda inside inline function
- [`KT-28166`](https://youtrack.jetbrains.com/issue/KT-28166) "Argument 1: expected I, but found R" for generic method with generic parameter or receiver with inline class upper bound
- [`KT-28331`](https://youtrack.jetbrains.com/issue/KT-28331) Consider generating accessors for lateinit properties to avoid assertion on each call
- [`KT-28573`](https://youtrack.jetbrains.com/issue/KT-28573) Inliner does not update references to transformed object
- [`KT-29331`](https://youtrack.jetbrains.com/issue/KT-29331) "AnalyzerException: Argument 1: expected R, but found I" with local generic extension property called on `Int` receiver
- [`KT-29595`](https://youtrack.jetbrains.com/issue/KT-29595) NoClassDefFoundError with inline reified function with lambda argument returning anonymous object
- [`KT-29802`](https://youtrack.jetbrains.com/issue/KT-29802) Incorrect reification when the same type parameter name is used for different reified types
- [`KT-30041`](https://youtrack.jetbrains.com/issue/KT-30041) "AnalyzerException: Expected an object reference, but found ." on nested suspend function calls outer suspend function
- [`KT-30066`](https://youtrack.jetbrains.com/issue/KT-30066) Consider adding annotations to ConeKotlinType
- [`KT-30280`](https://youtrack.jetbrains.com/issue/KT-30280) Inline class class literal gets unwrapped in annotation arguments
- [`KT-30402`](https://youtrack.jetbrains.com/issue/KT-30402) Constant folding works incorrectly with unsigned arithmetics
- [`KT-30548`](https://youtrack.jetbrains.com/issue/KT-30548) "java.lang.IndexOutOfBoundsException: Cannot pop operand off an empty stack" while compiling access to a private lateinit companion field
- [`KT-30629`](https://youtrack.jetbrains.com/issue/KT-30629) `java.lang.VerifyError: Bad type on operand stack` when using a function reference to a generic property
- [`KT-30933`](https://youtrack.jetbrains.com/issue/KT-30933) Inline function produces IllegalAccessError on property reference from different package
- [`KT-31136`](https://youtrack.jetbrains.com/issue/KT-31136) "AnalyzerException: Argument 1: expected R, but found I" on x::javaClass when x is inline class object built around primitive type
- [`KT-31227`](https://youtrack.jetbrains.com/issue/KT-31227) Prohibit using array based on non-reified type parameters as reified type arguments on JVM
- [`KT-31592`](https://youtrack.jetbrains.com/issue/KT-31592) NoSuchMethodException when inlining public function accessing a protected static Java class member
- [`KT-31727`](https://youtrack.jetbrains.com/issue/KT-31727) Object expression captures all variables used in constructor
- [`KT-32023`](https://youtrack.jetbrains.com/issue/KT-32023) "AnalyzerException: Expected I, but found R" with inline suspend function used with callable reference
- [`KT-32115`](https://youtrack.jetbrains.com/issue/KT-32115) NPE during initialization of enum class with delegated property
- [`KT-32153`](https://youtrack.jetbrains.com/issue/KT-32153) "AnalyzerException: Expected an object reference, but found ." with recursive suspend local function
- [`KT-32351`](https://youtrack.jetbrains.com/issue/KT-32351) ClassNotFoundException for anonymous object implementing interface inside a lambda with data class and inline methods
- [`KT-32384`](https://youtrack.jetbrains.com/issue/KT-32384) Safe cast to generic type argument with inline class upper-bound throws NPE instead of ClassCastException
- [`KT-32579`](https://youtrack.jetbrains.com/issue/KT-32579) java.lang.VerifyError: Bad type on operand stack on calling inner class of inherited class in super class when casting to inherited class
- [`KT-32749`](https://youtrack.jetbrains.com/issue/KT-32749) "VerifyError: Call to wrong <init> method" with inline function and accessing class field from anonymous object
- [`KT-32793`](https://youtrack.jetbrains.com/issue/KT-32793) Generated code crashes by ClassCastException with local suspend function and inline class
- [`KT-32812`](https://youtrack.jetbrains.com/issue/KT-32812) "AnalyzerException: Argument 1: expected R, but found I" invoking function with default parameter inherited by inline class
- [`KT-32821`](https://youtrack.jetbrains.com/issue/KT-32821) Missing unboxing of inline class for complex hierarchy of suspend calls
- [`KT-33155`](https://youtrack.jetbrains.com/issue/KT-33155) ClassNotFoundException for qualified this in anonymous object and as a result of inline function call
- [`KT-33173`](https://youtrack.jetbrains.com/issue/KT-33173) Internal error: "AnalyzerException: Expected I, but found R" for supercall inside inline lambda from HashSet.remove implementation
- [`KT-33577`](https://youtrack.jetbrains.com/issue/KT-33577) NoSuchFieldError with nested anonymous objects accessing outer instance property
- [`KT-33836`](https://youtrack.jetbrains.com/issue/KT-33836) Wrong code generated for a local tailrec suspend function.
- [`KT-33873`](https://youtrack.jetbrains.com/issue/KT-33873) ClassCastException invoking UByte setter function via reflection
- [`KT-34018`](https://youtrack.jetbrains.com/issue/KT-34018) "Cannot pop operand off an empty stack" with inline lambda with callable reference
- [`KT-34186`](https://youtrack.jetbrains.com/issue/KT-34186) JDK11: class file contains malformed variable arity method for vararg sealed class constructor
- [`KT-34202`](https://youtrack.jetbrains.com/issue/KT-34202) IllegalAccessError on callable reference of function from multifile facade from standard library
- [`KT-34255`](https://youtrack.jetbrains.com/issue/KT-34255) @JvmStatic tailrec function: "Cannot pop operand off an empty stack"
- [`KT-34507`](https://youtrack.jetbrains.com/issue/KT-34507) Incorrect generated code for mutable collection stub methods in case of presence of functions with similar signature
- [`KT-34665`](https://youtrack.jetbrains.com/issue/KT-34665) Possible index overflow in optimized "for" loop over withIndex()
- [`KT-34754`](https://youtrack.jetbrains.com/issue/KT-34754) Flow builder: "AnalyzerException: Expected an object reference, but found ." with recursive suspend local function
- [`KT-34816`](https://youtrack.jetbrains.com/issue/KT-34816) "AnalyzerException: Expected an object reference, but found I" on "this" in inline class member extension suspend function
- [`KT-34841`](https://youtrack.jetbrains.com/issue/KT-34841) ClassNotFoundException when invoke param function inside anonymous object method
- [`KT-35008`](https://youtrack.jetbrains.com/issue/KT-35008) "AnalyzerException: Expected an object reference, but found I" in inline class companion calling private constructor
- [`KT-35166`](https://youtrack.jetbrains.com/issue/KT-35166) `NoSuchMethodError` at runtime with local property delegate on anonymous object referencing another anonymous object
- [`KT-35224`](https://youtrack.jetbrains.com/issue/KT-35224) It's possible to pass non-spread arrays after arguments with SAM-conversion
- [`KT-35301`](https://youtrack.jetbrains.com/issue/KT-35301) MethodInliner fails with "AssertionError: <init> call doesn't correspond to object transformation info" for qualified this in SAM constructor used as parameter of anonymous object inside inline lambda
- [`KT-35419`](https://youtrack.jetbrains.com/issue/KT-35419) `Failed to generate expression: KtNamedFunction` for local suspend tailrec function with receiver
- [`KT-35511`](https://youtrack.jetbrains.com/issue/KT-35511) VerifyError: "Bad type on operand stack" after reification
- [`KT-35553`](https://youtrack.jetbrains.com/issue/KT-35553) Kotlin compiler generates methods that always have line number 1 for Inline Classes
- [`KT-35725`](https://youtrack.jetbrains.com/issue/KT-35725) "AssertionError: Couldn't find a context for a super-call" for `super` member call in property initializer of companion object
- [`KT-36420`](https://youtrack.jetbrains.com/issue/KT-36420) ClassCastException with inline class Foo extending generic Comparable<Foo>
- [`KT-36713`](https://youtrack.jetbrains.com/issue/KT-36713) AnalyzerException: "Incompatible stack heights" with suspend and inline suspend functions
- [`KT-36794`](https://youtrack.jetbrains.com/issue/KT-36794) Move $assertionsDisabled field to the top-level class
- [`KT-36853`](https://youtrack.jetbrains.com/issue/KT-36853) IR: UninitializedPropertyAccessException on tailrec with object expression in default argument
- [`KT-36875`](https://youtrack.jetbrains.com/issue/KT-36875) "RuntimeException: Trying to access skipped parameter" on synthetic local variable access from inline function
- [`KT-36916`](https://youtrack.jetbrains.com/issue/KT-36916) AnalyzerException: Argument 1: expected I, but found R when using inline class with rxjava
- [`KT-36957`](https://youtrack.jetbrains.com/issue/KT-36957) Exception during codegen: cannot pop operand off an empty stack (Nothing variable in string interpolation)
- [`KT-36984`](https://youtrack.jetbrains.com/issue/KT-36984) SAM adapter classes should be generated as anonymous inner classes in JVM_IR
- [`KT-37704`](https://youtrack.jetbrains.com/issue/KT-37704) Incorrect SMAP syntax
- [`KT-37716`](https://youtrack.jetbrains.com/issue/KT-37716) "AssertionError: <init> call doesn't correspond to object transformation info" with inline reified type parameter, anonymous object and lambda in constructor call
- [`KT-37972`](https://youtrack.jetbrains.com/issue/KT-37972) IllegalAccessError on initializing property reference for a property declared in JvmMultifileClass with -Xmultifile-parts-inherit
- [`KT-38100`](https://youtrack.jetbrains.com/issue/KT-38100) Support local delegated properties (not inlined) in new JVM default modes
- [`KT-38833`](https://youtrack.jetbrains.com/issue/KT-38833) JVM: java.lang.ClassCastException when loop variable is nullable in for loop over unsigned progression
- [`KT-38849`](https://youtrack.jetbrains.com/issue/KT-38849) Read-only variable initialized in non-inline lambda using contract callsInPlace EXACTLY_ONCE is not captured correctly in nested lambdas
- [`KT-38869`](https://youtrack.jetbrains.com/issue/KT-38869) JVM BE produces invalid bytecode when inheriting from AbstractList and declaring methods that look like MutableList implementors (but they aren't)
- [`KT-38965`](https://youtrack.jetbrains.com/issue/KT-38965) "UnsupportedOperationException: Don't know how to generate outer expression: Closure" with reference to local variable in block argument of anonymous object `by` delegation
- [`KT-39289`](https://youtrack.jetbrains.com/issue/KT-39289) CCE in if-else inside annotated 'if' statement
- [`KT-39425`](https://youtrack.jetbrains.com/issue/KT-39425) AbstractMethodError: "Receiver class does not define or inherit an implementation of the resolved method" using classes with complex Java and Kotlin inheritance hierarchies.
- [`KT-39434`](https://youtrack.jetbrains.com/issue/KT-39434) IllegalAccessError with local delegated property in lambda in inlined function
- [`KT-39687`](https://youtrack.jetbrains.com/issue/KT-39687) "Couldn't find captured this" when more than 3 inline functions are nested
- [`KT-39784`](https://youtrack.jetbrains.com/issue/KT-39784) "IndexOutOfBoundsException: Cannot pop operand off an empty stack" caused by JvmOverloads annotation inside an inline class
- [`KT-40165`](https://youtrack.jetbrains.com/issue/KT-40165) ClassCastException caused by SAM conversion used on a functional interface with suspended function
- [`KT-40179`](https://youtrack.jetbrains.com/issue/KT-40179) "VerifyError: Bad type on operand stack" with parent class `get` extension function and child class `set` extension function which used inside child class `plusAssign` extension function
- [`KT-40277`](https://youtrack.jetbrains.com/issue/KT-40277) Fix generic types in special bridge methods
- [`KT-40308`](https://youtrack.jetbrains.com/issue/KT-40308) NoSuchFieldError for multiple delegated extension properties with the same name in a companion object
- [`KT-40338`](https://youtrack.jetbrains.com/issue/KT-40338) NoSuchFieldError on property without backing field that is called as function reference
- [`KT-40392`](https://youtrack.jetbrains.com/issue/KT-40392) Deprecate JvmDefault annotation and old -Xjvm-default modes
- [`KT-40396`](https://youtrack.jetbrains.com/issue/KT-40396) NI: Exceptions when ambiguous type argument and generic invoke
- [`KT-40510`](https://youtrack.jetbrains.com/issue/KT-40510) "AssertionError: DELEGATION slice must override something" for ByteBuffer delegation
- [`KT-40601`](https://youtrack.jetbrains.com/issue/KT-40601) VerifyError: "interface method reference is in an indirect superinterface" when calling @JvmDefault suspend method
- [`KT-40809`](https://youtrack.jetbrains.com/issue/KT-40809) "Couldn't find captured field" compiler error with local function with recursive call through method reference
- [`KT-41056`](https://youtrack.jetbrains.com/issue/KT-41056) Increase stub version due to new "contract" keyword
- [`KT-41105`](https://youtrack.jetbrains.com/issue/KT-41105) IllegalStateException: 'Couldn't find declaration file <class name>' with inline delegate declared in another file
- [`KT-41165`](https://youtrack.jetbrains.com/issue/KT-41165) "IllegalStateException: Concrete fake override public final fun" when an enum class inherits an interface with a variable 'name' or 'ordinal'
- [`KT-41222`](https://youtrack.jetbrains.com/issue/KT-41222) "IllegalStateException: Concrete fake override public final fun" when a class property is inherited as merged 'var' from 'val' and 'var' from parent abstract class and interface properties
- [`KT-41255`](https://youtrack.jetbrains.com/issue/KT-41255) JDK 11: "VerifyError: Bad type on operand stack" with long function body with annotated `when` expression
- [`KT-41427`](https://youtrack.jetbrains.com/issue/KT-41427) NoSuchMethodError caused by implementation by delegation to function reference
- [`KT-41508`](https://youtrack.jetbrains.com/issue/KT-41508) ClassNotFoundException caused by object with overridden function inside a lambda with safe cast receiver
- [`KT-41750`](https://youtrack.jetbrains.com/issue/KT-41750) Inline classes: ClassCastExceptionError when calling .withIndex() on Iterator over Array
- [`KT-41758`](https://youtrack.jetbrains.com/issue/KT-41758) Deprecate kotlin.Metadata.bytecodeVersion and avoid using it in the compiler
- [`KT-41770`](https://youtrack.jetbrains.com/issue/KT-41770) AssertionError: "Asm parameter types should be the same length as Kotlin parameter types" cause by fun interface
- [`KT-41874`](https://youtrack.jetbrains.com/issue/KT-41874) "IllegalStateException: Couldn't obtain compiled function body" on extension delegated property with inline operator getValue in a different file
- [`KT-41917`](https://youtrack.jetbrains.com/issue/KT-41917) [FIR] Incorrect calculating property type for override from intersection scope
- [`KT-42012`](https://youtrack.jetbrains.com/issue/KT-42012) IllegalAccess to protected field instead of getter
- [`KT-42017`](https://youtrack.jetbrains.com/issue/KT-42017) "AssertionError: Unsigned type expected: UInt?" during codegen when a variable of nullable unsigned type is checking for presence in the range
- [`KT-42032`](https://youtrack.jetbrains.com/issue/KT-42032) "AnalyzerException: Expected I, but found R" while using Flow.reduce() with suspend function reference
- [`KT-42034`](https://youtrack.jetbrains.com/issue/KT-42034) ArrayIndexOutOfBoundsException in PopBackwardPropagationTransformer on external override of function in inline class
- [`KT-42064`](https://youtrack.jetbrains.com/issue/KT-42064) "Parameter specified as non-null is null" with default value of the parameter in operator fun
- [`KT-42069`](https://youtrack.jetbrains.com/issue/KT-42069) JVM IR: -Xreport-output-files doesn't report any source files for META-INF/*.kotlin_module files
- [`KT-42083`](https://youtrack.jetbrains.com/issue/KT-42083) AbstractMethodError when 'remove' with irrelevant generic parameter but matching JVM signature is present in Kotlin collection class
- [`KT-42092`](https://youtrack.jetbrains.com/issue/KT-42092) JVM / IR: "AnalyzerException: Argument 1: expected R, but found J" when trying to add to ArrayList the result of a function applied to int
- [`KT-42175`](https://youtrack.jetbrains.com/issue/KT-42175) Psi2ir: "AssertionError: Undefined parameter referenced: <this>" on augmented assignment on this in a BuilderInference lambda
- [`KT-42179`](https://youtrack.jetbrains.com/issue/KT-42179) Platform declaration clash when extending abstract Java class implementing 'java.util.Collection' by abstract Kotlin class implementing Kotlin Set or List
- [`KT-42321`](https://youtrack.jetbrains.com/issue/KT-42321) JVM IR: do not cast integer value based on the type of a literal receiver of an operator call
- [`KT-42337`](https://youtrack.jetbrains.com/issue/KT-42337) NoSuchMethodError in JVM backend with inheritance of private functions in the interface
- [`KT-42404`](https://youtrack.jetbrains.com/issue/KT-42404) "Supertypes of the following classes cannot be resolved" in Rider project
- [`KT-42472`](https://youtrack.jetbrains.com/issue/KT-42472) No TYPE_INFERENCE_UPPER_BOUND_VIOLATED for Delegated Properties do not check types (in Kotlin 1.4.10)
- [`KT-42487`](https://youtrack.jetbrains.com/issue/KT-42487) "IndexOutOfBoundsException: Cannot pop operand off an empty stack" caused by USELESS_IS_CHECK of Double type
- [`KT-42533`](https://youtrack.jetbrains.com/issue/KT-42533) `(N until MIN_VALUE).reversed()` should be an empty progression in for loops
- [`KT-42588`](https://youtrack.jetbrains.com/issue/KT-42588) "IllegalStateException: Concrete fake override public open fun" caused by `val` override with `var` with delegation.
- [`KT-42634`](https://youtrack.jetbrains.com/issue/KT-42634) Different bridges and abstract stubs behavior in abstract class implementing Map<K, String> in JVM and JVM_IR
- [`KT-42635`](https://youtrack.jetbrains.com/issue/KT-42635) ClassCastException with inline class in for loop
- [`KT-42662`](https://youtrack.jetbrains.com/issue/KT-42662) AbstractMethodError when using partially specialized generic Map class
- [`KT-42694`](https://youtrack.jetbrains.com/issue/KT-42694) @get:Synchronized causes the JVM getter method not to be generated
- [`KT-42753`](https://youtrack.jetbrains.com/issue/KT-42753) "VerifyError: Bad invokespecial instruction: interface method reference is in an indirect superinterface" with `jvm-default=all`
- [`KT-42879`](https://youtrack.jetbrains.com/issue/KT-42879) JVM: Declaration clash in fun interface implementation returning an inline class
- [`KT-42900`](https://youtrack.jetbrains.com/issue/KT-42900) "VerifyError: Bad return type" incorrect bytecode when a property and an extension property in inline class have the same names
- [`KT-42946`](https://youtrack.jetbrains.com/issue/KT-42946) FIR2IR: Fix super-calls to Java overrides of special built-in
- [`KT-42971`](https://youtrack.jetbrains.com/issue/KT-42971) JVM: "AssertionError: Unsigned type expected: T" with UInt loop range
- [`KT-42990`](https://youtrack.jetbrains.com/issue/KT-42990) "AssertionError: Next value after NEW should be one generated by DUP" caused by extension properties with accessors annotataed as @JvmStatic
- [`KT-43034`](https://youtrack.jetbrains.com/issue/KT-43034) AssertionError: Compiler fails with complicated tailrec + inline case
- [`KT-43048`](https://youtrack.jetbrains.com/issue/KT-43048) JVM_IR: Implement coroutines state clearing
- [`KT-43050`](https://youtrack.jetbrains.com/issue/KT-43050) JVM IR: incorrect mangling for method with type parameter with inline class bound in the signature
- [`KT-43059`](https://youtrack.jetbrains.com/issue/KT-43059) Different bridges behavior in class implementing Map<String, String> in JVM and JVM_IR
- [`KT-43063`](https://youtrack.jetbrains.com/issue/KT-43063) Redundant DefaultImpls delegate is generated in old JVM backend on explicit "duplicate" inheritance from interface
- [`KT-43069`](https://youtrack.jetbrains.com/issue/KT-43069) JVM: incorrect generic signature for method with implicit return type Nothing overriding a method from Collection
- [`KT-43099`](https://youtrack.jetbrains.com/issue/KT-43099) Tailrec call in not tail-call position leads to internal compiler error
- [`KT-43106`](https://youtrack.jetbrains.com/issue/KT-43106) JVM: custom `remove` in Iterator subclass results in a synthetic bridge
- [`KT-43120`](https://youtrack.jetbrains.com/issue/KT-43120) JVM: "Expected an object reference, but found ." caused by function which is passed as reference to suspend parameter
- [`KT-43167`](https://youtrack.jetbrains.com/issue/KT-43167) JVM IR, serialization: "No mapping for symbol: VALUE_PARAMETER INSTANCE_RECEIVER" with data class containing property defined in body
- [`KT-43255`](https://youtrack.jetbrains.com/issue/KT-43255) Verify error when inheriting from an abstract class implementing Collection with stub-like method in superclass
- [`KT-43303`](https://youtrack.jetbrains.com/issue/KT-43303) NI: False negative TYPE_INFERENCE_UPPER_BOUND_VIOLATED when inferred type argument is not a subtype of type parameter upper bound
- [`KT-43333`](https://youtrack.jetbrains.com/issue/KT-43333) AbstractMethodError when calling 'toArray' from Java on a Kotlin Collection with custom internal 'toArray'
- [`KT-43334`](https://youtrack.jetbrains.com/issue/KT-43334) AbstractMethodError when calling 'remove' from Java on a Kotlin Collection with custom internal 'remove'
- [`KT-43342`](https://youtrack.jetbrains.com/issue/KT-43342) [FIR2IR] No getter or backing field found for delegated member call
- [`KT-43347`](https://youtrack.jetbrains.com/issue/KT-43347) [FIR] Synthetic setter with unmatched parameter type isn't found
- [`KT-43401`](https://youtrack.jetbrains.com/issue/KT-43401) JVM_IR. Additional `synchronized` flag on JvmOverloads-generated adapter for Synchronized function
- [`KT-43405`](https://youtrack.jetbrains.com/issue/KT-43405) Turkish locale, Linux Mint: "NoSuchMethodError: 'int[] kotlin.jvm.internal.Intrinsics$Kotlin.intArrayOf(int[])'" with `intArrayOf` function call
- [`KT-43460`](https://youtrack.jetbrains.com/issue/KT-43460) JVM: redundant private setter is generated in case of multifile facade
- [`KT-43473`](https://youtrack.jetbrains.com/issue/KT-43473) "VerifyError: Bad type on operand stack" caused by operator `get` with optional argument in superclass when called via square brackets on subclass
- [`KT-43518`](https://youtrack.jetbrains.com/issue/KT-43518) JVM_IR. Additional `strictfp` flag on JvmOverloads-generated adapter for Strictfp function
- [`KT-43569`](https://youtrack.jetbrains.com/issue/KT-43569) FIR: inapplicable candidate(s): kotlin/collections/set
- [`KT-43616`](https://youtrack.jetbrains.com/issue/KT-43616) [FIR] Nullable type parameter-based type after merge in if
- [`KT-43669`](https://youtrack.jetbrains.com/issue/KT-43669) FIR: No real overrides for FUN IR_EXTERNAL_DECLARATION_STUB
- [`KT-43682`](https://youtrack.jetbrains.com/issue/KT-43682) Inline extension method of a multifile library inline class not found
- [`KT-43687`](https://youtrack.jetbrains.com/issue/KT-43687) FIR: UnusedChecker does not take annotation arguments into account
- [`KT-43688`](https://youtrack.jetbrains.com/issue/KT-43688) FIR: unused checker doesn't handle invokes properly
- [`KT-43749`](https://youtrack.jetbrains.com/issue/KT-43749) "UnsupportedOperationException: Don't know how to generate outer expression: Closure" caused by Flow and collect method with function reference as a parameter
- [`KT-43812`](https://youtrack.jetbrains.com/issue/KT-43812) JVM IR: SAM wrapper class with generic supertype mentions missing type parameter in the signature
- [`KT-43832`](https://youtrack.jetbrains.com/issue/KT-43832) JVM IR: missing bridges for inheritance of class from interface in a complex generic diamond hierarchy
- [`KT-43851`](https://youtrack.jetbrains.com/issue/KT-43851) JVM IR: function call returning object instance is removed during constant propagation
- [`KT-43864`](https://youtrack.jetbrains.com/issue/KT-43864) JVM: "Assertion error after mandatory stack transformations: incorrect bytecode" with lateinit property of type T, which has a primitive type upperbound
- [`KT-43887`](https://youtrack.jetbrains.com/issue/KT-43887) Problem with FunctionReferenceLowering$FunctionReferenceBuilder in kotlin native
- [`KT-43912`](https://youtrack.jetbrains.com/issue/KT-43912) JVM internal error: Augment assignment and increment are not supported for local delegated properties and inline properties
- [`KT-43915`](https://youtrack.jetbrains.com/issue/KT-43915) Back-end (JVM) Internal error: wrong bytecode generated for default method
- [`KT-43938`](https://youtrack.jetbrains.com/issue/KT-43938) NSME when calling 'kotlin.Number' methods on instance of Java class extending Kolin abstract class extending 'kotlin.Number'
- [`KT-43942`](https://youtrack.jetbrains.com/issue/KT-43942) org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Failed to generate function
- [`KT-43949`](https://youtrack.jetbrains.com/issue/KT-43949) FIR: unresolved callable reference as lambda return
- [`KT-43983`](https://youtrack.jetbrains.com/issue/KT-43983) IllegalStateException: "Couldn't obtain compiled function body for public final suspend inline fun" after moving inline extension function to library
- [`KT-43984`](https://youtrack.jetbrains.com/issue/KT-43984) FIR: recursion in overridden symbols
- [`KT-43984`](https://youtrack.jetbrains.com/issue/KT-43984) FIR: recursion in overridden symbols
- [`KT-44010`](https://youtrack.jetbrains.com/issue/KT-44010) FIR: Inapplicable constructor due to an unresolved reference
- [`KT-44030`](https://youtrack.jetbrains.com/issue/KT-44030) FIR2IR: uncached type parameters in delegated property
- [`KT-44032`](https://youtrack.jetbrains.com/issue/KT-44032) FIR2IR: uncached type parameters in Java field
- [`KT-44050`](https://youtrack.jetbrains.com/issue/KT-44050) FIR: anonymous object as IR parent
- [`KT-44054`](https://youtrack.jetbrains.com/issue/KT-44054) FIR2IR: incorrect IR origin for substituted override function
- [`KT-44058`](https://youtrack.jetbrains.com/issue/KT-44058) CompilationException: open suspend fun with @JvmStatic in open class companion
- [`KT-44069`](https://youtrack.jetbrains.com/issue/KT-44069) please remove deprecated usages
- [`KT-44066`](https://youtrack.jetbrains.com/issue/KT-44066) FIR Java: override ambiguity with vararg value type
- [`KT-44114`](https://youtrack.jetbrains.com/issue/KT-44114) CompilationException when inlining a extension suspend function declared in interface companion with 'this' reference to extension receiver
- [`KT-44131`](https://youtrack.jetbrains.com/issue/KT-44131) "UnsupportedOperationException: Don't know how to generate outer expression: Closure" when using suspend lambda and a function reference
- [`KT-44140`](https://youtrack.jetbrains.com/issue/KT-44140) JVM IR: compilation of kotlin.Result crashes with IOOBE while generating toString-impl
- [`KT-44141`](https://youtrack.jetbrains.com/issue/KT-44141) JVM IR: "ISE: There should be underlying type for inline class type" on usage of type parameter with Result upper bound inside a lambda
- [`KT-44192`](https://youtrack.jetbrains.com/issue/KT-44192) Allow a greater number of constants in an enum class
- [`KT-44202`](https://youtrack.jetbrains.com/issue/KT-44202) "ClassCastException" when getting delegated property with inline class and Any/Any? type
- [`KT-44210`](https://youtrack.jetbrains.com/issue/KT-44210) KJS / IR: "AssertionError: Undefined parameter referenced: <this> defined" caused by plus assign operators in build blocks
- [`KT-44233`](https://youtrack.jetbrains.com/issue/KT-44233) [IR] Collection Stub generation not correctly considering java.util Collection iterators
- [`KT-44234`](https://youtrack.jetbrains.com/issue/KT-44234) Private companion property with explicit setter generates invalid bytecode
- [`KT-44269`](https://youtrack.jetbrains.com/issue/KT-44269) "[TAILREC_ON_VIRTUAL_MEMBER_ERROR] Tailrec is not allowed on open members" with Spring annotation and private tailrec function
- [`KT-44284`](https://youtrack.jetbrains.com/issue/KT-44284) Make Kotlin binaries publicly unavailable (set KotlinCompilerVersion.IS_PRE_RELEASE = true)
- [`KT-44316`](https://youtrack.jetbrains.com/issue/KT-44316) ReenteringLazyValueComputationException when analyzing complex lazy delegate
- [`KT-44347`](https://youtrack.jetbrains.com/issue/KT-44347) Back-end (JVM) Internal error: Couldn't transform method node for suspend function with wrong local for Continuation
- [`KT-44368`](https://youtrack.jetbrains.com/issue/KT-44368) "IllegalStateException: Error type encountered" when inlining 'invoke' operator without enough information on type variable
- [`KT-44412`](https://youtrack.jetbrains.com/issue/KT-44412) JVM IR backend fails to compile break in condition of do while
- [`KT-44420`](https://youtrack.jetbrains.com/issue/KT-44420) False NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATION with 1.4.30-RC
- [`KT-44429`](https://youtrack.jetbrains.com/issue/KT-44429) JVM IR: unnecessary integer unboxing leads to NPE when using mockito-kotlin
- [`KT-44439`](https://youtrack.jetbrains.com/issue/KT-44439) Type inference of generic types failing java interop
- [`KT-44440`](https://youtrack.jetbrains.com/issue/KT-44440) Too many Nothings in inferred type
- [`KT-44471`](https://youtrack.jetbrains.com/issue/KT-44471) Fix failing script tests after switching to 1.5
- [`KT-44474`](https://youtrack.jetbrains.com/issue/KT-44474) Compiler expects sealed type inheritors from platform specific source-sets in when expression in common source-set
- [`KT-44483`](https://youtrack.jetbrains.com/issue/KT-44483) JVM IR: CCE on calling generic vararg function reference with Array expected type
- [`KT-44527`](https://youtrack.jetbrains.com/issue/KT-44527) Suspend function with kotlin.Result: ClassCastException class kotlin.Result cannot be cast to class ...
- [`KT-44529`](https://youtrack.jetbrains.com/issue/KT-44529) Inline class calls wrong iterator method in for loop
- [`KT-44533`](https://youtrack.jetbrains.com/issue/KT-44533) JVM IR: ClassFormatError on synthetic $suspendImpl method generated in interface for a @JvmDefault function
- [`KT-44540`](https://youtrack.jetbrains.com/issue/KT-44540) Regression in 1.4.30 in intellij-community: type mismatch for generic function call with generic Java class
- [`KT-44546`](https://youtrack.jetbrains.com/issue/KT-44546) NI: changed variable fixation order (that can lead to changed resolution)
- [`KT-44550`](https://youtrack.jetbrains.com/issue/KT-44550) KotlinBinaryClassCache leaks Kotlin plugin classloader on plugin unload
- [`KT-44563`](https://youtrack.jetbrains.com/issue/KT-44563) Type Inference loosing type annotations in lambda type expectation for function calls with block parameters
- [`KT-44583`](https://youtrack.jetbrains.com/issue/KT-44583) "Supertypes of the following classes cannot be resolved" error message gives no context
- [`KT-44627`](https://youtrack.jetbrains.com/issue/KT-44627) JVM IR: ACCIDENTAL_OVERRIDE when overriding a generic field where the type parameter has a primitive bound
- [`KT-44631`](https://youtrack.jetbrains.com/issue/KT-44631) "IndexOutOfBoundsException: Cannot pop operand off an empty stack" caused by a default param in inner class constructor which uses method or field from receiver
- [`KT-44647`](https://youtrack.jetbrains.com/issue/KT-44647) "IllegalAccessError: class TestKt tried to access private method" with String Builder `get` and `inc` operator
- [`KT-44651`](https://youtrack.jetbrains.com/issue/KT-44651) JVM / IR: "IllegalStateException: Illegal type substitutor" with if-else inside class constructor argument inside another if-else
- [`KT-44660`](https://youtrack.jetbrains.com/issue/KT-44660) Internal inline functions in companion object with inline class return type fails compilation
- [`KT-44671`](https://youtrack.jetbrains.com/issue/KT-44671) JVM_IR: ClassCastException: Result$Failure cannot be cast to Result with multithreaded coroutines
- [`KT-44703`](https://youtrack.jetbrains.com/issue/KT-44703) JVM / IR: "IllegalStateException: Unhandled special name in mangledNameFor" caused by a reference to inline class inside interface's companion with lazy initialization
- [`KT-44712`](https://youtrack.jetbrains.com/issue/KT-44712) JVM / IR: Behavior change after enabling with Mockito
- [`KT-44714`](https://youtrack.jetbrains.com/issue/KT-44714) Debugger / Coroutines: Local variables are trimmed out too aggressively
- [`KT-44722`](https://youtrack.jetbrains.com/issue/KT-44722) JVM IR: ClassCastException with inline class, let and bound function reference
- [`KT-44726`](https://youtrack.jetbrains.com/issue/KT-44726) JVM IR: Incorrect KType nullability for platform type reified as non-null
- [`KT-44781`](https://youtrack.jetbrains.com/issue/KT-44781) JVM IR: java.lang.NoSuchFieldError: $noName_0 when calling a crossinline lambda within a suspending lambda
- [`KT-44798`](https://youtrack.jetbrains.com/issue/KT-44798) JVM IR: Inherited platform declarations clash for class implementing both List and Set
- [`KT-44801`](https://youtrack.jetbrains.com/issue/KT-44801) 1.4.30 JVM IR: Unbound symbols not allowed with anonymous object
- [`KT-44803`](https://youtrack.jetbrains.com/issue/KT-44803) FIR bootstrap: incorrect nullability is set for type alias-based type
- [`KT-44827`](https://youtrack.jetbrains.com/issue/KT-44827) Non-existing outer class is written in anonymous class for SAM wrapper in inline lambda with capture
- [`KT-44837`](https://youtrack.jetbrains.com/issue/KT-44837) JVM / IR: ClassCastException with Result object when it is used by a generic method in a suspend call
- [`KT-44875`](https://youtrack.jetbrains.com/issue/KT-44875) JVM_IR. `hashCode` call is generated on interface target in fun interface equality
- [`KT-44878`](https://youtrack.jetbrains.com/issue/KT-44878) JVM_IR: "IllegalStateException: Unexpected types" when checking non-nullable variable is `in` range between nullable ones with smart-cast
- [`KT-44926`](https://youtrack.jetbrains.com/issue/KT-44926) MPP: Actual typealias to compiled inline class incompatible with expect inline class
- [`KT-44947`](https://youtrack.jetbrains.com/issue/KT-44947) Sealed interfaces: Sealed fun interface leads to "NoWhenBranchMatchedException"
- [`KT-44993`](https://youtrack.jetbrains.com/issue/KT-44993) JVM IR: VerifyError on getfield with Kotlin generic field and elvis operator
- [`KT-45008`](https://youtrack.jetbrains.com/issue/KT-45008) JVM IR: hashCode is generated as invokeinterface if smart cast to interface is present
- [`KT-45011`](https://youtrack.jetbrains.com/issue/KT-45011) JVM / IR: "AssertionError: Unbound symbols not allowed"
- [`KT-45022`](https://youtrack.jetbrains.com/issue/KT-45022) IR: "AssertionError: Undefined variable referenced" from psi2ir caused by plusAssign operator of object
- [`KT-45064`](https://youtrack.jetbrains.com/issue/KT-45064) JVM IR: "java.lang.AssertionError: SyntheticAccessorLowering should not attempt to modify other files!" with member reference to property in another file with private setter
- [`KT-45067`](https://youtrack.jetbrains.com/issue/KT-45067) "IllegalArgumentException: Wildcard mast have a bound for annotation of WILDCARD_BOUND position" with BEAM SDK 2.27
- [`KT-45069`](https://youtrack.jetbrains.com/issue/KT-45069) JVM / IR: New SAM conversions mode fails when converting from Unit to Any
- [`KT-45131`](https://youtrack.jetbrains.com/issue/KT-45131) JVM / IR: "RuntimeException: Lambda, SAM or anonymous object should have only one constructor" caused by inline class that type cast to reified type parameter inside lambda in inline function
- [`KT-45139`](https://youtrack.jetbrains.com/issue/KT-45139) Inline class: AssertionError: Expected top level inline class
- [`KT-45166`](https://youtrack.jetbrains.com/issue/KT-45166) JVM / IR: "AbstractMethodError: Receiver class does not define or inherit an implementation of the resolved method of interface" caused by interface with suspend function
- [`KT-45187`](https://youtrack.jetbrains.com/issue/KT-45187) JVM / IR: ClassCastException caused by substituting generic type of vararg parameter with java.lang.Void
- [`KT-45195`](https://youtrack.jetbrains.com/issue/KT-45195) JVM IR: annotation methods are generated as default interface methods if `allopen` is used
- [`KT-45243`](https://youtrack.jetbrains.com/issue/KT-45243) "IllegalStateException: Lambdas shouldn't be visited by ESExpressionVisitor" caused by lambda inside `kotlin.test.assertNotNull`
- [`KT-45259`](https://youtrack.jetbrains.com/issue/KT-45259) JVM: ClassCastException caused by Result as lambda parameter type
- [`KT-45292`](https://youtrack.jetbrains.com/issue/KT-45292) AssertionError with recursive inline extension property
- [`KT-45300`](https://youtrack.jetbrains.com/issue/KT-45300) Deprecate super calls in public-api inline functions
- [`KT-45409`](https://youtrack.jetbrains.com/issue/KT-45409) Rename jspecify annotations package and default not null annotation
- [`KT-45446`](https://youtrack.jetbrains.com/issue/KT-45446) JVM / IR: NullPointerException caused by unreachable code and comparison
- [`KT-45721`](https://youtrack.jetbrains.com/issue/KT-45721) JVM / IR: "Unbound symbols not allowed" caused by class reference in sequence lambda
- [`KT-45853`](https://youtrack.jetbrains.com/issue/KT-45853) JVM / IR: "Accidental override" caused by inheriting Throwable.getCause from Java interface
- [`KT-45861`](https://youtrack.jetbrains.com/issue/KT-45861) Turning warnings into errors for calls with type parameters annotated by @OnlyInputTypes
- [`KT-45865`](https://youtrack.jetbrains.com/issue/KT-45865) JVM IR: "VerifyError: Bad type on operand stack" with `enumValueOf` on a value from a list of strings
- [`KT-45868`](https://youtrack.jetbrains.com/issue/KT-45868) JVM IR: ClassCastException with SAM function in init block when SAM is generated via invokedynamic
- [`KT-45920`](https://youtrack.jetbrains.com/issue/KT-45920) JVM IR: "Accidental override" on redefining `get()` in custom Map class
- [`KT-45934`](https://youtrack.jetbrains.com/issue/KT-45934) JVM IR: "java.lang.IllegalStateException: Function has no body" for class implementing interface by delegation
- [`KT-45945`](https://youtrack.jetbrains.com/issue/KT-45945) JVM / IR: "AssertionError: Unexpected variance in super type argument" with contravariance and intersection types
- [`KT-45963`](https://youtrack.jetbrains.com/issue/KT-45963) JVM / IR: "AbstractMethodError: Receiver class does not define or inherit an implementation of the resolved method" in Dokka tests
- [`KT-45967`](https://youtrack.jetbrains.com/issue/KT-45967) JVM IR: "IllegalAccessError" with invokedynamic to Java SAM over callable reference to private function
- [`KT-45982`](https://youtrack.jetbrains.com/issue/KT-45982) Wrong subtyping result on captured types with postponed type variables
- [`KT-46007`](https://youtrack.jetbrains.com/issue/KT-46007) JVM / IR: "ClassCastException: kotlin.Unit cannot be cast to java.lang.String" caused by default suspend function in interface
- [`KT-46060`](https://youtrack.jetbrains.com/issue/KT-46060) JVM IR: NullPointerException from RangeContainsLowering when `contains` is a @JvmStatic function in object
- [`KT-46069`](https://youtrack.jetbrains.com/issue/KT-46069) JVM IR: unbound type parameter on generic bound adapted function reference
- [`KT-46092`](https://youtrack.jetbrains.com/issue/KT-46092) JVM IR: AssertionError "Array type expected: @[FlexibleNullability] kotlin.CharArray?" on super call to Java constructor with primitive vararg
- [`KT-46104`](https://youtrack.jetbrains.com/issue/KT-46104) The message on inline -> value class migration should not say that inline classes are deprecated
- [`KT-46131`](https://youtrack.jetbrains.com/issue/KT-46131) Kotlin 1.5.0-RC errors when reading class file
- [`KT-46160`](https://youtrack.jetbrains.com/issue/KT-46160) JVM IR: IllegalAccessException at runtime for member reference to JvmMultifileClass member from stdlib
- [`KT-46186`](https://youtrack.jetbrains.com/issue/KT-46186) Type inference regression in Kotlin 1.5 with constrained generic return types
### Docs & Examples
- [`KT-45884`](https://youtrack.jetbrains.com/issue/KT-45884) Incorrect description for JVM `toUpperCase` method
### IDE
- [`KT-33233`](https://youtrack.jetbrains.com/issue/KT-33233) Use dependency of library to build built-ins in IDE, instead of loading them from the current classloader
- [`KT-34023`](https://youtrack.jetbrains.com/issue/KT-34023) kotlin.KotlinNullPointerException at org.jetbrains.kotlin.backend.common.FunctionsFromAnyGenerator.getPrimaryConstructorProperties(FunctionsFromAnyGenerator.kt:66)
- [`KT-35947`](https://youtrack.jetbrains.com/issue/KT-35947) KFunctionN.call is unresolved in IDE in Kotlin/JVM project
- [`KT-37702`](https://youtrack.jetbrains.com/issue/KT-37702) Code analysis speed: on-the-fly analysis diagnostics reporting
- [`KT-41048`](https://youtrack.jetbrains.com/issue/KT-41048) [FIR-IDE] Properly implement methods in KtFirPackageScope
- [`KT-41671`](https://youtrack.jetbrains.com/issue/KT-41671) Missing nullability information in properties using type inference from get()
- [`KT-43824`](https://youtrack.jetbrains.com/issue/KT-43824) KtLightClassForSourceDeclaration#isInheritor works in a different way than java implementation
- [`KT-44128`](https://youtrack.jetbrains.com/issue/KT-44128) IDE: Kotlin JVM record has incorrect property accessors as seen from Java
- [`KT-44487`](https://youtrack.jetbrains.com/issue/KT-44487) MPP, IDE: No error in IDE when sealed class inheritor from common source-set is not used in exhaustive when expression in platform source-set
- [`KT-45254`](https://youtrack.jetbrains.com/issue/KT-45254) Highlighting for files with certain errors appears only on second opening
- [`KT-46097`](https://youtrack.jetbrains.com/issue/KT-46097) Light classes: Incomplete nullability information for a getter method of a kotlin property defined in private constructor
### IDE. Decompiler, Indexing, Stubs
- [`KT-43699`](https://youtrack.jetbrains.com/issue/KT-43699) IDE: Unresolved extension method from Java code for simple class with typealias and generics (IllegalStateException: Unknown type parameter)
- [`KT-44756`](https://youtrack.jetbrains.com/issue/KT-44756) Infinite "UpToDateStubIndexMismatch: PSI and index do not match." with IDEA 2021.1 EAP upon attempt to open "org.gradle.configurationcache" even they seem to be the same
### IDE. Gradle Integration
- [`KT-37127`](https://youtrack.jetbrains.com/issue/KT-37127) Implement precise importing of platforms of root source sets (commonMain/commonTest) when hierarchical multiplatform support is enabled
- [`KT-42048`](https://youtrack.jetbrains.com/issue/KT-42048) KJS / Gradle integration: Could not determine the dependencies of task ':webApp:testPackageJson' in Android Studio 4.2 Canary 11
### IDE. Gradle. Script
- [`KT-46215`](https://youtrack.jetbrains.com/issue/KT-46215) Dead lock on closing project during the import in IJ211 through ScriptDefinitionsManager
### IDE. Inspections and Intentions
- [`KT-23824`](https://youtrack.jetbrains.com/issue/KT-23824) Return lifted out of if condition causes suspend tail call optimization to no longer apply
- [`KT-38155`](https://youtrack.jetbrains.com/issue/KT-38155) Lift assignment out of 'if' produces type mismatch without manually adding a semicolon
- [`KT-44821`](https://youtrack.jetbrains.com/issue/KT-44821) IDE: False positive NO_ELSE_IN_WHEN caused by sealed class and when in another module
- [`KT-46088`](https://youtrack.jetbrains.com/issue/KT-46088) [IDEA] Incorrect behavior of replace inline class with value class intention
### IDE. Misc
- [`KT-44675`](https://youtrack.jetbrains.com/issue/KT-44675) Incorrect reference to resource into 202 plugin
### IDE. Refactorings
- [`KT-44079`](https://youtrack.jetbrains.com/issue/KT-44079) Sealed Interfaces: Move refactoring should warn about violation of hierarchy restrictions
- [`KT-44839`](https://youtrack.jetbrains.com/issue/KT-44839) Sealed interfaces: move refactoring warnings works with "more freedom for sealed classes" rules for language level < 1.5
### IDE. Script
- [`KT-43288`](https://youtrack.jetbrains.com/issue/KT-43288) Allow push notifications about script configuration /dependencies changes via the `ScriptDefinitionsProvider` EP
### JavaScript
- [`KT-39272`](https://youtrack.jetbrains.com/issue/KT-39272) KJS / IR: Can't use javascript keywords as JsName
- [`KT-41650`](https://youtrack.jetbrains.com/issue/KT-41650) JS IR BE: `default` should be a reserved identifier
- [`KT-42176`](https://youtrack.jetbrains.com/issue/KT-42176) KJS / IR: Interface default method in sub-interface not resolved correctly from extension on super-interface
- [`KT-44103`](https://youtrack.jetbrains.com/issue/KT-44103) [JSIR] TypeError when bumping from 1.4.20 to 1.4.30-M1
- [`KT-44180`](https://youtrack.jetbrains.com/issue/KT-44180) KJS / IR: NPE in ConstTransformer of compileDevelopmentExecutableKotlinJs/compileProductionExecutableKotlinJs tasks
- [`KT-44415`](https://youtrack.jetbrains.com/issue/KT-44415) Kotlin/JS with IR and kotlin-react: "too much recursion" error in runtime in browser
- [`KT-44433`](https://youtrack.jetbrains.com/issue/KT-44433) KJS IR: support function interfaces with suspend member
- [`KT-44469`](https://youtrack.jetbrains.com/issue/KT-44469) KJS / IR: Incorrect export functions with bridges
- [`KT-44718`](https://youtrack.jetbrains.com/issue/KT-44718) MPP/ KJS: "IllegalStateException: Unsupported operation" with serialization plugin and incremental compilation
- [`KT-44796`](https://youtrack.jetbrains.com/issue/KT-44796) KJS / IR: default parameter of function with @JsName leads to "RangeError: Maximum call stack size exceeded"
- [`KT-45059`](https://youtrack.jetbrains.com/issue/KT-45059) KJS / IR: Add possibility for runtime diagnostics of DCE result
### Libraries
- [`KT-12109`](https://youtrack.jetbrains.com/issue/KT-12109) Add stdlib method that combines mapNotNull() and first/firstOrNull()
- [`KT-25571`](https://youtrack.jetbrains.com/issue/KT-25571) Make random implementations serializable
- [`KT-26234`](https://youtrack.jetbrains.com/issue/KT-26234) Floored division and remainder function for numeric types
- [`KT-32996`](https://youtrack.jetbrains.com/issue/KT-32996) kotlin.test: add assertContentEquals for comparing content of arrays, iterables, sequences
- [`KT-39177`](https://youtrack.jetbrains.com/issue/KT-39177) Make CharCategory available in common multiplatform code
- [`KT-40225`](https://youtrack.jetbrains.com/issue/KT-40225) Support adding kotlin-test as a single dependency, as it should be with a multiplatform library
- [`KT-42071`](https://youtrack.jetbrains.com/issue/KT-42071) Strict version of String.toBoolean()
- [`KT-42720`](https://youtrack.jetbrains.com/issue/KT-42720) Kotlin ArrayDeque on JVM: provide optimized toArray method
- [`KT-42840`](https://youtrack.jetbrains.com/issue/KT-42840) Commonize and generalize String.contentEquals that is currently JVM-only
- [`KT-43772`](https://youtrack.jetbrains.com/issue/KT-43772) Kotlin/Native unfinished workers detected.
- [`KT-44168`](https://youtrack.jetbrains.com/issue/KT-44168) Prevent storing NaN and negative zero in kotlin.time.Duration
- [`KT-44369`](https://youtrack.jetbrains.com/issue/KT-44369) Commonize Char.titlecaseChar() and Char.titlecase() that are currently JVM-only
- [`KT-44783`](https://youtrack.jetbrains.com/issue/KT-44783) Add IS_VALUE flag for value classes to kotlinx-metadata-jvm
- [`KT-44815`](https://youtrack.jetbrains.com/issue/KT-44815) Remove kotlin-annotations-android and JVM compiler support for @ParameterName/@DefaultValue/@DefaultNull
- [`KT-45213`](https://youtrack.jetbrains.com/issue/KT-45213) Update Unicode version used in K/N for Char and String case conversion functions
### Middle-end. IR
- [`KT-43831`](https://youtrack.jetbrains.com/issue/KT-43831) Compilation failed, IrSimpleFunctionPublicSymbolImpl is already bound
- [`KT-44100`](https://youtrack.jetbrains.com/issue/KT-44100) KJS / IR: Top level declarations added in IR plugin are not referenceable from other modules
- [`KT-45170`](https://youtrack.jetbrains.com/issue/KT-45170) IR: "AssertionError: Single expression value for GET_OBJECT" caused by inc operator of field inside scope function inside object
### Native
- [`KT-42446`](https://youtrack.jetbrains.com/issue/KT-42446) Native: SIGSEGV in Kotlin_Array_get on linuxArm64
- [`KT-43502`](https://youtrack.jetbrains.com/issue/KT-43502) [K/N] relocation R_X86_64_PC32 cannot be used against symbol __environ; recompile with -fPIC
- [`KT-44295`](https://youtrack.jetbrains.com/issue/KT-44295) 1.4.21 Kotlin native ndk compiler crash
- [`KT-44774`](https://youtrack.jetbrains.com/issue/KT-44774) ld fails with CALL16 reloc at 0x48f00 not against global symbol (Linux MIPS)
- [`KT-44746`](https://youtrack.jetbrains.com/issue/KT-44746) Different hashCode() results for Kotlin/Native stdlib
### Native. C and ObjC Import
- [`KT-44824`](https://youtrack.jetbrains.com/issue/KT-44824) cinterop tool no longer appends .klib to produced klibs
### Native. C Export
- [`KT-36639`](https://youtrack.jetbrains.com/issue/KT-36639) MPP: Build ios "staticLib" or "sharedLib" binary failed if interface contains member extension function
- [`KT-41725`](https://youtrack.jetbrains.com/issue/KT-41725) Dynamic library doesn't load on raspberrypi
### Native. ObjC Export
- [`KT-44549`](https://youtrack.jetbrains.com/issue/KT-44549) In the Xcode debug session, call stack is missing a frame when the iOS app fails
### Native. Platforms
- [`KT-45094`](https://youtrack.jetbrains.com/issue/KT-45094) Fail to compile Kotlin Native sources under Oracle Linux 7
### Reflection
- [`KT-44594`](https://youtrack.jetbrains.com/issue/KT-44594) Avoid using unnecessary array types reflection in kotlin-reflect
- [`KT-44782`](https://youtrack.jetbrains.com/issue/KT-44782) Add KClass.isValue to kotlin-reflect
### Tools. Ant
- [`KT-16227`](https://youtrack.jetbrains.com/issue/KT-16227) Ant task: do not include runtime by default if destination is a jar
- [`KT-44293`](https://youtrack.jetbrains.com/issue/KT-44293) Support fork mode in kotlinc Ant task
### Tools. CLI
- [`KT-17344`](https://youtrack.jetbrains.com/issue/KT-17344) Include kotlin-reflect to resulting jar if "-include-runtime" is specified
- [`KT-43220`](https://youtrack.jetbrains.com/issue/KT-43220) -include-runtime should add .kotlin_builtins to the output
- [`KT-43704`](https://youtrack.jetbrains.com/issue/KT-43704) Illegal reflective access by com.intellij.util.ReflectionUtil to method java.util.ResourceBundle.setParent(java.util.ResourceBundle)
- [`KT-44078`](https://youtrack.jetbrains.com/issue/KT-44078) Do not include module-info.class of kotlin-stdlib.jar to the resulting jar with -include-runtime
- [`KT-44232`](https://youtrack.jetbrains.com/issue/KT-44232) CLI: do not pass -noverify to java process starting from JDK 13
- [`KT-45566`](https://youtrack.jetbrains.com/issue/KT-45566) JDK 16 - e: java.lang.NoClassDefFoundError: Could not initialize class org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel
### Tools. CLI. Native
- [`KT-43874`](https://youtrack.jetbrains.com/issue/KT-43874) Native / CLI: provide a way to show difference between Jvm and Native compilers
### Tools. Compiler Plugins
- [`KT-45783`](https://youtrack.jetbrains.com/issue/KT-45783) Serialization: "AnalyzerException: Expected an object reference, but found I" caused by `JvmInline` and `Serializable` annotations
### Tools. Gradle
- [`KT-31027`](https://youtrack.jetbrains.com/issue/KT-31027) java.lang.NoSuchMethodError: No static method hashCode(Z)I in class Ljava/lang/Boolean; or its super classes (declaration of 'java.lang.Boolean' appears in /system/framework/core-libart.jar)
- [`KT-43605`](https://youtrack.jetbrains.com/issue/KT-43605) Kotlin Gradle Plugin 1.4.20 undeclared system property reads cause problems with Gradle configuration cache enabled
- [`KT-44204`](https://youtrack.jetbrains.com/issue/KT-44204) Kotlin Gradle Plugin 1.4.21 makes impossible to use ANTLR in other plugins
- [`KT-44361`](https://youtrack.jetbrains.com/issue/KT-44361) Gradle: deprecate options includeRuntime, noStdlib, noReflect
- [`KT-44462`](https://youtrack.jetbrains.com/issue/KT-44462) Kotlin Gradle plugin creates `compile` configuration with Gradle 7.0
- [`KT-44834`](https://youtrack.jetbrains.com/issue/KT-44834) Gradle Kotlin DSL: Add `languageSettings` configuration lambda without `apply` call
- [`KT-44949`](https://youtrack.jetbrains.com/issue/KT-44949) Compatibility with Gradle 7.0
- [`KT-44957`](https://youtrack.jetbrains.com/issue/KT-44957) gradle - target.compilations seems to be deprecated
- [`KT-45340`](https://youtrack.jetbrains.com/issue/KT-45340) Update minimal supported version of Kotlin Gradle Plugin to 6.1
### Tools. Gradle. JS
- [`KT-43237`](https://youtrack.jetbrains.com/issue/KT-43237) KJS: `-jsLegacy` Naming Convention is incompatible with NPM
- [`KT-43869`](https://youtrack.jetbrains.com/issue/KT-43869) Error in webpack configuration not displayed
- [`KT-44614`](https://youtrack.jetbrains.com/issue/KT-44614) Update Node.JS and Yarn versions
- [`KT-44616`](https://youtrack.jetbrains.com/issue/KT-44616) Kotlin/JS: IR backend with React: "Uncaught TypeError: _this__0 is undefined" runtime error in browser
- [`KT-45574`](https://youtrack.jetbrains.com/issue/KT-45574) Sync Kotlin/JS compile tasks into one folder (build/js/packages/<package>/kotlin)
### Tools. Gradle. Multiplatform
- [`KT-42098`](https://youtrack.jetbrains.com/issue/KT-42098) Commonizer is re-launched for every included Gradle build
- [`KT-43116`](https://youtrack.jetbrains.com/issue/KT-43116) Merge together MultiplatformHighlightingTest and MultiplatformAnalysisTest
- [`KT-44322`](https://youtrack.jetbrains.com/issue/KT-44322) KotlinTargetComponent maintenance for -sources.jar
- [`KT-44900`](https://youtrack.jetbrains.com/issue/KT-44900) Support gradle configuration cache with kotlin.multiplatform plugin
### Tools. Gradle. Native
- [`KT-46122`](https://youtrack.jetbrains.com/issue/KT-46122) kotlinx-serialization and kotlinx-datetime can't be built with 1.5.0-RC
### Tools. JPS
- [`KT-13631`](https://youtrack.jetbrains.com/issue/KT-13631) Compilation fails on Turkish locale because of locale-sensitive uppercasing
- [`KT-44644`](https://youtrack.jetbrains.com/issue/KT-44644) Mark all `@JvmMultifileClass` parts compiled in the previous round as dirty in the JPS plugin, similarly to how its done in the Gradle plugin
### Tools. Scripts
- [`KT-45194`](https://youtrack.jetbrains.com/issue/KT-45194) KT: Generate Kotlin Entities script: it doesn't work
- [`KT-44580`](https://youtrack.jetbrains.com/issue/KT-44580) Scripts: Unable to set new file annotation hooks after first snippet compilation
### Tools. kapt
- [`KT-43686`](https://youtrack.jetbrains.com/issue/KT-43686) KaptWithoutKotlincTask should use `@CompileClasspath` for `kotlinStdlibClasspath` for cache relocateability.
- [`KT-44130`](https://youtrack.jetbrains.com/issue/KT-44130) KAPT changes field order in 1.4.30-M1
- [`KT-44909`](https://youtrack.jetbrains.com/issue/KT-44909) Kapt: ReenteringLazyValueComputationException without stacktrace caused by `when` expression with sealed class function without explicit return type
- [`KT-45168`](https://youtrack.jetbrains.com/issue/KT-45168) KAPT: Java stubs generated for Kotlin files generated by annotation processors
## 1.4.32
### IDE
- [`KT-43824`](https://youtrack.jetbrains.com/issue/KT-43824) KtLightClassForSourceDeclaration#isInheritor works in a different way than java implementation
- [`KT-45287`](https://youtrack.jetbrains.com/issue/KT-45287) LightClasses: `KtLightSimpleModifierList` is no more a parent of `KtLightAnnotationForSourceEntry`
- [`KT-45291`](https://youtrack.jetbrains.com/issue/KT-45291) LightClasses: can't get annotations for constructor val-parameter
- [`KT-45417`](https://youtrack.jetbrains.com/issue/KT-45417) ULC leakage of primitive type annotations
### Tools. CLI
- [`KT-44758`](https://youtrack.jetbrains.com/issue/KT-44758) kotlin-compiler-embeddable dependency includes unshaded `fastutil` package
- [`KT-45007`](https://youtrack.jetbrains.com/issue/KT-45007) Concurrent Kotlin script compilation/execution results in NullPointerException in KeyedExtensionCollector.getPoint()
## 1.4.31
### Compiler
- [`KT-39776`](https://youtrack.jetbrains.com/issue/KT-39776) 2020.3+: Unresolved reference to Kotlin stdlib function
### IDE. Gradle Integration
- [`KT-44845`](https://youtrack.jetbrains.com/issue/KT-44845) After update to Kotlin 1.4.30 all external dependencies is unresolved in IDE with kotlin.mpp.enableGranularSourceSetsMetadata=true
### IDE. Gradle. Script
- [`KTIJ-11137`](https://youtrack.jetbrains.com/issue/KTIJ-1137) build.gradle.kts: Fatal error during save/load standalone scripts settings
- [`KTIJ-898`](https://youtrack.jetbrains.com/issue/KTIJ-898) Unable to import with Kotlin DSL buildscript - NullPointerException in KotlinDslScriptModelProcessorKt.toListOfScriptModels
### IDE. Multiplatform
- [`KTIJ-1200`](https://youtrack.jetbrains.com/issue/KTIJ-1200) KotlinIconProviderKt.addExpectActualMarker takes up to 180+ seconds
### IDE
#### Fixes
- [`KT-44697`](https://youtrack.jetbrains.com/issue/KT-44697) New JVM IR backend notification - narrow its triggering to Kotlin projects
- [`KT-44523`](https://youtrack.jetbrains.com/issue/KT-44523) IDE notification for trying new JVM backend
- [`KTIJ-696`](https://youtrack.jetbrains.com/issue/KTIJ-696) Freeze during startup of IDEA with intellij project with Kotlin (211-1.4.10-release-IJ1440)
## 1.4.30

View File

@@ -1,11 +1,11 @@
import kotlinx.benchmark.gradle.benchmark
val benchmarks_version = "0.3.1"
val benchmarks_version = "0.3.0"
plugins {
java
kotlin("jvm")
id("org.jetbrains.kotlinx.benchmark") version "0.3.1"
id("org.jetbrains.kotlinx.benchmark") version "0.3.0"
}
dependencies {

View File

@@ -12,7 +12,6 @@ import com.intellij.psi.PsiFileFactory
import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.ObsoleteTestInfrastructure
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -148,7 +147,6 @@ abstract class AbstractSimpleFileBenchmark {
bh.consume(result.shouldGenerateCode)
}
@OptIn(ObsoleteTestInfrastructure::class)
private fun analyzeGreenFileIr(bh: Blackhole) {
val scope = GlobalSearchScope.filesScope(env.project, listOf(file.virtualFile))
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project))

View File

@@ -39,4 +39,4 @@ class GeneratedJvmClass(
}
}
fun File.isModuleMappingFile() = extension == ModuleMapping.MAPPING_FILE_EXT && parentFile.name == "META-INF"
fun File.isModuleMappingFile() = extension == ModuleMapping.MAPPING_FILE_EXT && parentFile.name == "META-INF"

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.incremental
import com.intellij.util.io.DataExternalizer
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
import org.jetbrains.kotlin.incremental.js.IrTranslationResultValue
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
@@ -49,7 +48,6 @@ open class IncrementalJsCache(
private const val INLINE_FUNCTIONS = "inline-functions"
private const val HEADER_FILE_NAME = "header.meta"
private const val PACKAGE_META_FILE = "packages-meta"
private const val SOURCE_TO_JS_OUTPUT = "source-to-js-output"
fun hasHeaderFile(cachesDir: File) = File(cachesDir, HEADER_FILE_NAME).exists()
}
@@ -62,7 +60,6 @@ open class IncrementalJsCache(
private val irTranslationResults = registerMap(IrTranslationResultMap(IR_TRANSLATION_RESULT_MAP.storageFile, pathConverter))
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, pathConverter))
private val packageMetadata = registerMap(PackageMetadataMap(PACKAGE_META_FILE.storageFile))
private val sourceToJsOutputsMap = registerMap(SourceToJsOutputMap(SOURCE_TO_JS_OUTPUT.storageFile, pathConverter))
private val dirtySources = hashSetOf<File>()
@@ -78,7 +75,6 @@ open class IncrementalJsCache(
override fun markDirty(removedAndCompiledSources: Collection<File>) {
removedAndCompiledSources.forEach { sourceFile ->
sourceToJsOutputsMap.remove(sourceFile)
// The common prefix of all FQN parents has to be the file package
sourceToClassesMap[sourceFile].map { it.parentOrNull()?.asString() ?: "" }.minByOrNull { it.length }?.let {
packageMetadata.remove(it)
@@ -99,10 +95,6 @@ open class IncrementalJsCache(
}
}
fun getOutputsBySource(sourceFile: File): Collection<File> {
return sourceToJsOutputsMap.get(sourceFile)
}
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
val translatedFiles = incrementalResults.packageParts
@@ -183,17 +175,6 @@ open class IncrementalJsCache(
}
}
}
fun updateSourceToOutputMap(
generatedFiles: Iterable<GeneratedFile>,
) {
for (generatedFile in generatedFiles) {
for (source in generatedFile.sourceFiles) {
if (dirtySources.contains(source))
sourceToJsOutputsMap.add(source, generatedFile.outputFile)
}
}
}
}
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
@@ -234,20 +215,17 @@ private class TranslationResultMap(
override fun dumpValue(value: TranslationResultValue): String =
"Metadata: ${value.metadata.md5()}, Binary AST: ${value.binaryAst.md5()}, InlineData: ${value.inlineData.md5()}"
@Synchronized
fun put(sourceFile: File, newMetadata: ByteArray, newBinaryAst: ByteArray, newInlineData: ByteArray) {
storage[pathConverter.toPath(sourceFile)] =
TranslationResultValue(metadata = newMetadata, binaryAst = newBinaryAst, inlineData = newInlineData)
}
@Synchronized
operator fun get(sourceFile: File): TranslationResultValue? =
storage[pathConverter.toPath(sourceFile)]
fun keys(): Collection<File> =
storage.keys.map { pathConverter.toFile(it) }
@Synchronized
fun remove(sourceFile: File, changesCollector: ChangesCollector) {
val path = pathConverter.toPath(sourceFile)
val protoBytes = storage[path]!!.metadata
@@ -381,7 +359,6 @@ private class InlineFunctionsMap(
storageFile: File,
private val pathConverter: FileToPathConverter
) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
@Synchronized
fun process(srcFile: File, newMap: Map<String, Long>, changesCollector: ChangesCollector) {
val key = pathConverter.toPath(srcFile)
val oldMap = storage[key] ?: emptyMap()
@@ -399,7 +376,6 @@ private class InlineFunctionsMap(
}
}
@Synchronized
fun remove(sourceFile: File) {
storage.remove(pathConverter.toPath(sourceFile))
}

View File

@@ -47,16 +47,10 @@ abstract class BasicMap<K : Comparable<K>, V>(
storage.flush(memoryCachesOnly)
}
// avoid unsynchronized close
fun close() {
storage.close()
}
@TestOnly
fun closeForTest() {
close()
}
@TestOnly
fun dump(): String {
return with(StringBuilder()) {

View File

@@ -34,6 +34,7 @@ class CachingLazyStorage<K, V>(
) : LazyStorage<K, V> {
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
@@ -45,36 +46,32 @@ class CachingLazyStorage<K, V>(
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
}
return storage!!
}
override val keys: Collection<K>
@Synchronized
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
@Synchronized
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
@Synchronized
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
@Synchronized
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
@Synchronized
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
@Synchronized
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key, { valueExternalizer.save(it, value) })
}
@@ -106,11 +103,7 @@ class CachingLazyStorage<K, V>(
@Synchronized
override fun close() {
try {
storage?.close()
} finally {
storage = null
}
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> = PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)

View File

@@ -28,7 +28,6 @@ internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collec
storage.append(key.asString(), listOf(value.asString()))
}
@Synchronized
operator fun get(key: FqName): Collection<FqName> =
storage[key.asString()]?.map(::FqName) ?: setOf()

View File

@@ -31,6 +31,7 @@ class NonCachingLazyStorage<K, V>(
) : LazyStorage<K, V> {
private var storage: PersistentHashMap<K, V>? = null
@Synchronized
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
if (storage != null) return storage
@@ -42,6 +43,7 @@ class NonCachingLazyStorage<K, V>(
return null
}
@Synchronized
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
if (storage == null) {
storage = createMap()
@@ -51,28 +53,22 @@ class NonCachingLazyStorage<K, V>(
}
override val keys: Collection<K>
@Synchronized
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
@Synchronized
override operator fun contains(key: K): Boolean =
getStorageIfExists()?.containsMapping(key) ?: false
@Synchronized
override operator fun get(key: K): V? =
getStorageIfExists()?.get(key)
@Synchronized
override operator fun set(key: K, value: V) {
getStorageOrCreateNew().put(key, value)
}
@Synchronized
override fun remove(key: K) {
getStorageIfExists()?.remove(key)
}
@Synchronized
override fun append(key: K, value: V) {
getStorageOrCreateNew().appendData(key) { dataOutput -> valueExternalizer.save(dataOutput, value) }
}
@@ -104,11 +100,7 @@ class NonCachingLazyStorage<K, V>(
@Synchronized
override fun close() {
try {
storage?.close()
} finally {
storage = null
}
storage?.close()
}
private fun createMap(): PersistentHashMap<K, V> =

View File

@@ -1,43 +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.incremental.storage
import org.jetbrains.kotlin.incremental.dumpCollection
import java.io.File
class SourceToJsOutputMap(storageFile: File, private val pathConverter: FileToPathConverter) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
@Synchronized
fun add(key: File, value: File) {
storage.append(pathConverter.toPath(key), listOf(pathConverter.toPath(value)))
}
operator fun get(sourceFile: File): Collection<File> =
storage[pathConverter.toPath(sourceFile)]?.map { pathConverter.toFile(it) } ?: setOf()
@Synchronized
operator fun set(key: File, values: Collection<File>) {
if (values.isEmpty()) {
remove(key)
return
}
storage[pathConverter.toPath(key)] = values.map { pathConverter.toPath(it) }
}
@Synchronized
fun remove(key: File) {
storage.remove(pathConverter.toPath(key))
}
@Synchronized
fun removeValues(key: File, removed: Set<File>) {
val notRemoved = this[key].filter { it !in removed }
this[key] = notRemoved
}
}

View File

@@ -14,11 +14,8 @@ buildscript {
if (cacheRedirectorEnabled) {
maven("https://cache-redirector.jetbrains.com/plugins.gradle.org/m2")
maven("https://cache-redirector.jetbrains.com/repo.maven.apache.org/maven2")
} else {
maven("https://plugins.gradle.org/m2")
mavenCentral()
}
}
@@ -30,7 +27,7 @@ buildscript {
dependencies {
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.29")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.26")
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
classpath(kotlin("serialization", bootstrapKotlinVersion))
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
@@ -38,6 +35,10 @@ buildscript {
}
}
if (kotlinBuildProperties.buildScanServer != null) {
apply(from = "gradle/buildScanUserData.gradle")
}
plugins {
base
idea
@@ -182,7 +183,7 @@ extra["versions.jflex"] = "1.7.0"
extra["versions.markdown"] = "0.1.25"
extra["versions.trove4j"] = "1.0.20181211"
extra["versions.completion-ranking-kotlin"] = "0.1.3"
extra["versions.r8"] = "2.2.64"
extra["versions.r8"] = "2.1.96"
val immutablesVersion = "0.3.1"
extra["versions.kotlinx-collections-immutable"] = immutablesVersion
extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
@@ -297,7 +298,6 @@ extra["compilerModules"] = arrayOf(
":compiler:fir:java",
":compiler:fir:jvm",
":compiler:fir:checkers",
":compiler:fir:checkers:checkers.jvm",
":compiler:fir:entrypoint",
":compiler:fir:analysis-tests",
":compiler:fir:analysis-tests:legacy-fir-tests",
@@ -317,6 +317,7 @@ extra["compilerModulesForJps"] = listOf(
":core:compiler.common.jvm",
":core:descriptors",
":core:descriptors.jvm",
":idea:idea-jps-common",
":kotlin-preloader",
":compiler:util",
":compiler:config",
@@ -326,48 +327,13 @@ extra["compilerModulesForJps"] = listOf(
":compiler:compiler.version"
)
extra["compilerArtifactsForIde"] = listOf(
":prepare:ide-plugin-dependencies:android-extensions-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:allopen-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:incremental-compilation-impl-tests-for-ide",
":prepare:ide-plugin-dependencies:js-ir-runtime-for-ide",
":prepare:ide-plugin-dependencies:kotlin-build-common-tests-for-ide",
":prepare:ide-plugin-dependencies:kotlin-compiler-for-ide",
":prepare:ide-plugin-dependencies:kotlin-compiler-cli-for-ide",
":prepare:ide-plugin-dependencies:kotlin-gradle-statistics-for-ide",
":prepare:ide-plugin-dependencies:kotlinx-serialization-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:noarg-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:compiler-components-for-jps",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:kotlin-compiler-tests-for-ide",
":prepare:ide-plugin-dependencies:kotlin-compiler-testdata-for-ide",
":kotlin-script-runtime",
":kotlin-script-util",
":kotlin-scripting-common",
":kotlin-scripting-jvm",
":kotlin-scripting-compiler",
":kotlin-scripting-compiler-impl",
":kotlin-android-extensions-runtime",
":kotlin-stdlib-common",
":kotlin-stdlib",
":kotlin-stdlib-jdk7",
":kotlin-stdlib-jdk8",
":kotlin-reflect",
":kotlin-main-kts"
)
// 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-base:compileKotlin",
":plugins:uast-kotlin:compileKotlin",
":plugins:uast-kotlin:compileTestKotlin",
":plugins:uast-kotlin-fir:compileKotlin",
":plugins:uast-kotlin-fir:compileTestKotlin"
":plugins:uast-kotlin:compileTestKotlin"
)
val tasksWithWarnings: List<String> by extra
@@ -412,7 +378,7 @@ apply {
}
apply {
if (extra["isDeployStagingRepoGenerationRequired"] as? Boolean == true) {
if (extra["isSonatypeRelease"] as? Boolean == true) {
logger.info("Applying configuration for sonatype release")
from("libraries/prepareSonatypeStaging.gradle")
}
@@ -431,29 +397,6 @@ val defaultJavaHome = jdkPath(if (Platform[203].orHigher()) "11" else defaultJvm
val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures)
allprojects {
val mirrorRepo: String? = findProperty("maven.repository.mirror")?.toString()
repositories {
kotlinBuildLocalRepo(project)
mirrorRepo?.let(::maven)
internalBootstrapRepo?.let(::maven)
bootstrapKotlinRepo?.let(::maven)
maven(protobufRepo)
maven(intellijRepo)
mavenCentral()
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
maven("https://dl.google.com/dl/android/maven2")
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
jcenter()
}
if (path.startsWith(":kotlin-ide.")) {
return@allprojects
}
configurations.maybeCreate("embedded").apply {
isCanBeConsumed = false
@@ -482,6 +425,25 @@ allprojects {
// therefore it is disabled by default
// buildDir = File(commonBuildDir, project.name)
val mirrorRepo: String? = findProperty("maven.repository.mirror")?.toString()
repositories {
kotlinBuildLocalRepo(project)
mirrorRepo?.let(::maven)
internalBootstrapRepo?.let(::maven)
bootstrapKotlinRepo?.let(::maven)
maven(protobufRepo)
maven(intellijRepo)
mavenCentral()
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
maven("https://dl.google.com/dl/android/maven2")
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
jcenter()
}
configureJvmProject(javaHome!!, jvmTarget!!)
@@ -557,16 +519,12 @@ allprojects {
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KTI-112") { true }
}
if (isConfigurationCacheDisabled) {
// Custom input normolization isn't supported by configuration cache at the moment
// See https://github.com/gradle/gradle/issues/13706
normalization {
runtimeClasspath {
ignore("META-INF/MANIFEST.MF")
ignore("META-INF/compiler.version")
ignore("META-INF/plugin.xml")
ignore("kotlin/KotlinVersionCurrentValue.class")
}
normalization {
runtimeClasspath {
ignore("META-INF/MANIFEST.MF")
ignore("META-INF/compiler.version")
ignore("META-INF/plugin.xml")
ignore("kotlin/KotlinVersionCurrentValue.class")
}
}
@@ -886,12 +844,11 @@ tasks {
":idea:idea-fir:test",
":idea:idea-frontend-api:test",
":idea:idea-frontend-fir:test",
":idea:idea-frontend-fir:idea-fir-low-level-api:test",
":plugins:uast-kotlin-fir:test",
":idea:idea-fir-fe10-binding:test"
":idea:idea-frontend-fir:idea-fir-low-level-api:test"
)
}
register("android-ide-tests") {
dependsOn("dist")
dependsOn(
@@ -937,6 +894,7 @@ tasks {
}
}
register("kaptIdeTest") {
dependsOn(":kotlin-annotation-processing:test")
dependsOn(":kotlin-annotation-processing-base:test")
@@ -992,13 +950,32 @@ tasks {
register("publishIdeArtifacts") {
idePluginDependency {
dependsOn((rootProject.extra["compilerArtifactsForIde"] as List<String>).map { "$it:publish" })
}
}
register("installIdeArtifacts") {
idePluginDependency {
dependsOn((rootProject.extra["compilerArtifactsForIde"] as List<String>).map { "$it:install" })
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: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",
":prepare:ide-plugin-dependencies:kotlin-gradle-statistics-for-ide:publish",
":prepare:ide-plugin-dependencies:kotlinx-serialization-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:noarg-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:compiler-components-for-jps:publish",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide:publish",
":kotlin-script-runtime:publish",
":kotlin-script-util:publish",
":kotlin-scripting-common:publish",
":kotlin-scripting-jvm:publish",
":kotlin-scripting-compiler:publish",
":kotlin-scripting-compiler-impl:publish",
":kotlin-android-extensions-runtime:publish",
":kotlin-stdlib-common:publish",
":kotlin-stdlib:publish",
":kotlin-stdlib-jdk7:publish",
":kotlin-stdlib-jdk8:publish",
":kotlin-reflect:publish",
":kotlin-main-kts:publish"
)
}
}
}
@@ -1136,7 +1113,7 @@ fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
}
tasks.withType<KotlinCompile> {
kotlinOptions.jdkHome = javaHome.takeUnless { kotlinBuildProperties.suppressJdkHomeWarning }
kotlinOptions.jdkHome = javaHome
kotlinOptions.jvmTarget = javaVersion
kotlinOptions.freeCompilerArgs += "-Xjvm-default=compatibility"
}

View File

@@ -22,7 +22,7 @@ buildscript {
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.29")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.26")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
}
@@ -144,7 +144,7 @@ java {
dependencies {
implementation(kotlin("stdlib", embeddedKotlinVersion))
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.29")
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.26")
implementation("com.gradle.publish:plugin-publish-plugin:0.14.0")
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")

View File

@@ -18,7 +18,6 @@ plugins {
val intellijUltimateEnabled: Boolean by rootProject.extra
val intellijReleaseType: String by rootProject.extra
val intellijVersion = rootProject.extra["versions.intellijSdk"] as String
val intellijVersionForIde = rootProject.intellijSdkVersionForIde()
val asmVersion = rootProject.findProperty("versions.jar.asm-all") as String?
val androidStudioRelease = rootProject.findProperty("versions.androidStudioRelease") as String?
val androidStudioBuild = rootProject.findProperty("versions.androidStudioBuild") as String?
@@ -26,18 +25,15 @@ val intellijSeparateSdks: Boolean by rootProject.extra
val installIntellijCommunity = !intellijUltimateEnabled || intellijSeparateSdks
val installIntellijUltimate = intellijUltimateEnabled && androidStudioRelease == null
fun checkIntellijVersion(intellijVersion: String) {
val intellijVersionDelimiterIndex = intellijVersion.indexOfAny(charArrayOf('.', '-'))
if (intellijVersionDelimiterIndex == -1) {
error("Invalid IDEA version $intellijVersion")
}
val intellijVersionDelimiterIndex = intellijVersion.indexOfAny(charArrayOf('.', '-'))
if (intellijVersionDelimiterIndex == -1) {
error("Invalid IDEA version $intellijVersion")
}
checkIntellijVersion(intellijVersion)
intellijVersionForIde?.let { checkIntellijVersion(it) }
val platformBaseVersion = intellijVersion.substring(0, intellijVersionDelimiterIndex)
logger.info("intellijUltimateEnabled: $intellijUltimateEnabled")
logger.info("intellijVersion: $intellijVersion")
logger.info("intellijVersionForIde: $intellijVersionForIde")
logger.info("androidStudioRelease: $androidStudioRelease")
logger.info("androidStudioBuild: $androidStudioBuild")
logger.info("intellijSeparateSdks: $intellijSeparateSdks")
@@ -77,16 +73,11 @@ repositories {
}
val intellij by configurations.creating
val intellijForIde by configurations.creating
val intellijUltimate by configurations.creating
val intellijUltimateForIde by configurations.creating
val androidStudio by configurations.creating
val sources by configurations.creating
val sourcesForIde by configurations.creating
val jpsStandalone by configurations.creating
val jpsStandaloneForIde by configurations.creating
val intellijCore by configurations.creating
val intellijCoreForIde by configurations.creating
val nodeJSPlugin by configurations.creating
/**
@@ -102,6 +93,7 @@ val dependenciesDir = (findProperty("kotlin.build.dependencies.dir") as String?)
val customDepsRepoDir = dependenciesDir.resolve("repo")
val customDepsOrg: String by rootProject.extra
val customDepsRevision = intellijVersion
val repoDir = File(customDepsRepoDir, customDepsOrg)
dependencies {
@@ -115,11 +107,9 @@ dependencies {
} else {
if (installIntellijCommunity) {
intellij("com.jetbrains.intellij.idea:ideaIC:$intellijVersion")
intellijVersionForIde?.let { intellijForIde("com.jetbrains.intellij.idea:ideaIC:$it") }
}
if (installIntellijUltimate) {
intellijUltimate("com.jetbrains.intellij.idea:ideaIU:$intellijVersion")
intellijVersionForIde.let { intellijUltimateForIde("com.jetbrains.intellij.idea:ideaIU:$it") }
}
}
@@ -128,111 +118,102 @@ dependencies {
}
sources("com.jetbrains.intellij.idea:ideaIC:$intellijVersion:sources@jar")
intellijVersionForIde?.let { sourcesForIde("com.jetbrains.intellij.idea:ideaIC:$it:sources@jar") }
jpsStandalone("com.jetbrains.intellij.idea:jps-standalone:$intellijVersion")
intellijVersionForIde?.let { jpsStandaloneForIde("com.jetbrains.intellij.idea:jps-standalone:$it") }
intellijCore("com.jetbrains.intellij.idea:intellij-core:$intellijVersion")
intellijVersionForIde?.let { intellijCoreForIde("com.jetbrains.intellij.idea:intellij-core:$it") }
if (intellijUltimateEnabled) {
nodeJSPlugin("com.jetbrains.plugins:NodeJS:${rootProject.extra["versions.idea.NodeJS"]}@zip")
}
}
fun prepareDeps(intellij: Configuration, intellijCore: Configuration, sources: Configuration, intellijUltimate: Configuration, jpsStandalone: Configuration, intellijVersion: String) {
val makeIntellijCore = buildIvyRepositoryTask(intellijCore, customDepsOrg, customDepsRepoDir)
val makeIntellijCore = buildIvyRepositoryTask(intellijCore, customDepsOrg, customDepsRepoDir)
val makeIntellijAnnotations = tasks.register("makeIntellijAnnotations${intellij.name.capitalize()}", Copy::class) {
dependsOn(makeIntellijCore)
val makeIntellijAnnotations by tasks.registering(Copy::class) {
dependsOn(makeIntellijCore)
val intellijCoreRepo = CleanableStore[repoDir.resolve("intellij-core").absolutePath][intellijVersion].use()
from(intellijCoreRepo.resolve("artifacts/annotations.jar"))
val intellijCoreRepo = CleanableStore[repoDir.resolve("intellij-core").absolutePath][intellijVersion].use()
from(intellijCoreRepo.resolve("artifacts/annotations.jar"))
val annotationsStore = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath]
val targetDir = annotationsStore[intellijVersion].use()
into(targetDir)
val annotationsStore = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath]
val targetDir = annotationsStore[intellijVersion].use()
into(targetDir)
val ivyFile = File(targetDir, "$intellijRuntimeAnnotations.ivy.xml")
outputs.files(ivyFile)
val ivyFile = File(targetDir, "$intellijRuntimeAnnotations.ivy.xml")
outputs.files(ivyFile)
doFirst {
annotationsStore.cleanStore()
}
doLast {
writeIvyXml(
customDepsOrg,
intellijRuntimeAnnotations,
intellijVersion,
intellijRuntimeAnnotations,
targetDir,
targetDir,
targetDir,
allowAnnotations = true
)
}
doFirst {
annotationsStore.cleanStore()
}
val mergeSources = tasks.create("mergeSources${intellij.name.capitalize()}", Jar::class.java) {
dependsOn(sources)
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
isZip64 = true
if (!kotlinBuildProperties.isTeamcityBuild) {
from(provider { sources.map(::zipTree) })
}
destinationDirectory.set(File(repoDir, sources.name))
archiveBaseName.set("intellij")
archiveClassifier.set("sources")
archiveVersion.set(intellijVersion)
}
val sourcesFile = mergeSources.outputs.files.singleFile
val makeIde = if (androidStudioBuild != null) {
buildIvyRepositoryTask(
androidStudio,
doLast {
writeIvyXml(
customDepsOrg,
customDepsRepoDir,
if (androidStudioOs == "mac")
::skipContentsDirectory
else
::skipToplevelDirectory
intellijRuntimeAnnotations,
intellijVersion,
intellijRuntimeAnnotations,
targetDir,
targetDir,
targetDir,
allowAnnotations = true
)
} else {
val task = if (installIntellijUltimate) {
buildIvyRepositoryTask(intellijUltimate, customDepsOrg, customDepsRepoDir, null, sourcesFile)
} else {
buildIvyRepositoryTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
}
task.configure {
dependsOn(mergeSources)
}
task
}
val buildJpsStandalone = buildIvyRepositoryTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
tasks.named("build") {
dependsOn(
makeIntellijCore,
makeIde,
buildJpsStandalone,
makeIntellijAnnotations
)
}
if (installIntellijUltimate) {
val buildNodeJsPlugin =
buildIvyRepositoryTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
tasks.named("build") { dependsOn(buildNodeJsPlugin) }
}
}
prepareDeps(intellij, intellijCore, sources, intellijUltimate, jpsStandalone, intellijVersion)
if (intellijVersionForIde != null) {
prepareDeps(intellijForIde, intellijCoreForIde, sourcesForIde, intellijUltimateForIde, jpsStandaloneForIde, intellijVersionForIde)
val mergeSources by tasks.creating(Jar::class.java) {
dependsOn(sources)
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
isZip64 = true
if (!kotlinBuildProperties.isTeamcityBuild) {
from(provider { sources.map(::zipTree) })
}
destinationDirectory.set(File(repoDir, sources.name))
archiveBaseName.set("intellij")
archiveClassifier.set("sources")
archiveVersion.set(intellijVersion)
}
val sourcesFile = mergeSources.outputs.files.singleFile
val makeIde = if (androidStudioBuild != null) {
buildIvyRepositoryTask(
androidStudio,
customDepsOrg,
customDepsRepoDir,
if (androidStudioOs == "mac")
::skipContentsDirectory
else
::skipToplevelDirectory
)
} else {
val task = if (installIntellijUltimate) {
buildIvyRepositoryTask(intellijUltimate, customDepsOrg, customDepsRepoDir, null, sourcesFile)
} else {
buildIvyRepositoryTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
}
task.configure {
dependsOn(mergeSources)
}
task
}
val buildJpsStandalone = buildIvyRepositoryTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
tasks.named("build") {
dependsOn(
makeIntellijCore,
makeIde,
buildJpsStandalone,
makeIntellijAnnotations
)
}
if (installIntellijUltimate) {
val buildNodeJsPlugin =
buildIvyRepositoryTask(nodeJSPlugin, customDepsOrg, customDepsRepoDir, ::skipToplevelDirectory, sourcesFile)
tasks.named("build") { dependsOn(buildNodeJsPlugin) }
}
tasks.named<Delete>("clean") {
@@ -419,11 +400,6 @@ fun skipToplevelDirectory(path: String) = path.substringAfter('/')
fun skipContentsDirectory(path: String) = path.substringAfter("Contents/")
fun Project.intellijSdkVersionForIde(): String? {
val majorVersion = kotlinBuildProperties.getOrNull("attachedIntellijVersion") as? String ?: return null
return rootProject.findProperty("versions.intellijSdk.forIde.$majorVersion") as? String
}
class XMLWriter(private val outputStreamWriter: OutputStreamWriter) : Closeable {
private val xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStreamWriter)

View File

@@ -18,10 +18,9 @@ buildscript {
} else {
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies" }
}
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.29")
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.26")
}
}

View File

@@ -20,5 +20,3 @@ val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.bui
val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignoreTestFailures", isTeamcityBuild)
val KotlinBuildProperties.disableWerror: Boolean get() = getBoolean("kotlin.build.disable.werror", false)
val KotlinBuildProperties.suppressJdkHomeWarning: Boolean get() = getBoolean("kotlin.suppress.jdkHome.warning", false)

View File

@@ -81,9 +81,3 @@ fun Task.singleOutputFile(): File = when (this) {
is ProGuardTask -> project.file(outJarFiles.single()!!)
else -> outputs.files.singleFile
}
val Project.isConfigurationCacheDisabled
get() = (gradle.startParameter as? org.gradle.api.internal.StartParameterInternal)?.isConfigurationCache != true
val Project.isIdeaActive
get() = providers.systemProperty("idea.active").forUseAtConfigurationTime().isPresent

View File

@@ -229,6 +229,23 @@ fun Project.publish(moduleMetadata: Boolean = false, configure: MavenPublication
publication.configure()
}
fun Project.publishWithLegacyMavenPlugin(body: Upload.() -> Unit = {}): Upload {
apply<plugins.PublishedKotlinModule>()
if (artifactsRemovedDiagnosticFlag) {
error("`publish()` should be called before removing artifacts typically done in `noDefaultJar()` or `runtimeJar()` call")
}
afterEvaluate {
if (configurations.findByName("classes-dirs") != null)
throw GradleException("classesDirsArtifact() is incompatible with publish(), see sources comments for details")
}
return (tasks.getByName("uploadArchives") as Upload).apply {
body()
}
}
fun Project.idePluginDependency(block: () -> Unit) {
val shouldActivate = rootProject.findProperty("publish.ide.plugin.dependencies")?.toString()?.toBoolean() == true
if (shouldActivate) {
@@ -236,31 +253,6 @@ fun Project.idePluginDependency(block: () -> Unit) {
}
}
fun Project.publishJarsForIde(projects: List<String>, libraryDependencies: List<String> = emptyList()) {
idePluginDependency {
publishProjectJars(projects, libraryDependencies)
}
dependencies {
projects.forEach {
jpsLikeJarDependency(project(it), JpsDepScope.COMPILE, { isTransitive = false }, exported = true)
}
libraryDependencies.forEach {
jpsLikeJarDependency(it, JpsDepScope.COMPILE, exported = true)
}
}
}
fun Project.publishTestJarsForIde(projectNames: List<String>) {
idePluginDependency {
publishTestJar(projectNames)
}
dependencies {
for (projectName in projectNames) {
jpsLikeJarDependency(projectTests(projectName), JpsDepScope.COMPILE, exported = true)
}
}
}
fun Project.publishProjectJars(projects: List<String>, libraryDependencies: List<String> = emptyList()) {
apply<JavaPlugin>()
@@ -299,15 +291,13 @@ fun Project.publishProjectJars(projects: List<String>, libraryDependencies: List
javadocJar()
}
fun Project.publishTestJar(projects: List<String>) {
fun Project.publishTestJar(projectName: String) {
apply<JavaPlugin>()
val fatJarContents by configurations.creating
dependencies {
for (projectName in projects) {
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
}
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
}
publish()
@@ -324,7 +314,7 @@ fun Project.publishTestJar(projects: List<String>) {
sourcesJar {
from {
projects.map { project(it).testSourceSet.allSource }
project(projectName).testSourceSet.allSource
}
}

View File

@@ -11,13 +11,11 @@ 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.ModuleDependency
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.closureOf
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.project
import java.io.File
@@ -117,87 +115,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")
enum class JpsDepScope {
COMPILE, TEST, RUNTIME, PROVIDED
}
fun DependencyHandler.add(configurationName: String, dependencyNotation: Any, configure: (ModuleDependency.() -> Unit)?) {
// Avoid `dependencyNotation` to `ModuleDependency` class cast exception if possible
if (configure != null) {
add(configurationName, dependencyNotation, closureOf(configure))
} else {
add(configurationName, dependencyNotation)
}
}
fun DependencyHandler.jpsLikeJarDependency(
dependencyNotation: Any,
scope: JpsDepScope,
dependencyConfiguration: (ModuleDependency.() -> Unit)? = null,
exported: Boolean = false
) {
when (scope) {
JpsDepScope.COMPILE -> {
if (exported) {
add("api", dependencyNotation, dependencyConfiguration)
add("testCompile", dependencyNotation, dependencyConfiguration)
} else {
add("implementation", dependencyNotation, dependencyConfiguration)
}
}
JpsDepScope.TEST -> {
if (exported) {
add("testCompile", dependencyNotation, dependencyConfiguration)
} else {
add("testImplementation", dependencyNotation, dependencyConfiguration)
}
}
JpsDepScope.RUNTIME -> {
add("testRuntimeOnly", dependencyNotation, dependencyConfiguration)
}
JpsDepScope.PROVIDED -> {
if (exported) {
add("compileOnlyApi", dependencyNotation, dependencyConfiguration)
add("testCompile", dependencyNotation, dependencyConfiguration)
} else {
add("compileOnly", dependencyNotation, dependencyConfiguration)
add("testImplementation", dependencyNotation, dependencyConfiguration)
}
}
}
}
fun DependencyHandler.jpsLikeModuleDependency(moduleName: String, scope: JpsDepScope, exported: Boolean = false) {
jpsLikeJarDependency(project(moduleName), scope, exported = exported)
when (scope) {
JpsDepScope.COMPILE -> {
if (exported) {
add("testCompile", projectTests(moduleName))
} else {
add("testImplementation", projectTests(moduleName))
}
}
JpsDepScope.TEST -> {
if (exported) {
add("testCompile", projectTests(moduleName))
} else {
add("testImplementation", projectTests(moduleName))
}
}
JpsDepScope.RUNTIME -> {
add("runtimeOnly", projectTests(moduleName))
}
JpsDepScope.PROVIDED -> {
if (exported) {
add("testCompile", projectTests(moduleName))
} else {
add("testImplementation", projectTests(moduleName))
}
}
}
}
fun Project.testApiJUnit5(
vintageEngine: Boolean = false,
runner: Boolean = false,

View File

@@ -1,51 +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.
*/
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm")
}
publish()
standardPublicJars()
extensions.extraProperties["kotlin.stdlib.default.dependency"] = "false"
dependencies {
compileOnly(kotlinStdlib())
compileOnly(gradleApi())
}
// These dependencies will be provided by Gradle and we should prevent version conflict
fun Configuration.excludeGradleCommonDependencies() {
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-reflect")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-script-runtime")
}
configurations {
"implementation" {
excludeGradleCommonDependencies()
}
"api" {
excludeGradleCommonDependencies()
}
}
tasks.withType<KotlinCompile> {
kotlinOptions.languageVersion = "1.3"
kotlinOptions.apiVersion = "1.3"
kotlinOptions.freeCompilerArgs += listOf(
"-Xskip-prerelease-check",
"-Xskip-runtime-version-check",
"-Xsuppress-version-warnings"
)
}
tasks.named<Jar>("jar") {
callGroovy("manifestAttributes", manifest, project)
}

View File

@@ -42,21 +42,9 @@ private fun Project.ideModuleName() = when (IdeVersionConfigurator.currentIde.ki
}
}
private fun Project.ideModuleVersion(forIde: Boolean) = when (IdeVersionConfigurator.currentIde.kind) {
private fun Project.ideModuleVersion() = when (IdeVersionConfigurator.currentIde.kind) {
Ide.Kind.AndroidStudio -> rootProject.findProperty("versions.androidStudioBuild")
Ide.Kind.IntelliJ -> {
if (forIde) {
intellijSdkVersionForIde()
?: error("Please specify 'attachedIntellijVersion' in your local.properties")
} else {
rootProject.findProperty("versions.intellijSdk")
}
}
}
fun Project.intellijSdkVersionForIde(): String? {
val majorVersion = kotlinBuildProperties.getOrNull("attachedIntellijVersion") as? String ?: return null
return rootProject.findProperty("versions.intellijSdk.forIde.$majorVersion") as? String
Ide.Kind.IntelliJ -> rootProject.findProperty("versions.intellijSdk")
}
fun RepositoryHandler.kotlinBuildLocalRepo(project: Project): IvyArtifactRepository = ivy {
@@ -70,7 +58,6 @@ fun RepositoryHandler.kotlinBuildLocalRepo(project: Project): IvyArtifactReposit
artifact("[organisation]/[module]/[revision]/artifacts/lib/[artifact](-[classifier]).[ext]")
artifact("[organisation]/[module]/[revision]/artifacts/[artifact](-[classifier]).[ext]")
artifact("[organisation]/intellij-core/[revision]/artifacts/[artifact](-[classifier]).[ext]")
artifact("[organisation]/${project.ideModuleName()}/[revision]/artifacts/plugins/[module]/lib/[artifact](-[classifier]).[ext]") // bundled plugins
artifact("[organisation]/sources/[artifact]-[revision](-[classifier]).[ext]")
artifact("[organisation]/[module]/[revision]/[artifact](-[classifier]).[ext]")
@@ -81,9 +68,7 @@ fun RepositoryHandler.kotlinBuildLocalRepo(project: Project): IvyArtifactReposit
}
}
@JvmOverloads
fun Project.intellijDep(module: String? = null, forIde: Boolean = false) =
"kotlin.build:${module ?: ideModuleName()}:${ideModuleVersion(forIde)}"
fun Project.intellijDep(module: String? = null) = "kotlin.build:${module ?: ideModuleName()}:${ideModuleVersion()}"
fun Project.intellijCoreDep() = "kotlin.build:intellij-core:${rootProject.extra["versions.intellijSdk"]}"
@@ -108,7 +93,7 @@ fun Project.kotlinxCollectionsImmutable() = "org.jetbrains.kotlinx:kotlinx-colle
*/
fun Project.intellijRuntimeAnnotations() = "kotlin.build:intellij-runtime-annotations:${rootProject.extra["versions.intellijSdk"]}"
fun Project.intellijPluginDep(plugin: String, forIde: Boolean = false) = intellijDep(plugin, forIde)
fun Project.intellijPluginDep(plugin: String) = intellijDep(plugin)
fun Project.intellijUltimateDep() = intellijDep("ideaIU")
@@ -140,7 +125,7 @@ object IntellijRootUtils {
fun getIntellijRootDir(project: Project): File = with(project.rootProject) {
return File(
getRepositoryRootDir(this),
"${ideModuleName()}/${ideModuleVersion(forIde = false)}/artifacts"
"${ideModuleName()}/${ideModuleVersion()}/artifacts"
)
}
}

View File

@@ -164,17 +164,7 @@ fun Project.configureDefaultPublishing() {
private fun Project.configureSigning() {
configure<SigningExtension> {
sign(extensions.getByType<PublishingExtension>().publications) // all publications
val signKeyId = project.findProperty("signKeyId") as? String
if (!signKeyId.isNullOrBlank()) {
val signKeyPrivate = project.findProperty("signKeyPrivate") as? String
?: error("Parameter `signKeyPrivate` not found")
val signKeyPassphrase = project.findProperty("signKeyPassphrase") as? String
?: error("Parameter `signKeyPassphrase` not found")
useInMemoryPgpKeys(signKeyId, signKeyPrivate, signKeyPassphrase)
} else {
useGpgCmd()
}
useGpgCmd()
}
}

View File

@@ -0,0 +1,173 @@
@file:Suppress("DEPRECATION")
package plugins
import org.codehaus.groovy.runtime.InvokerHelper
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer
import org.gradle.api.artifacts.maven.MavenDeployment
import org.gradle.api.artifacts.maven.MavenResolver
import org.gradle.api.plugins.MavenPluginConvention
import org.gradle.api.plugins.MavenRepositoryHandlerConvention
import org.gradle.api.publication.maven.internal.deployer.MavenRemoteRepository
import org.gradle.api.tasks.Upload
import org.gradle.kotlin.dsl.*
import org.gradle.plugins.signing.Sign
import org.gradle.plugins.signing.SigningExtension
import kotlin.properties.Delegates
/**
* Configures a Kotlin module for publication.
*/
open class PublishedKotlinModule : Plugin<Project> {
private fun String.toBooleanOrNull() = listOf(true, false).firstOrNull { it.toString().equals(this, ignoreCase = true) }
override fun apply(project: Project) {
project.run {
plugins.apply("maven")
configurations.maybeCreate("publishedRuntime").apply {
the<MavenPluginConvention>()
.conf2ScopeMappings
.addMapping(0, this, Conf2ScopeMappingContainer.RUNTIME)
}
configurations.maybeCreate("publishedCompile").apply {
the<MavenPluginConvention>()
.conf2ScopeMappings
.addMapping(0, this, Conf2ScopeMappingContainer.COMPILE)
}
if (!project.hasProperty("prebuiltJar")) {
plugins.apply("signing")
val signingRequired = project.findProperty("signingRequired")?.toString()?.toBooleanOrNull()
?: project.property("isSonatypeRelease") as Boolean
configure<SigningExtension> {
isRequired = signingRequired
sign(configurations["archives"])
useGpgCmd()
}
tasks.named<Sign>("signArchives").configure {
enabled = signingRequired
}
}
fun MavenResolver.configurePom() {
pom.project {
withGroovyBuilder {
"licenses" {
"license" {
"name"("The Apache Software License, Version 2.0")
"url"("http://www.apache.org/licenses/LICENSE-2.0.txt")
"distribution"("repo")
}
}
"name"("${project.group}:${project.name}")
"packaging"("jar")
// optionally artifactId can be defined here
"description"(project.description)
"url"("https://kotlinlang.org/")
"licenses" {
"license" {
"name"("The Apache License, Version 2.0")
"url"("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
"scm" {
"url"("https://github.com/JetBrains/kotlin")
"connection"("scm:git:https://github.com/JetBrains/kotlin.git")
"developerConnection"("scm:git:https://github.com/JetBrains/kotlin.git")
}
"developers" {
"developer" {
"name"("Kotlin Team")
setProperty("organization", "JetBrains")
"organizationUrl"("https://www.jetbrains.com")
}
}
}
}
pom.whenConfigured {
dependencies.removeIf {
InvokerHelper.getMetaClass(it).getProperty(it, "scope") == "test"
}
dependencies
.find {
InvokerHelper.getMetaClass(it).getProperty(it, "groupId") == "org.jetbrains.kotlin"
&& InvokerHelper.getMetaClass(it).getProperty(it, "artifactId") == "kotlin-stdlib"
}
?.also {
InvokerHelper.getMetaClass(it).setProperty(it, "exclusions", emptyList<Any>())
logger.warn("WARNING! Removed exclusions from kotlin-stdlib dependency of ${this.artifactId} artifact's maven metadata, check kotlin-stdlib dependency of ${project.path} project")
}
}
}
tasks.named<Upload>("uploadArchives").configure {
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
dependsOn(preparePublication)
val username: String? by preparePublication.extra
val password: String? by preparePublication.extra
val repoUrl: String by preparePublication.extra
var repository by Delegates.notNull<MavenRemoteRepository>()
repositories {
withConvention(MavenRepositoryHandlerConvention::class) {
mavenDeployer {
withGroovyBuilder {
"beforeDeployment" {
val signing = project.the<SigningExtension>()
if (signing.isRequired)
signing.signPom(delegate as MavenDeployment)
}
"repository"("url" to repoUrl)!!.also { repository = it as MavenRemoteRepository }.withGroovyBuilder {
if (username != null && password != null) {
"authentication"("userName" to username, "password" to password)
}
}
}
configurePom()
}
}
}
doFirst {
repository.url = repoUrl
}
}
val install = if (tasks.names.contains("install")) tasks.getByName("install") as Upload
else tasks.create("install", Upload::class.java)
install.apply {
configuration = project.configurations.getByName(Dependency.ARCHIVES_CONFIGURATION)
description = "Installs the 'archives' artifacts into the local Maven repository."
repositories {
withConvention(MavenRepositoryHandlerConvention::class) {
mavenInstaller {
configurePom()
}
}
}
}
tasks.register("publish") {
dependsOn(tasks.named("uploadArchives"))
}
}
}
}

View File

@@ -354,8 +354,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
extractor.provideConfigurationKeys()
extractor.configure(keyConfiguration, module.directives)
}
val kind = JvmEnvironmentConfigurator.extractConfigurationKind(module.directives)
val jdkKind = JvmEnvironmentConfigurator.extractJdkKind(module.directives)
val kind = configuratorForFlags.extractConfigurationKind(module.directives)
val jdkKind = configuratorForFlags.extractJdkKind(module.directives)
keyConfiguration.languageVersionSettings = module.languageVersionSettings

View File

@@ -18,7 +18,6 @@ interface TypeMappingContext<Writer : JvmDescriptorTypeWriter<Type>> {
val typeContext: TypeSystemCommonBackendContextForTypeMapping
fun getClassInternalName(typeConstructor: TypeConstructorMarker): String
fun getScriptInternalName(typeConstructor: TypeConstructorMarker): String
fun Writer.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode)
}
@@ -118,7 +117,9 @@ object AbstractTypeMapper {
}
typeConstructor.isScript() -> {
return Type.getObjectType(context.getScriptInternalName(typeConstructor))
val asmType = AsmTypes.JAVA_CLASS_TYPE
with(context) { sw?.writeGenericType(type, asmType, mode) }
return asmType
}
typeConstructor.isTypeParameter() -> {

View File

@@ -34,10 +34,10 @@ 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;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
import org.jetbrains.kotlin.types.FlexibleType;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType;
@@ -376,7 +376,7 @@ public abstract class AnnotationCodegen {
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
// (Otherwise we would've resolved the entry to the actual annotation class.)
if (OptionalAnnotationUtil.isOptionalAnnotationClass(classDescriptor)) {
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(classDescriptor)) {
return null;
}

View File

@@ -12,7 +12,6 @@ import kotlin.Unit;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.context.ClosureContext;
@@ -32,6 +31,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.metadata.ProtoBuf;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -376,12 +376,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
value = StackValue.local(slot, type, bridgeParameterKotlinTypes.get(i));
slot += type.getSize();
}
if (InlineClassesCodegenUtilKt.isInlineClassWithUnderlyingTypeAnyOrAnyN(parameterType) && functionReferenceCall == null) {
ClassDescriptor descriptor = TypeUtils.getClassDescriptor(parameterType);
InlineClassRepresentation<SimpleType> representation =
descriptor != null ? descriptor.getInlineClassRepresentation() : null;
assert representation != null : "Not an inline class type: " + parameterType;
parameterType = representation.getUnderlyingType();
if (InlineClassesCodegenUtilKt.isInlineClassWithUnderlyingTypeAnyOrAnyN(parameterType) &&
functionReferenceCall == null
) {
parameterType = InlineClassesUtilsKt.unsubstitutedUnderlyingParameter(parameterType).getType();
}
value.put(typeMapper.mapType(calleeParameter), parameterType, iv);
}

View File

@@ -72,7 +72,7 @@ class ErasedInlineClassBodyCodegen(
}
private fun generateUnboxMethod() {
val boxMethodDescriptor = InlineClassDescriptorResolver.createBoxFunctionDescriptor(descriptor)
val boxMethodDescriptor = InlineClassDescriptorResolver.createBoxFunctionDescriptor(descriptor) ?: return
functionCodegen.generateMethod(
Synthetic(null, boxMethodDescriptor), boxMethodDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) {
@@ -103,7 +103,7 @@ class ErasedInlineClassBodyCodegen(
}
private fun generateSpecializedEqualsStub() {
val specializedEqualsDescriptor = InlineClassDescriptorResolver.createSpecializedEqualsDescriptor(descriptor)
val specializedEqualsDescriptor = InlineClassDescriptorResolver.createSpecializedEqualsDescriptor(descriptor) ?: return
functionCodegen.generateMethod(
Synthetic(null, specializedEqualsDescriptor), specializedEqualsDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) {

View File

@@ -20,7 +20,6 @@ import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
@@ -93,6 +92,7 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
import org.jetbrains.kotlin.types.model.TypeParameterMarker;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -265,23 +265,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
);
}
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen<?> member, @NotNull ClassDescriptor descriptor) {
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen member, @NotNull ClassDescriptor descriptor) {
for (KotlinType type : descriptor.getTypeConstructor().getSupertypes()) {
processTypeArguments(member, type);
}
}
private static void processTypeArguments(@NotNull MemberCodegen<?> member, KotlinType type) {
for (TypeProjection supertypeArgument : type.getArguments()) {
if (supertypeArgument.isStarProjection()) continue;
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
if (parameterDescriptor != null) {
if (parameterDescriptor.isReified()) {
for (TypeProjection supertypeArgument : type.getArguments()) {
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString());
}
} else {
processTypeArguments(member, supertypeArgument.getType());
}
}
}
@@ -2024,12 +2014,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// Do not unbox parameters of suspend lambda, they are unboxed in `invoke` method
!CoroutineCodegenUtilKt.isInvokeSuspendOfLambda(context.getFunctionDescriptor())
) {
ClassDescriptor inlineClass = (ClassDescriptor) inlineClassType.getConstructor().getDeclarationDescriptor();
InlineClassRepresentation<SimpleType> representation =
inlineClass != null ? inlineClass.getInlineClassRepresentation() : null;
assert representation != null : "Not an inline class: " + inlineClassType;
KotlinType underlyingType = representation.getUnderlyingType();
return StackValue.underlyingValueOfInlineClass(typeMapper.mapType(underlyingType), underlyingType, localOrCaptured);
KotlinType underlyingType = InlineClassesUtilsKt.underlyingRepresentation(
(ClassDescriptor) inlineClassType.getConstructor().getDeclarationDescriptor()).getType();
return StackValue.underlyingValueOfInlineClass(
typeMapper.mapType(underlyingType), underlyingType, localOrCaptured);
}
}
return localOrCaptured;

View File

@@ -53,7 +53,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -370,22 +369,23 @@ public class FunctionCodegen {
public static void generateMethodInsideInlineClassWrapper(
@NotNull JvmDeclarationOrigin origin,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull ClassDescriptor inlineClass,
@NotNull ClassDescriptor containingDeclaration,
@NotNull MethodVisitor mv,
@NotNull KotlinTypeMapper typeMapper
) {
mv.visitCode();
Type fieldOwnerType = typeMapper.mapClass(inlineClass);
Type fieldOwnerType = typeMapper.mapClass(containingDeclaration);
Method erasedMethodImpl = typeMapper.mapAsmMethod(functionDescriptor.getOriginal(), OwnerKind.ERASED_INLINE_CLASS);
InlineClassRepresentation<SimpleType> representation = inlineClass.getInlineClassRepresentation();
assert representation != null : "Not an inline class: " + inlineClass;
ValueParameterDescriptor valueRepresentation = InlineClassesUtilsKt.underlyingRepresentation(containingDeclaration);
if (valueRepresentation == null) return;
Type fieldType = typeMapper.mapType(valueRepresentation);
generateDelegateToStaticErasedVersion(
mv, erasedMethodImpl, fieldOwnerType,
representation.getUnderlyingPropertyName().asString(),
typeMapper.mapType(representation.getUnderlyingType())
mv, erasedMethodImpl,
fieldOwnerType, valueRepresentation.getName().asString(), fieldType
);
endVisit(mv, null, origin.getElement());

View File

@@ -55,7 +55,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
@@ -275,25 +274,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateUnboxMethodForInlineClass() {
if (!(myClass instanceof KtClass)) return;
InlineClassRepresentation<SimpleType> inlineClassRepresentation = descriptor.getInlineClassRepresentation();
if (inlineClassRepresentation == null) return;
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
Type ownerType = typeMapper.mapClass(descriptor);
Type valueType = typeMapper.mapType(inlineClassRepresentation.getUnderlyingType());
ValueParameterDescriptor inlinedValue = InlineClassesUtilsKt.underlyingRepresentation(this.descriptor);
if (inlinedValue == null) return;
Type valueType = typeMapper.mapType(inlinedValue.getType());
SimpleFunctionDescriptor functionDescriptor = InlineClassDescriptorResolver.createUnboxFunctionDescriptor(this.descriptor);
assert functionDescriptor != null : "FunctionDescriptor for unbox method should be not null during codegen";
functionCodegen.generateMethod(
JvmDeclarationOriginKt.UnboxMethodOfInlineClass(functionDescriptor), functionDescriptor,
new FunctionGenerationStrategy.CodegenBased(state) {
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
public void doGenerateBody(
@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature
) {
InstructionAdapter iv = codegen.v;
iv.load(0, OBJECT_TYPE);
iv.getfield(
ownerType.getInternalName(),
inlineClassRepresentation.getUnderlyingPropertyName().asString(),
valueType.getDescriptor()
);
iv.getfield(ownerType.getInternalName(), inlinedValue.getName().asString(), valueType.getDescriptor());
iv.areturn(valueType);
}
}

View File

@@ -35,9 +35,9 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.lazy.descriptors.PackageDescriptorUtilKt;
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
import org.jetbrains.org.objectweb.asm.Type;
@@ -91,8 +91,8 @@ public class PackageCodegenImpl implements PackageCodegen {
if (declaration instanceof KtClassOrObject) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, declaration);
if (PsiUtilsKt.hasExpectModifier(declaration)) {
if (descriptor != null && OptionalAnnotationUtil.shouldGenerateExpectClass(descriptor)) {
assert OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor) :
if (descriptor != null && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor)) {
assert ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor) :
"Expect class should be generated only if it's an optional annotation: " + descriptor;
state.getFactory().getPackagePartRegistry().getOptionalAnnotations().add(descriptor);
}

View File

@@ -7,7 +7,9 @@ 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.codegen.*
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE
@@ -599,6 +601,21 @@ class CoroutineCodegenForLambda private constructor(
}
}
fun isCapturedSuspendLambda(closure: CalculatedClosure, name: String, bindingContext: BindingContext): Boolean {
for ((param, value) in closure.captureVariables) {
if (param !is ValueParameterDescriptor) continue
if (value.fieldName != name) continue
return param.type.isSuspendFunctionTypeOrSubtype
}
val classDescriptor = closure.capturedOuterClassDescriptor ?: return false
return isCapturedSuspendLambda(classDescriptor, name, bindingContext)
}
fun isCapturedSuspendLambda(classDescriptor: ClassDescriptor, name: String, bindingContext: BindingContext): Boolean {
val closure = bindingContext[CLOSURE, classDescriptor] ?: return false
return isCapturedSuspendLambda(closure, name, bindingContext)
}
private class AddEndLabelMethodVisitor(
delegate: MethodVisitor,
access: Int,

View File

@@ -650,7 +650,7 @@ class CoroutineTransformerMethodVisitor(
val livenessFrames = analyzeLiveness(methodNode)
// References shall be cleaned up after unspill (during spill in next suspension point) to prevent memory leaks,
// References shall be cleaned up after uspill (during spill in next suspension point) to prevent memory leaks,
val referencesToSpillBySuspensionPointIndex = arrayListOf<List<ReferenceToSpill>>()
// while primitives shall not
val primitivesToSpillBySuspensionPointIndex = arrayListOf<List<PrimitiveToSpill>>()
@@ -759,35 +759,6 @@ class CoroutineTransformerMethodVisitor(
referencesToCleanBySuspensionPointIndex += currentSpilledReferencesCount to predSpilledReferencesCount
}
// Calculate debug metadata mapping before modifying method node to make it easier to locate
// locals alive across suspension points.
fun calculateSpilledVariableAndField(
suspension: SuspensionPoint,
slot: Int,
spillableVariable: SpillableVariable?
): SpilledVariableAndField? {
if (spillableVariable == null) return null
val name = localVariableName(methodNode, slot, suspension.suspensionCallBegin.index()) ?: return null
return SpilledVariableAndField(spillableVariable.fieldName, name)
}
val spilledToVariableMapping = arrayListOf<List<SpilledVariableAndField>>()
for (suspensionPointIndex in suspensionPoints.indices) {
val suspension = suspensionPoints[suspensionPointIndex]
val spilledToVariable = arrayListOf<SpilledVariableAndField>()
referencesToSpillBySuspensionPointIndex[suspensionPointIndex].mapNotNullTo(spilledToVariable) { (slot, spillableVariable) ->
calculateSpilledVariableAndField(suspension, slot, spillableVariable)
}
primitivesToSpillBySuspensionPointIndex[suspensionPointIndex].mapNotNullTo(spilledToVariable) { (slot, spillableVariable) ->
calculateSpilledVariableAndField(suspension, slot, spillableVariable)
}
spilledToVariableMapping += spilledToVariable
}
// Mutate method node
fun generateSpillAndUnspill(suspension: SuspensionPoint, slot: Int, spillableVariable: SpillableVariable?) {
@@ -801,22 +772,6 @@ class CoroutineTransformerMethodVisitor(
return
}
// Find and remove the local variable node, if any, in the local variable table corresponding to the slot that is spilled.
var local: LocalVariableNode? = null
val localRestart = LabelNode().linkWithLabel()
val iterator = methodNode.localVariables.listIterator()
while (iterator.hasNext()) {
val node = iterator.next()
if (node.index == slot &&
methodNode.instructions.indexOf(node.start) <= methodNode.instructions.indexOf(suspension.suspensionCallBegin) &&
methodNode.instructions.indexOf(node.end) > methodNode.instructions.indexOf(suspension.tryCatchBlockEndLabelAfterSuspensionCall)
) {
local = node
iterator.remove()
break
}
}
with(instructions) {
// store variable before suspension call
insertBefore(suspension.suspensionCallBegin, withInstructionAdapter {
@@ -840,31 +795,8 @@ class CoroutineTransformerMethodVisitor(
)
StackValue.coerce(spillableVariable.normalizedType, spillableVariable.type, this)
store(slot, spillableVariable.type)
if (local != null) {
visitLabel(localRestart.label)
}
})
}
// Split the local variable range for the local so that it is visible until the next state label, but is
// not visible until it has been unspilled from the continuation on the reentry path.
if (local != null) {
val previousEnd = local.end
local.end = suspension.stateLabel
// Add the local back, but end it at the next state label.
methodNode.localVariables.add(local)
// Add a new entry that starts after the local variable is restored from the continuation.
methodNode.localVariables.add(
LocalVariableNode(
local.name,
local.desc,
local.signature,
localRestart,
previousEnd,
local.index
)
)
}
}
fun cleanUpField(suspension: SuspensionPoint, fieldIndex: Int) {
@@ -907,6 +839,33 @@ class CoroutineTransformerMethodVisitor(
}
}
// Calculate debug metadata mapping
fun calculateSpilledVariableAndField(
suspension: SuspensionPoint,
slot: Int,
spillableVariable: SpillableVariable?
): SpilledVariableAndField? {
if (spillableVariable == null) return null
val name = localVariableName(methodNode, slot, suspension.suspensionCallEnd.next.index()) ?: return null
return SpilledVariableAndField(spillableVariable.fieldName, name)
}
val spilledToVariableMapping = arrayListOf<List<SpilledVariableAndField>>()
for (suspensionPointIndex in suspensionPoints.indices) {
val suspension = suspensionPoints[suspensionPointIndex]
val spilledToVariable = arrayListOf<SpilledVariableAndField>()
referencesToSpillBySuspensionPointIndex[suspensionPointIndex].mapNotNullTo(spilledToVariable) { (slot, spillableVariable) ->
calculateSpilledVariableAndField(suspension, slot, spillableVariable)
}
primitivesToSpillBySuspensionPointIndex[suspensionPointIndex].mapNotNullTo(spilledToVariable) { (slot, spillableVariable) ->
calculateSpilledVariableAndField(suspension, slot, spillableVariable)
}
spilledToVariableMapping += spilledToVariable
}
return spilledToVariableMapping
}
@@ -942,6 +901,7 @@ class CoroutineTransformerMethodVisitor(
suspendMarkerVarIndex: Int,
suspendPointLineNumber: LineNumberNode?
): LabelNode {
val stateLabel = LabelNode().linkWithLabel()
val continuationLabelAfterLoadedResult = LabelNode()
val suspendElementLineNumber = lineNumber
var nextLineNumberNode = nextDefinitelyHitLineNumber(suspension)
@@ -969,7 +929,7 @@ class CoroutineTransformerMethodVisitor(
load(suspendMarkerVarIndex, AsmTypes.OBJECT_TYPE)
areturn(AsmTypes.OBJECT_TYPE)
// Mark place for continuation
visitLabel(suspension.stateLabel.label)
visitLabel(stateLabel.label)
})
// After suspension point there is always three nodes: L1, NOP, L2
@@ -1025,7 +985,7 @@ class CoroutineTransformerMethodVisitor(
}
}
return suspension.stateLabel
return stateLabel
}
// Find the next line number instruction that is defintely hit. That is, a line number
@@ -1194,7 +1154,6 @@ internal class SuspensionPoint(
) {
lateinit var tryCatchBlocksContinuationLabel: LabelNode
val stateLabel = LabelNode().linkWithLabel()
val unboxInlineClassInstructions: List<AbstractInsnNode> = findUnboxInlineClassInstructions()
private fun findUnboxInlineClassInstructions(): List<AbstractInsnNode> {
@@ -1276,13 +1235,16 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
fun isAlive(insnIndex: Int, variableIndex: Int): Boolean =
liveness[insnIndex].isAlive(variableIndex)
fun nextLabel(node: AbstractInsnNode?): LabelNode? {
var current = node
while (current != null) {
if (current is LabelNode) return current
current = current.next
}
return null
fun nextSuspensionPointEndLabel(insn: AbstractInsnNode): LabelNode {
val suspensionPoint =
InsnSequence(insn, method.instructions.last).firstOrNull { isAfterSuspendMarker(it) } ?: method.instructions.last
return suspensionPoint as? LabelNode ?: suspensionPoint.findNextOrNull { it is LabelNode } as LabelNode
}
fun nextSuspensionPointStartLabel(insn: AbstractInsnNode): LabelNode {
val suspensionPoint =
InsnSequence(insn, method.instructions.last).firstOrNull { isBeforeSuspendMarker(it) } ?: method.instructions.last
return suspensionPoint as? LabelNode ?: suspensionPoint.findPreviousOrNull { it is LabelNode } as LabelNode
}
fun min(a: LabelNode, b: LabelNode): LabelNode =
@@ -1291,6 +1253,9 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
fun max(a: LabelNode, b: LabelNode): LabelNode =
if (method.instructions.indexOf(a) < method.instructions.indexOf(b)) b else a
fun containsSuspensionPoint(a: LabelNode, b: LabelNode): Boolean =
InsnSequence(min(a, b), max(a, b)).none { isBeforeSuspendMarker(it) }
val oldLvt = arrayListOf<LocalVariableNode>()
for (record in method.localVariables) {
oldLvt += record
@@ -1311,40 +1276,35 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
// No variable in LVT -> do not add one
val lvtRecord = oldLvt.findRecord(insnIndex, variableIndex) ?: continue
if (lvtRecord.name == CONTINUATION_VARIABLE_NAME) continue
// End the local when it is no longer live. Since it is not live, we will not spill and unspill it across
// suspension points. It is tempting to keep it alive until the next suspension point to leave it visible in
// the debugger for as long as possible. However, in the case of loops, the resumption after suspension can
// have a backwards edge targeting instruction between the point of death and the next suspension point.
//
// For example, code such as the following:
//
// listOf<String>.forEach {
// yield(it)
// }
//
// Generates code of this form with a back edge after resumption that will lead to invalid locals tables
// if the local range is extended to the next suspension point.
//
// iterator = iterable.iterator()
// L1: (iterable dies here)
// load iterator.next if there
// yield suspension point
//
// L2: (resumption point)
// restore live variables (not including iterable)
// goto L1 (iterator not restored here, so we cannot not have iterator live at L1)
val endLabel = nextLabel(insn.next)?.let { min(lvtRecord.end, it) } ?: lvtRecord.end
// Extend lvt record to the next suspension point
val endLabel = min(lvtRecord.end, nextSuspensionPointEndLabel(insn))
// startLabel can be null in case of parameters
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
if (lvtRecord !in oldLvtNodeToLatestNewLvtNode) {
method.localVariables.add(node)
// Attempt to extend existing local variable node corresponding to the record in
// the original local variable table.
val recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
if (recordToExtend != null && containsSuspensionPoint(recordToExtend.end, startLabel)) {
recordToExtend.end = endLabel
} else {
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
if (lvtRecord !in oldLvtNodeToLatestNewLvtNode) {
method.localVariables.add(node)
}
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
}
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
}
}
}
val deadVariables = arrayListOf<Int>()
outer@for (variableIndex in start until method.maxLocals) {
if (oldLvt.none { it.index == variableIndex }) continue
for (insnIndex in 0 until (method.instructions.size() - 1)) {
if (isAlive(insnIndex, variableIndex)) continue@outer
}
deadVariables += variableIndex
}
for (variable in oldLvt) {
// $continuation and $result are dead, but they are used by debugger, as well as fake inliner variables
// For example, $continuation is used to create async stack trace
@@ -1360,5 +1320,19 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
method.localVariables.add(variable)
continue
}
// Shrink LVT records of dead variables to the next suspension point
if (variable.index in deadVariables) {
method.localVariables.add(
LocalVariableNode(
variable.name,
variable.desc,
variable.signature,
variable.start,
min(variable.end, nextSuspensionPointStartLabel(variable.start)),
variable.index
)
)
}
}
}

View File

@@ -189,7 +189,7 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
Pair(it, typeArguments[candidateDescriptor.typeParameters[it.index]]!!.asTypeProjection())
}.toMap()
newCall.setSubstitutor(
newCall.setResultingSubstitutor(
TypeConstructorSubstitution.createByParametersMap(newTypeArguments).buildSubstitutor()
)

View File

@@ -547,7 +547,7 @@ class AnonymousObjectTransformer(
capturedParamBuilder.addCapturedParam(desc, desc.fieldName, !capturedOuterThisTypes.add(desc.type.className))
else
capturedParamBuilder.addCapturedParam(desc, addUniqueField(desc.fieldName + INLINE_TRANSFORMATION_SUFFIX), false)
if (desc.isSuspend) {
if (info is ExpressionLambda && info.isCapturedSuspend(desc)) {
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend
}
val composed = StackValue.field(

View File

@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.org.objectweb.asm.Type
class CapturedParamDesc(containingLambdaType: Type, val fieldName: String, val type: Type, val isSuspend: Boolean = false) {
val containingLambdaName: String = containingLambdaType.internalName
class CapturedParamDesc(private val containingLambdaType: Type, val fieldName: String, val type: Type) {
val containingLambdaName: String
get() = containingLambdaType.internalName
}

View File

@@ -320,7 +320,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
processor.localVarsMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true);
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
mark.dropTo()
}
@@ -329,7 +330,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
processor.substituteTryBlockNodes(intoNode)
processor.substituteLocalVarTable(intoNode);
//processor.substituteLocalVarTable(intoNode);
}
protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext)

View File

@@ -5,13 +5,32 @@
package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.*
import org.jetbrains.kotlin.codegen.binding.MutableClosure
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.coroutines.isCapturedSuspendLambda
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.resolve.BindingContext
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.ClassReader
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import kotlin.properties.Delegates
@@ -28,9 +47,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
abstract val invokeMethod: Method
abstract val invokeMethodParameters: List<KotlinType?>
abstract val invokeMethodReturnType: KotlinType?
abstract val invokeMethodDescriptor: FunctionDescriptor
abstract val capturedVars: List<CapturedParamDesc>
@@ -39,8 +56,6 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
lateinit var node: SMAPAndMethodNode
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>)
open val hasDispatchReceiver = true
@@ -52,7 +67,7 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName)
val recapturedParamInfo = builder.addCapturedParam(field, info.fieldName)
if (info.isSuspend) {
if (this is ExpressionLambda && isCapturedSuspend(info)) {
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend
}
}
@@ -60,9 +75,14 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
return builder.buildParameters()
}
companion object {
fun LambdaInfo.capturedParamDesc(fieldName: String, fieldType: Type, isSuspend: Boolean): CapturedParamDesc {
return CapturedParamDesc(lambdaClassType, fieldName, fieldType, isSuspend)
fun LambdaInfo.getCapturedParamInfo(descriptor: EnclosedValueDescriptor): CapturedParamDesc {
return capturedParamDesc(descriptor.fieldName, descriptor.type)
}
fun LambdaInfo.capturedParamDesc(fieldName: String, fieldType: Type): CapturedParamDesc {
return CapturedParamDesc(lambdaClassType, fieldName, fieldType)
}
}
}
@@ -70,19 +90,31 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
object NonInlineableArgumentForInlineableParameterCalledInSuspend : FunctionalArgument
object NonInlineableArgumentForInlineableSuspendParameter : FunctionalArgument
abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInline) {
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
node = sourceCompiler.generateLambdaBody(this, reifiedTypeParametersUsages)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
class PsiDefaultLambda(
lambdaClassType: Type,
capturedArgs: Array<Type>,
parameterDescriptor: ValueParameterDescriptor,
offset: Int,
needReification: Boolean
) : DefaultLambda(lambdaClassType, capturedArgs, parameterDescriptor, offset, needReification) {
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
}
override fun findInvokeMethodDescriptor(): FunctionDescriptor =
parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single()
}
abstract class DefaultLambda(
override val lambdaClassType: Type,
private val capturedArgs: Array<Type>,
isCrossinline: Boolean,
val parameterDescriptor: ValueParameterDescriptor,
val offset: Int,
val needReification: Boolean
) : LambdaInfo(isCrossinline) {
) : LambdaInfo(parameterDescriptor.isCrossinline) {
final override var isBoundCallableReference by Delegates.notNull<Boolean>()
private set
@@ -92,52 +124,80 @@ abstract class DefaultLambda(
final override lateinit var invokeMethod: Method
private set
override lateinit var invokeMethodDescriptor: FunctionDescriptor
final override lateinit var capturedVars: List<CapturedParamDesc>
private set
var originalBoundReceiverType: Type? = null
private set
override val isSuspend = false // TODO: it should probably be true sometimes, but it never was
override val isSuspend = parameterDescriptor.isSuspendLambda
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
val classBytes = loadClassBytesByInternalName(sourceCompiler.state, lambdaClassType.internalName)
val superName = ClassReader(classBytes).superName
val isPropertyReference = superName in PROPERTY_REFERENCE_SUPER_CLASSES
val isFunctionReference = superName == FUNCTION_REFERENCE.internalName || superName == FUNCTION_REFERENCE_IMPL.internalName
val classReader = ClassReader(classBytes)
var isPropertyReference = false
var isFunctionReference = false
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visit(
version: Int,
access: Int,
name: String,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
isPropertyReference = superName in PROPERTY_REFERENCE_SUPER_CLASSES
isFunctionReference = superName == FUNCTION_REFERENCE.internalName || superName == FUNCTION_REFERENCE_IMPL.internalName
val constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
val constructor = getMethodNode(classBytes, "<init>", constructorDescriptor, lambdaClassType)?.node
assert(constructor != null || capturedArgs.isEmpty()) {
"Can't find non-default constructor <init>$constructorDescriptor for default lambda $lambdaClassType"
super.visit(version, access, name, signature, superName, interfaces)
}
}, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG)
invokeMethodDescriptor = findInvokeMethodDescriptor().let {
//property reference generates erased 'get' method
if (isPropertyReference) it.original else it
}
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
val constructor = getMethodNode(classBytes, "<init>", descriptor, lambdaClassType)?.node
assert(constructor != null || capturedArgs.isEmpty()) {
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
}
capturedVars =
if (isFunctionReference || isPropertyReference)
constructor?.desc?.let { Type.getArgumentTypes(it) }?.singleOrNull()?.let {
originalBoundReceiverType = it
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, AsmUtil.boxType(it), isSuspend = false))
listOf(capturedParamDesc(AsmUtil.RECEIVER_PARAMETER_NAME, it.boxReceiverForBoundReference()))
} ?: emptyList()
else
constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode ->
capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc), isSuspend = false)
capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc))
}?.toList() ?: emptyList()
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
val invokeNameFallback = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
val invokeMethod = mapAsmMethod(sourceCompiler, isPropertyReference)
// TODO: `signatureAmbiguity = true` ignores the argument types from `invokeDescriptor` and only looks at the count.
// This effectively masks incorrect results from `mapAsmDescriptor`, which hopefully won't manifest in another way.
node = getMethodNode(classBytes, invokeMethod.name, invokeMethod.descriptor, lambdaClassType, signatureAmbiguity = true)
?: getMethodNode(classBytes, invokeNameFallback, invokeMethod.descriptor, lambdaClassType, signatureAmbiguity = true)
?: error("Can't find method '$invokeMethod' in '${lambdaClassType.internalName}'")
this.invokeMethod = Method(node.node.name, node.node.desc)
val methodName = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
val signature = mapAsmSignature(sourceCompiler)
node = getMethodNode(classBytes, methodName, signature.descriptor, lambdaClassType, signatureAmbiguity = true)
?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
invokeMethod = Method(node.node.name, node.node.desc)
if (needReification) {
//nested classes could also require reification
reifiedTypeParametersUsages.mergeAll(reifiedTypeInliner.reifyInstructions(node.node))
reifiedTypeInliner.reifyInstructions(node.node)
}
}
protected abstract fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method
protected abstract fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method
protected abstract fun findInvokeMethodDescriptor(): FunctionDescriptor
private companion object {
val PROPERTY_REFERENCE_SUPER_CLASSES =
@@ -148,3 +208,131 @@ abstract class DefaultLambda(
.mapTo(HashSet(), Type::getInternalName)
}
}
internal fun Type.boxReceiverForBoundReference() =
AsmUtil.boxType(this)
internal fun Type.boxReceiverForBoundReference(kotlinType: KotlinType, typeMapper: KotlinTypeMapper) =
DescriptorAsmUtil.boxType(this, kotlinType, typeMapper)
abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInline) {
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) {
node = sourceCompiler.generateLambdaBody(this)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
}
abstract fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor
abstract fun isCapturedSuspend(desc: CapturedParamDesc): Boolean
}
class PsiExpressionLambda(
expression: KtExpression,
private val typeMapper: KotlinTypeMapper,
private val languageVersionSettings: LanguageVersionSettings,
isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
) : ExpressionLambda(isCrossInline) {
override val lambdaClassType: Type
override val invokeMethod: Method
override val invokeMethodDescriptor: FunctionDescriptor
val classDescriptor: ClassDescriptor
val propertyReferenceInfo: PropertyReferenceInfo?
val functionWithBodyOrCallableReference: KtExpression = (expression as? KtLambdaExpression)?.functionLiteral ?: expression
override val returnLabels: Map<String, Label?>
override val isSuspend: Boolean
var closure: CalculatedClosure
private set
init {
val bindingContext = typeMapper.bindingContext
val function =
bindingContext.get<PsiElement, SimpleFunctionDescriptor>(BindingContext.FUNCTION, functionWithBodyOrCallableReference)
if (function == null && expression is KtCallableReferenceExpression) {
val variableDescriptor =
bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors
?: throw AssertionError("Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}")
classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, variableDescriptor)
?: throw IllegalStateException("Class for callable not found: $variableDescriptor\n${expression.text}")
lambdaClassType = typeMapper.mapClass(classDescriptor)
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(bindingContext)
propertyReferenceInfo = PropertyReferenceInfo(
resolvedCall.resultingDescriptor as VariableDescriptor, getFunction
)
} else {
propertyReferenceInfo = null
invokeMethodDescriptor = function ?: throw AssertionError("Function is not resolved to descriptor: " + expression.text)
classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, invokeMethodDescriptor)
?: throw IllegalStateException("Class for invoke method not found: $invokeMethodDescriptor\n${expression.text}")
lambdaClassType = asmTypeForAnonymousClass(bindingContext, invokeMethodDescriptor)
}
bindingContext.get<ClassDescriptor, MutableClosure>(CLOSURE, classDescriptor).let {
assert(it != null) { "Closure for lambda should be not null " + expression.text }
closure = it!!
}
returnLabels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
invokeMethod = typeMapper.mapAsmMethod(invokeMethodDescriptor)
isSuspend = invokeMethodDescriptor.isSuspend
}
override val capturedVars: List<CapturedParamDesc> by lazy {
arrayListOf<CapturedParamDesc>().apply {
val captureThis = closure.capturedOuterClassDescriptor
if (captureThis != null) {
val kotlinType = captureThis.defaultType
val type = typeMapper.mapType(kotlinType)
val descriptor = EnclosedValueDescriptor(
AsmUtil.CAPTURED_THIS_FIELD, null,
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0),
type, kotlinType
)
add(getCapturedParamInfo(descriptor))
}
val capturedReceiver = closure.capturedReceiverFromOuterContext
if (capturedReceiver != null) {
val type = typeMapper.mapType(capturedReceiver).let {
if (isBoundCallableReference) it.boxReceiverForBoundReference() else it
}
val fieldName = closure.getCapturedReceiverFieldName(typeMapper.bindingContext, languageVersionSettings)
val descriptor = EnclosedValueDescriptor(
fieldName, null,
StackValue.field(type, capturedReceiver, lambdaClassType, fieldName, false, StackValue.LOCAL_0),
type, capturedReceiver
)
add(getCapturedParamInfo(descriptor))
}
closure.captureVariables.values.forEach { descriptor ->
add(getCapturedParamInfo(descriptor))
}
}
}
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
override fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor {
return getOrCreateJvmSuspendFunctionView(
invokeMethodDescriptor,
languageVersionSettings.isReleaseCoroutines(),
typeMapper.bindingContext
)
}
override fun isCapturedSuspend(desc: CapturedParamDesc): Boolean =
isCapturedSuspendLambda(closure, desc.fieldName, typeMapper.bindingContext)
}

View File

@@ -23,10 +23,13 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -230,34 +233,52 @@ class MethodInliner(
return
}
val nullableAnyType = inliningContext.root.sourceCompilerForInline.compilationContextDescriptor.builtIns.nullableAnyType
val expectedParameters = info.invokeMethod.argumentTypes
val expectedKotlinParameters = info.invokeMethodParameters
val argumentCount = Type.getArgumentTypes(desc).size.let {
if (!inliningContext.root.state.isIrBackend && info.isSuspend && it < expectedParameters.size) {
// Inlining suspend lambda into a function that takes a non-suspend lambda.
// In the IR backend, this cannot happen as inline lambdas are not lowered.
// in case of inlining suspend lambda reference as ordinary parameter of inline function:
// suspend fun foo (...) ...
// inline fun inlineMe(c: (...) -> ...) ...
// builder {
// inlineMe(::foo)
// }
// we should create additional parameter for continuation.
var coroutineDesc = desc
val actualInvokeDescriptor: FunctionDescriptor
if (info.isSuspend) {
actualInvokeDescriptor = (info as ExpressionLambda).getInlineSuspendLambdaViewDescriptor()
val parametersSize = actualInvokeDescriptor.valueParameters.size +
(if (actualInvokeDescriptor.extensionReceiverParameter != null) 1 else 0)
// And here we expect invoke(...Ljava/lang/Object;) be replaced with invoke(...Lkotlin/coroutines/Continuation;)
// if this does not happen, insert fake continuation, since we could not have one yet.
val argumentTypes = Type.getArgumentTypes(desc)
if (argumentTypes.size != parametersSize &&
// But do not add it in IR. In IR we already have lowered lambdas with additional parameter, while in Old BE we don't.
!inliningContext.root.state.isIrBackend
) {
addFakeContinuationMarker(this)
it + 1
} else it
}
assert(argumentCount == expectedParameters.size && argumentCount == expectedKotlinParameters.size) {
"inconsistent lambda arguments: $argumentCount on stack, ${expectedParameters.size} expected, " +
"${expectedKotlinParameters.size} Kotlin types"
coroutineDesc = Type.getMethodDescriptor(Type.getReturnType(desc), *argumentTypes, AsmTypes.OBJECT_TYPE)
}
} else {
actualInvokeDescriptor = info.invokeMethodDescriptor
}
var valueParamShift = max(nextLocalIndex, markerShift) + expectedParameters.sumOf { it.size }
for (index in argumentCount - 1 downTo 0) {
val type = expectedParameters[index]
StackValue.coerce(AsmTypes.OBJECT_TYPE, nullableAnyType, type, expectedKotlinParameters[index], this)
valueParamShift -= type.size
store(valueParamShift, type)
}
if (expectedParameters.isEmpty()) {
nop() // add something for a line number to bind onto
val valueParameters =
listOfNotNull(actualInvokeDescriptor.extensionReceiverParameter) + actualInvokeDescriptor.valueParameters
val erasedInvokeFunction = ClosureCodegen.getErasedInvokeFunction(actualInvokeDescriptor)
val invokeParameters = erasedInvokeFunction.valueParameters
val valueParamShift = max(nextLocalIndex, markerShift)//NB: don't inline cause it changes
val parameterTypesFromDesc = info.invokeMethod.argumentTypes
putStackValuesIntoLocalsForLambdaOnInvoke(
listOf(*parameterTypesFromDesc), valueParameters, invokeParameters, valueParamShift, this, coroutineDesc
)
if (parameterTypesFromDesc.isEmpty()) {
// There won't be no parameters processing and line call can be left without actual instructions.
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
visitInsn(Opcodes.NOP)
}
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info.node.node, sourceMapper.parent)
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info, sourceMapper.parent)
addInlineMarker(this, true)
val lambdaParameters = info.addAllParameters(nodeRemapper)
@@ -282,9 +303,10 @@ class MethodInliner(
val lambdaResult = inliner.doInline(localVariablesSorter, varRemapper, true, info.returnLabels, invokeCall.finallyDepthShift)
result.mergeWithNotChangeInfo(lambdaResult)
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
result.reifiedTypeParametersUsages.mergeAll(info.reifiedTypeParametersUsages)
StackValue.coerce(info.invokeMethod.returnType, info.invokeMethodReturnType, OBJECT_TYPE, nullableAnyType, this)
StackValue
.onStack(info.invokeMethod.returnType, info.invokeMethodDescriptor.returnType)
.put(OBJECT_TYPE, erasedInvokeFunction.returnType, this)
setLambdaInlining(false)
addInlineMarker(this, false)
inlineOnlySmapSkipper?.onInlineLambdaEnd(remappingMethodAdapter)
@@ -1051,6 +1073,46 @@ class MethodInliner(
}
}
private fun putStackValuesIntoLocalsForLambdaOnInvoke(
directOrder: List<Type>,
directOrderOfArguments: List<ParameterDescriptor>,
directOrderOfInvokeParameters: List<ValueParameterDescriptor>,
shift: Int,
iv: InstructionAdapter,
descriptor: String
) {
val actualParams = Type.getArgumentTypes(descriptor)
assert(actualParams.size == directOrder.size) {
"Number of expected and actual parameters should be equal, but ${actualParams.size} != ${directOrder.size}!"
}
var currentShift = shift + directOrder.sumOf { it.size }
val safeToUseArgumentKotlinType =
directOrder.size == directOrderOfArguments.size && directOrderOfArguments.size == directOrderOfInvokeParameters.size
for (index in directOrder.lastIndex downTo 0) {
val type = directOrder[index]
currentShift -= type.size
val typeOnStack = actualParams[index]
val argumentKotlinType: KotlinType?
val invokeParameterKotlinType: KotlinType?
if (safeToUseArgumentKotlinType) {
argumentKotlinType = directOrderOfArguments[index].type
invokeParameterKotlinType = directOrderOfInvokeParameters[index].type
} else {
argumentKotlinType = null
invokeParameterKotlinType = null
}
if (typeOnStack != type || invokeParameterKotlinType != argumentKotlinType) {
StackValue.onStack(typeOnStack, invokeParameterKotlinType).put(type, argumentKotlinType, iv)
}
iv.store(currentShift, type)
}
}
//process local and global returns (local substituted with goto end-label global kept unchanged)
@JvmStatic
fun processReturns(

View File

@@ -5,23 +5,20 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.inline.InlineUtil
@@ -31,11 +28,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.Label
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.MethodNode
class PsiInlineCodegen(
@@ -146,9 +140,9 @@ class PsiInlineCodegen(
val receiverKotlinType = receiver.kotlinType
val boxedReceiver =
if (receiverKotlinType != null)
DescriptorAsmUtil.boxType(receiver.type, receiverKotlinType, state.typeMapper)
receiver.type.boxReceiverForBoundReference(receiverKotlinType, state.typeMapper)
else
AsmUtil.boxType(receiver.type)
receiver.type.boxReceiverForBoundReference()
putClosureParametersOnStack(
lambdaInfo,
@@ -220,139 +214,3 @@ class PsiInlineCodegen(
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
memberDescriptor is DescriptorWithContainerSource
}
private val FunctionDescriptor.explicitParameters
get() = listOfNotNull(extensionReceiverParameter) + valueParameters
class PsiExpressionLambda(
expression: KtExpression,
private val typeMapper: KotlinTypeMapper,
private val languageVersionSettings: LanguageVersionSettings,
isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
) : ExpressionLambda(isCrossInline) {
override val lambdaClassType: Type
override val invokeMethod: Method
val invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>
get() {
val actualInvokeDescriptor = if (isSuspend)
getOrCreateJvmSuspendFunctionView(
invokeMethodDescriptor, languageVersionSettings.isReleaseCoroutines(), typeMapper.bindingContext
)
else
invokeMethodDescriptor
return actualInvokeDescriptor.explicitParameters.map { it.returnType }
}
override val invokeMethodReturnType: KotlinType?
get() = invokeMethodDescriptor.returnType
val classDescriptor: ClassDescriptor
val propertyReferenceInfo: PropertyReferenceInfo?
val functionWithBodyOrCallableReference: KtExpression = (expression as? KtLambdaExpression)?.functionLiteral ?: expression
override val returnLabels: Map<String, Label?>
override val isSuspend: Boolean
val closure: CalculatedClosure
init {
val bindingContext = typeMapper.bindingContext
val function = bindingContext.get(BindingContext.FUNCTION, functionWithBodyOrCallableReference)
if (function == null && expression is KtCallableReferenceExpression) {
val variableDescriptor =
bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors
?: throw AssertionError("Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}")
classDescriptor = bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, variableDescriptor)
?: throw IllegalStateException("Class for callable not found: $variableDescriptor\n${expression.text}")
lambdaClassType = typeMapper.mapClass(classDescriptor)
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(bindingContext)
propertyReferenceInfo = PropertyReferenceInfo(resolvedCall.resultingDescriptor as VariableDescriptor, getFunction)
} else {
propertyReferenceInfo = null
invokeMethodDescriptor = function ?: throw AssertionError("Function is not resolved to descriptor: " + expression.text)
classDescriptor = bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, invokeMethodDescriptor)
?: throw IllegalStateException("Class for invoke method not found: $invokeMethodDescriptor\n${expression.text}")
lambdaClassType = CodegenBinding.asmTypeForAnonymousClass(bindingContext, invokeMethodDescriptor)
}
closure = bindingContext.get(CodegenBinding.CLOSURE, classDescriptor)
?: throw AssertionError("null closure for lambda ${expression.text}")
returnLabels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
invokeMethod = typeMapper.mapAsmMethod(invokeMethodDescriptor)
isSuspend = invokeMethodDescriptor.isSuspend
}
override val capturedVars: List<CapturedParamDesc> by lazy {
arrayListOf<CapturedParamDesc>().apply {
val captureThis = closure.capturedOuterClassDescriptor
if (captureThis != null) {
add(capturedParamDesc(AsmUtil.CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis.defaultType), isSuspend = false))
}
val capturedReceiver = closure.capturedReceiverFromOuterContext
if (capturedReceiver != null) {
val fieldName = closure.getCapturedReceiverFieldName(typeMapper.bindingContext, languageVersionSettings)
val type = typeMapper.mapType(capturedReceiver).let {
if (isBoundCallableReference) AsmUtil.boxType(it) else it
}
add(capturedParamDesc(fieldName, type, isSuspend = false))
}
closure.captureVariables.forEach { (parameter, value) ->
val isSuspend = parameter is ValueParameterDescriptor && parameter.type.isSuspendFunctionTypeOrSubtype
add(capturedParamDesc(value.fieldName, value.type, isSuspend))
}
}
}
val isPropertyReference: Boolean
get() = propertyReferenceInfo != null
}
class PsiDefaultLambda(
override val lambdaClassType: Type,
capturedArgs: Array<Type>,
private val parameterDescriptor: ValueParameterDescriptor,
offset: Int,
needReification: Boolean
) : DefaultLambda(capturedArgs, parameterDescriptor.isCrossinline, offset, needReification) {
private lateinit var invokeMethodDescriptor: FunctionDescriptor
override val invokeMethodParameters: List<KotlinType?>
get() = invokeMethodDescriptor.explicitParameters.map { it.returnType }
override val invokeMethodReturnType: KotlinType?
get() = invokeMethodDescriptor.returnType
override fun mapAsmMethod(sourceCompiler: SourceCompilerForInline, isPropertyReference: Boolean): Method {
val substitutedDescriptor = parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single()
invokeMethodDescriptor = when {
// Property references: `(A) -> B` => `get(Any?): Any?`
isPropertyReference -> substitutedDescriptor.original
// Suspend function references: `suspend (A) -> B` => `invoke(A, Continuation<B>): Any?`
// TODO: default suspend lambdas are currently uninlinable
parameterDescriptor.type.isSuspendFunctionType ->
getOrCreateJvmSuspendFunctionView(
substitutedDescriptor,
sourceCompiler.state.languageVersionSettings.isReleaseCoroutines(),
sourceCompiler.state.bindingContext
)
// Non-suspend function references and lambdas: `(A) -> B` => `invoke(A): B`
else -> substitutedDescriptor
}
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
}
}

View File

@@ -48,7 +48,7 @@ interface SourceCompilerForInline {
val lazySourceMapper: SourceMapper
fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode
fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode
fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
@@ -130,7 +130,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
override val lazySourceMapper
get() = codegen.parentCodegen.orCreateSourceMapper
override fun generateLambdaBody(lambdaInfo: ExpressionLambda, reifiedTypeParameters: ReifiedTypeParametersUsages): SMAPAndMethodNode {
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode {
lambdaInfo as? PsiExpressionLambda ?: error("TODO")
val invokeMethodDescriptor = lambdaInfo.invokeMethodDescriptor
val jvmMethodSignature = state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)

View File

@@ -2,13 +2,12 @@
* Copyright 2010-2019 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.
*/
@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package org.jetbrains.kotlin.codegen.inline.coroutines
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import jdk.internal.org.objectweb.asm.Type
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.coroutines.*
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
@@ -17,12 +16,10 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
@@ -253,18 +250,7 @@ fun FieldInsnNode.isSuspendLambdaCapturedByOuterObjectOrLambda(inliningContext:
while (container !is ClassDescriptor) {
container = container.containingDeclaration ?: return false
}
val bindingContext = inliningContext.state.bindingContext
var classDescriptor: ClassDescriptor? = container
while (classDescriptor != null) {
val closure = bindingContext[CodegenBinding.CLOSURE, classDescriptor] ?: return false
for ((param, value) in closure.captureVariables) {
if (param is ValueParameterDescriptor && value.fieldName == name) {
return param.type.isSuspendFunctionTypeOrSubtype
}
}
classDescriptor = closure.capturedOuterClassDescriptor
}
return false
return isCapturedSuspendLambda(container, name, inliningContext.state.bindingContext)
}
// Interpreter, that keeps track of captured functional arguments
@@ -301,4 +287,4 @@ private class CapturedLambdaInterpreter : BasicInterpreter(Opcodes.API_VERSION)
override fun merge(v: BasicValue?, w: BasicValue?): BasicValue? =
if (v is PossibleLambdaLoad && w is PossibleLambdaLoad && v.insn == w.insn) v else super.merge(v, w)
}
}

View File

@@ -579,8 +579,8 @@ class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
const val LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER = 1
}
fun onInlineLambdaStart(mv: MethodVisitor, lambda: MethodNode, smap: SourceMapper) {
val firstLine = lambda.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
fun onInlineLambdaStart(mv: MethodVisitor, info: LambdaInfo, smap: SourceMapper) {
val firstLine = info.node.node.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
if (callLineNumber >= 0 && firstLine == callLineNumber) {
// We want the debugger to be able to break both on the inline call itself, plus on each
// invocation of the inline lambda passed to it. For that to happen there needs to be at least

View File

@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.underlyingRepresentation
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import org.jetbrains.kotlin.types.KotlinType
@@ -24,8 +26,9 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.Method
fun KotlinType.isInlineClassWithUnderlyingTypeAnyOrAnyN(): Boolean {
val classDescriptor = constructor.declarationDescriptor
return classDescriptor is ClassDescriptor && classDescriptor.inlineClassRepresentation?.underlyingType?.isAnyOrNullableAny() == true
if (!isInlineClassType()) return false
val classDescriptor = constructor.declarationDescriptor as? ClassDescriptor ?: return false
return classDescriptor.underlyingRepresentation()?.type?.isAnyOrNullableAny() == true
}
fun CallableDescriptor.isGenericParameter(): Boolean {
@@ -76,4 +79,4 @@ fun classFileContainsMethod(classId: ClassId, state: GenerationState, method: Me
}
}, ClassReader.SKIP_FRAMES)
return found
}
}

View File

@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.optimization
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -32,10 +31,12 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
private val deadCodeElimination = DeadCodeEliminationMethodTransformer()
override fun transform(internalClassName: String, methodNode: MethodNode) {
do {
val changes = ConstantConditionsOptimization(internalClassName, methodNode).run()
if (changes) deadCodeElimination.transform(internalClassName, methodNode)
} while (changes)
}
@@ -48,21 +49,11 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
private fun collectRewriteActions(): List<() -> Unit> =
arrayListOf<() -> Unit>().also { actions ->
val deadCode = ArrayList<AbstractInsnNode>()
val frames = analyze(internalClassName, methodNode, ConstantPropagationInterpreter())
val insns = methodNode.instructions.toArray()
for (i in frames.indices) {
val insn = insns[i]
val frame = frames[i]
if (frame == null && insn !is LabelNode) {
deadCode.add(insn)
continue
}
if (insn !is JumpInsnNode) continue
val frame = frames[i] ?: continue
val insn = insns[i] as? JumpInsnNode ?: continue
when (insn.opcode) {
in Opcodes.IFEQ..Opcodes.IFLE ->
tryRewriteComparisonWithZero(insn, frame, actions)
@@ -70,12 +61,6 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
tryRewriteBinaryComparison(insn, frame, actions)
}
}
if (deadCode.isNotEmpty()) {
actions.add {
methodNode.instructions.removeAll(deadCode)
}
}
}
private fun tryRewriteComparisonWithZero(insn: JumpInsnNode, frame: Frame<BasicValue>, actions: ArrayList<() -> Unit>) {

View File

@@ -18,16 +18,12 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
import com.google.common.collect.ImmutableSet
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.RELEASE_COROUTINES_VERSION_SETTINGS
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.topLevelClassInternalName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -178,7 +174,7 @@ fun AbstractInsnNode.isUnboxing(state: GenerationState) =
isPrimitiveUnboxing() || isJavaLangClassUnboxing() || isInlineClassUnboxing(state)
fun AbstractInsnNode.isBoxing(state: GenerationState) =
isPrimitiveBoxing() || isJavaLangClassBoxing() || isInlineClassBoxing(state) || isCoroutinePrimitiveBoxing()
isPrimitiveBoxing() || isJavaLangClassBoxing() || isInlineClassBoxing(state)
fun AbstractInsnNode.isPrimitiveUnboxing() =
isMethodInsnWith(Opcodes.INVOKEVIRTUAL) {
@@ -215,19 +211,6 @@ fun AbstractInsnNode.isPrimitiveBoxing() =
isBoxingMethodDescriptor()
}
private val BOXING_CLASS_INTERNAL_NAME =
RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()
private fun isJvmPrimitiveName(name: String) = JvmPrimitiveType.values().any { it.javaKeywordName == name }
fun AbstractInsnNode.isCoroutinePrimitiveBoxing(): Boolean {
return isMethodInsnWith(Opcodes.INVOKESTATIC) {
owner == BOXING_CLASS_INTERNAL_NAME &&
name.startsWith("box") &&
isJvmPrimitiveName(name.substring(3).lowercase())
}
}
private fun MethodInsnNode.isBoxingMethodDescriptor(): Boolean {
val ownerType = Type.getObjectType(owner)
return desc == Type.getMethodDescriptor(ownerType, AsmUtil.unboxType(ownerType))

View File

@@ -17,9 +17,12 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.debugText
import org.jetbrains.kotlin.codegen.optimization.common.isLoadOperation
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.fixStack.peekWords
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.removeNodeGetNext
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
@@ -29,66 +32,91 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
import java.util.*
private typealias Transformation = (AbstractInsnNode) -> Unit
class PopBackwardPropagationTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
if (!OptimizationMethodVisitor.canBeOptimizedUsingSourceInterpreter(methodNode)) return
if (methodNode.instructions.any { it.isPop() || it.isPurePush() }) {
Transformer(methodNode).transform()
}
Transformer(methodNode).transform()
}
private class Transformer(val methodNode: MethodNode) {
private val REPLACE_WITH_NOP: Transformation = { insnList.set(it, InsnNode(Opcodes.NOP)) }
private val REPLACE_WITH_POP1: Transformation = { insnList.set(it, InsnNode(Opcodes.POP)) }
private val REPLACE_WITH_POP2: Transformation = { insnList.set(it, InsnNode(Opcodes.POP2)) }
private val INSERT_POP1_AFTER: Transformation = { insnList.insert(it, InsnNode(Opcodes.POP)) }
private val INSERT_POP2_AFTER: Transformation = { insnList.insert(it, InsnNode(Opcodes.POP2)) }
private interface Transformation {
fun apply(insn: AbstractInsnNode)
}
private inline fun Transformation(crossinline body: (AbstractInsnNode) -> Unit): Transformation =
object : Transformation {
override fun apply(insn: AbstractInsnNode) {
body(insn)
}
}
private val REPLACE_WITH_NOP = Transformation { insnList.set(it, createRemovableNopInsn()) }
private val REPLACE_WITH_POP1 = Transformation { insnList.set(it, InsnNode(Opcodes.POP)) }
private val REPLACE_WITH_POP2 = Transformation { insnList.set(it, InsnNode(Opcodes.POP2)) }
private val INSERT_POP1_AFTER = Transformation { insnList.insert(it, InsnNode(Opcodes.POP)) }
private val INSERT_POP2_AFTER = Transformation { insnList.insert(it, InsnNode(Opcodes.POP2)) }
private val insnList = methodNode.instructions
private val insns = insnList.toArray()
private val dontTouchInsnIndices = BitSet(insns.size)
private val transformations = hashMapOf<AbstractInsnNode, Transformation>()
private val removableNops = hashSetOf<InsnNode>()
private val frames by lazy { analyzeMethodBody() }
fun transform() {
val frames = Analyzer(HazardsTrackingInterpreter()).analyze("fake", methodNode)
for ((i, insn) in insns.withIndex()) {
val frame = frames[i] ?: continue
when (insn.opcode) {
Opcodes.POP ->
frame.top()?.let { input ->
// If this POP won't be removed, other POPs that touch the same values have to stay as well.
if (input.insns.any { it.shouldKeep() } || input.longerWhenFusedWithPop()) {
input.insns.markAsDontTouch()
}
}
Opcodes.POP2 -> frame.peekWords(2)?.forEach { it.insns.markAsDontTouch() }
Opcodes.DUP_X1 -> frame.peekWords(1, 1)?.forEach { it.insns.markAsDontTouch() }
Opcodes.DUP2_X1 -> frame.peekWords(2, 1)?.forEach { it.insns.markAsDontTouch() }
Opcodes.DUP_X2 -> frame.peekWords(1, 2)?.forEach { it.insns.markAsDontTouch() }
Opcodes.DUP2_X2 -> frame.peekWords(2, 2)?.forEach { it.insns.markAsDontTouch() }
}
}
if (insns.none { it.isPop() || it.isPurePush() }) return
val transformations = hashMapOf<AbstractInsnNode, Transformation>()
for ((i, insn) in insns.withIndex()) {
computeTransformations()
for ((insn, transformation) in transformations.entries) {
transformation.apply(insn)
}
postprocessNops()
}
private fun analyzeMethodBody(): Array<out Frame<SourceValue>?> {
val frames = Analyzer<SourceValue>(HazardsTrackingInterpreter()).analyze("fake", methodNode)
postprocessStackHazards(frames)
return frames
}
private fun postprocessStackHazards(frames: Array<out Frame<SourceValue>?>) {
val insns = methodNode.instructions.toArray()
for (i in frames.indices) {
val frame = frames[i] ?: continue
if (insn.opcode == Opcodes.POP) {
val input = frame.top() ?: continue
if (input.insns.none { it.shouldKeep() }) {
transformations[insn] = REPLACE_WITH_NOP
input.insns.forEach {
if (it !in transformations) {
transformations[it] = it.combineWithPop(frames, input.size)
}
}
val insn = insns[i]
when (insn.opcode) {
Opcodes.POP2 -> {
val top2 = frame.peekWords(2) ?: throwIncorrectBytecode(insn, frame)
top2.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP_X1 -> {
val top2 = frame.peekWords(1, 1) ?: throwIncorrectBytecode(insn, frame)
top2.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP2_X1 -> {
val top3 = frame.peekWords(2, 1) ?: throwIncorrectBytecode(insn, frame)
top3.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP_X2 -> {
val top3 = frame.peekWords(1, 2) ?: throwIncorrectBytecode(insn, frame)
top3.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP2_X2 -> {
val top4 = frame.peekWords(2, 2) ?: throwIncorrectBytecode(insn, frame)
top4.forEach { it.insns.markAsDontTouch() }
}
}
}
for ((insn, transformation) in transformations.entries) {
transformation(insn)
}
}
private fun throwIncorrectBytecode(insn: AbstractInsnNode?, frame: Frame<SourceValue>): Nothing {
throw AssertionError("Incorrect bytecode at ${methodNode.instructions.indexOf(insn)}: ${insn.debugText} $frame")
}
private inner class HazardsTrackingInterpreter : SourceInterpreter(Opcodes.API_VERSION) {
@@ -105,7 +133,9 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
}
override fun unaryOperation(insn: AbstractInsnNode, value: SourceValue): SourceValue {
value.insns.markAsDontTouch()
if (insn.opcode != Opcodes.CHECKCAST && !insn.isPrimitiveTypeConversion()) {
value.insns.markAsDontTouch()
}
return super.unaryOperation(insn, value)
}
@@ -134,48 +164,153 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
}
}
private fun SourceValue.longerWhenFusedWithPop() = insns.fold(0) { x, insn ->
when {
insn.isPurePush() -> x - 1
insn.isPrimitiveBoxing() || insn.isPrimitiveTypeConversion() -> x
else -> x + 1
}
} > 0
private fun AbstractInsnNode.combineWithPop(frames: Array<out Frame<SourceValue>?>, resultSize: Int): Transformation =
private fun computeTransformations() {
transformations.clear()
for (i in insns.indices) {
if (frames[i] == null) continue
val insn = insns[i]
if (insn.opcode == Opcodes.POP) {
propagatePopBackwards(insn, 0)
}
}
}
private fun propagatePopBackwards(insn: AbstractInsnNode, poppedValueSize: Int) {
if (transformations.containsKey(insn)) return
when {
isPurePush() -> REPLACE_WITH_NOP
isPrimitiveBoxing() || isPrimitiveTypeConversion() -> {
val index = insnList.indexOf(this)
val frame = frames[index] ?: throw AssertionError("dead instruction #$index used by non-dead instruction")
val input = frame.top() ?: throw AssertionError("coercion instruction at #$index has no input")
when (input.size) {
1 -> REPLACE_WITH_POP1
2 -> REPLACE_WITH_POP2
else -> throw AssertionError("Unexpected pop value size: ${input.size}")
insn.opcode == Opcodes.POP -> {
val inputTop = getInputTop(insn)
val sources = inputTop.insns
if (sources.all { !isDontTouch(it) } && sources.any { isTransformablePopOperand(it) }) {
transformations[insn] = replaceWithNopTransformation()
sources.forEach { propagatePopBackwards(it, inputTop.size) }
}
}
else ->
when (resultSize) {
1 -> INSERT_POP1_AFTER
2 -> INSERT_POP2_AFTER
else -> throw AssertionError("Unexpected pop value size: $resultSize")
insn.opcode == Opcodes.CHECKCAST -> {
val inputTop = getInputTop(insn)
val sources = inputTop.insns
val resultType = (insn as TypeInsnNode).desc
if (sources.all { !isDontTouch(it) } && sources.any { isTransformableCheckcastOperand(it, resultType) }) {
transformations[insn] = replaceWithNopTransformation()
sources.forEach { propagatePopBackwards(it, inputTop.size) }
} else {
transformations[insn] = insertPopAfterTransformation(poppedValueSize)
}
}
insn.isPrimitiveBoxing() -> {
val boxedValueSize = getInputTop(insn).size
transformations[insn] = replaceWithPopTransformation(boxedValueSize)
}
insn.isPurePush() -> {
transformations[insn] = replaceWithNopTransformation()
}
insn.isPrimitiveTypeConversion() -> {
val inputTop = getInputTop(insn)
val sources = inputTop.insns
if (sources.all { !isDontTouch(it) }) {
transformations[insn] = replaceWithNopTransformation()
sources.forEach { propagatePopBackwards(it, inputTop.size) }
} else {
transformations[insn] = replaceWithPopTransformation(poppedValueSize)
}
}
else -> {
transformations[insn] = insertPopAfterTransformation(poppedValueSize)
}
}
}
private fun postprocessNops() {
var node: AbstractInsnNode? = insnList.first
var hasRemovableNops = false
while (node != null) {
node = node.next
val begin = node ?: break
while (node != null && node !is LabelNode) {
if (node in removableNops) {
hasRemovableNops = true
}
node = node.next
}
val end = node
if (hasRemovableNops) {
removeUnneededNopsInRange(begin, end)
}
hasRemovableNops = false
}
}
private fun removeUnneededNopsInRange(begin: AbstractInsnNode, end: AbstractInsnNode?) {
var node: AbstractInsnNode? = begin
var keepNop = true
while (node != null && node != end) {
if (node in removableNops && !keepNop) {
node = insnList.removeNodeGetNext(node)
} else {
if (node.isMeaningful) keepNop = false
node = node.next
}
}
}
private fun replaceWithPopTransformation(size: Int): Transformation =
when (size) {
1 -> REPLACE_WITH_POP1
2 -> REPLACE_WITH_POP2
else -> throw AssertionError("Unexpected pop value size: $size")
}
private fun AbstractInsnNode.shouldKeep() =
dontTouchInsnIndices[insnList.indexOf(this)]
private fun insertPopAfterTransformation(size: Int): Transformation =
when (size) {
1 -> INSERT_POP1_AFTER
2 -> INSERT_POP2_AFTER
else -> throw AssertionError("Unexpected pop value size: $size")
}
private fun replaceWithNopTransformation(): Transformation =
REPLACE_WITH_NOP
private fun createRemovableNopInsn() =
InsnNode(Opcodes.NOP).apply { removableNops.add(this) }
private fun getInputTop(insn: AbstractInsnNode): SourceValue {
val i = insnList.indexOf(insn)
val frame = frames[i] ?: throw AssertionError("Unexpected dead instruction #$i")
return frame.top() ?: throw AssertionError("Instruction #$i has empty stack on input")
}
private fun isTransformableCheckcastOperand(it: AbstractInsnNode, resultType: String) =
it.isPrimitiveBoxing() && (it as MethodInsnNode).owner == resultType
private fun isTransformablePopOperand(insn: AbstractInsnNode) =
insn.opcode == Opcodes.CHECKCAST || insn.isPrimitiveBoxing() || insn.isPurePush()
private fun isDontTouch(insn: AbstractInsnNode) =
dontTouchInsnIndices[insnList.indexOf(insn)]
}
}
fun AbstractInsnNode.isPurePush() =
isLoadOperation() || opcode in Opcodes.ACONST_NULL..Opcodes.LDC + 2 || isUnitInstance()
isLoadOperation() ||
opcode in Opcodes.ACONST_NULL..Opcodes.LDC + 2 ||
isUnitInstance()
fun AbstractInsnNode.isPop() =
opcode == Opcodes.POP || opcode == Opcodes.POP2
fun AbstractInsnNode.isUnitInstance() =
opcode == Opcodes.GETSTATIC && this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"
opcode == Opcodes.GETSTATIC &&
this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"
fun AbstractInsnNode.isPrimitiveTypeConversion() =
opcode in Opcodes.I2L..Opcodes.I2S

View File

@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class StackPeepholeOptimizationsTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
while (true) {
if (!transformOnce(methodNode)) break
while (transformOnce(methodNode)) {
}
}
@@ -113,26 +115,20 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() {
opcode == Opcodes.DUP
private fun AbstractInsnNode.isPurePushOfSize1(): Boolean =
!isLdcOfSize2() && (
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
opcode == Opcodes.FLOAD ||
opcode == Opcodes.ALOAD ||
isUnitInstance()
)
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
opcode == Opcodes.FLOAD ||
opcode == Opcodes.ALOAD ||
isUnitInstance()
private fun AbstractInsnNode.isEliminatedByPop2() =
isPurePushOfSize2() ||
opcode == Opcodes.DUP2
private fun AbstractInsnNode.isPurePushOfSize2(): Boolean =
isLdcOfSize2() ||
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1 ||
opcode == Opcodes.LLOAD ||
opcode == Opcodes.DLOAD
private fun AbstractInsnNode.isLdcOfSize2(): Boolean =
opcode == Opcodes.LDC && this is LdcInsnNode && (this.cst is Double || this.cst is Long)
}

View File

@@ -39,9 +39,9 @@ import org.jetbrains.org.objectweb.asm.tree.*
class RedundantNullCheckMethodTransformer(private val generationState: GenerationState) : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
do {
val changes = TransformerPass(internalClassName, methodNode, generationState).run()
} while (changes)
@Suppress("ControlFlowWithEmptyBody")
while (TransformerPass(internalClassName, methodNode, generationState).run()) {
}
}
private class TransformerPass(val internalClassName: String, val methodNode: MethodNode, val generationState: GenerationState) {
@@ -170,14 +170,14 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
}
private fun collectVariableDependentChecks() {
for (insn in methodNode.instructions) {
insnLoop@ for (insn in methodNode.instructions) {
when {
insn.isInstanceOfOrNullCheck() -> {
val previous = insn.previous ?: continue
val previous = insn.previous ?: continue@insnLoop
if (previous.opcode == Opcodes.ALOAD) {
addDependentCheck(insn, previous as VarInsnNode)
} else if (previous.opcode == Opcodes.DUP) {
val previous2 = previous.previous ?: continue
val previous2 = previous.previous ?: continue@insnLoop
if (previous2.opcode == Opcodes.ALOAD) {
addDependentCheck(insn, previous2 as VarInsnNode)
}
@@ -185,36 +185,36 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
}
insn.isCheckNotNull() -> {
val previous = insn.previous ?: continue
val previous = insn.previous ?: continue@insnLoop
val aLoadInsn = if (previous.opcode == Opcodes.DUP) {
previous.previous ?: continue
previous.previous ?: continue@insnLoop
} else previous
if (aLoadInsn.opcode != Opcodes.ALOAD) continue
if (aLoadInsn.opcode != Opcodes.ALOAD) continue@insnLoop
addDependentCheck(insn, aLoadInsn as VarInsnNode)
}
insn.isCheckParameterIsNotNull() -> {
val ldcInsn = insn.previous ?: continue
if (ldcInsn.opcode != Opcodes.LDC) continue
val aLoadInsn = ldcInsn.previous ?: continue
if (aLoadInsn.opcode != Opcodes.ALOAD) continue
val ldcInsn = insn.previous ?: continue@insnLoop
if (ldcInsn.opcode != Opcodes.LDC) continue@insnLoop
val aLoadInsn = ldcInsn.previous ?: continue@insnLoop
if (aLoadInsn.opcode != Opcodes.ALOAD) continue@insnLoop
addDependentCheck(insn, aLoadInsn as VarInsnNode)
}
insn.isCheckExpressionValueIsNotNull() -> {
val ldcInsn = insn.previous ?: continue
if (ldcInsn.opcode != Opcodes.LDC) continue
val ldcInsn = insn.previous ?: continue@insnLoop
if (ldcInsn.opcode != Opcodes.LDC) continue@insnLoop
var aLoadInsn: VarInsnNode? = null
val insn1 = ldcInsn.previous ?: continue
val insn1 = ldcInsn.previous ?: continue@insnLoop
if (insn1.opcode == Opcodes.ALOAD) {
aLoadInsn = insn1 as VarInsnNode
} else if (insn1.opcode == Opcodes.DUP) {
val insn2 = insn1.previous ?: continue
val insn2 = insn1.previous ?: continue@insnLoop
if (insn2.opcode == Opcodes.ALOAD) {
aLoadInsn = insn2 as VarInsnNode
}
}
if (aLoadInsn == null) continue
if (aLoadInsn == null) continue@insnLoop
addDependentCheck(insn, aLoadInsn)
}
}

View File

@@ -29,7 +29,4 @@ class JvmCodegenStringTable @JvmOverloads constructor(
ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
}
}
override val isLocalClassIdReplacementKeptGeneric: Boolean
get() = true
}

View File

@@ -30,7 +30,6 @@ dependencies {
compile(project(":compiler:fir:fir2ir"))
compile(project(":compiler:fir:fir2ir:jvm-backend"))
compile(project(":compiler:fir:checkers"))
compile(project(":compiler:fir:checkers:checkers.jvm"))
compile(project(":kotlin-util-klib"))
compile(project(":kotlin-util-io"))

View File

@@ -151,18 +151,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
)
var irModuleName: String? by NullableStringFreezableVar(null)
@Argument(value = "-Xir-legacy-property-access", description = "Force property access via JS properties (requires -Xir-export-all)")
var irLegacyPropertyAccess: Boolean by FreezableVar(false)
@Argument(value = "-Xir-base-class-in-metadata", description = "Write base class into metadata")
var irBaseClassInMetadata: Boolean by FreezableVar(false)
@Argument(value = "-Xir-per-module", description = "Splits generated .js per-module")
var irPerModule: Boolean by FreezableVar(false)
@Argument(value = "-Xir-per-module-output-name", description = "Adds a custom output name to the splitted js files")
var irPerModuleOutputName: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xinclude",
valueDescription = "<path>",
@@ -170,16 +161,6 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
)
var includes: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xcache-directories",
valueDescription = "<path>",
description = "A path to cache directories"
)
var cacheDirectories: String? by NullableStringFreezableVar(null)
@Argument(value = "-Xir-build-cache", description = "Use compiler to build cache")
var irBuildCache: Boolean by FreezableVar(false)
@Argument(
value = "-Xgenerate-dts",
description = "Generate TypeScript declarations .d.ts file alongside JS file. Available in IR backend only."
@@ -231,7 +212,7 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
}
fun K2JSCompilerArguments.isPreIrBackendDisabled(): Boolean =
irOnly || irProduceJs || irProduceKlibFile || irBuildCache
irOnly || irProduceJs || irProduceKlibFile
fun K2JSCompilerArguments.isIrBackendEnabled(): Boolean =
irProduceKlibDir || irProduceJs || irProduceKlibFile || wasm || irBuildCache
irProduceKlibDir || irProduceJs || irProduceKlibFile || wasm

View File

@@ -30,11 +30,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-include-runtime", description = "Include Kotlin runtime into the resulting JAR")
var includeRuntime: Boolean by FreezableVar(false)
@DeprecatedOption(
message = "This option is not working well with Gradle caching and will be removed in the future.",
removeAfter = "1.7",
level = DeprecationLevel.WARNING
)
@GradleOption(DefaultValues.StringNullDefault::class)
@Argument(
value = "-jdk-home",

View File

@@ -161,10 +161,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val outputFile = File(outputFilePath)
val moduleName = arguments.irModuleName ?: FileUtil.getNameWithoutExtension(outputFile)
configurationJs.put(
CommonConfigurationKeys.MODULE_NAME,
moduleName
arguments.irModuleName ?: FileUtil.getNameWithoutExtension(outputFile)
)
// TODO: in this method at least 3 different compiler configurations are used (original, env.configuration, jsConfig.configuration)
@@ -206,8 +205,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
friendDependencies = friendDependencies,
irFactory = PersistentIrFactory(), // TODO IrFactoryImpl?
outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir,
jsOutputName = arguments.irPerModuleOutputName,
nopack = arguments.irProduceKlibDir
)
}
@@ -275,10 +273,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
multiModule = arguments.irPerModule,
relativeRequirePath = true,
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
legacyPropertyAccess = arguments.irLegacyPropertyAccess,
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
)
val jsCode = if (arguments.irDce && !arguments.irDceDriven) compiledModule.dceJsCode!! else compiledModule.jsCode!!
outputFile.writeText(jsCode.mainModule)
jsCode.dependencies.forEach { (name, content) ->

View File

@@ -53,7 +53,6 @@ public class Usage {
appendln(sb, "Advanced options are non-standard and may be changed or removed without any notice.");
}
else {
renderOptionJUsage(sb);
renderArgfileUsage(sb);
}
@@ -104,15 +103,6 @@ public class Usage {
appendln(sb, argument.description().replace("\n", "\n" + StringsKt.repeat(" ", OPTION_NAME_PADDING_WIDTH)));
}
private static void renderOptionJUsage(@NotNull StringBuilder sb) {
int descriptionStart = sb.length() + OPTION_NAME_PADDING_WIDTH;
sb.append(" -J<option>");
while (sb.length() < descriptionStart) {
sb.append(" ");
}
appendln(sb, "Pass an option directly to JVM");
}
private static void renderArgfileUsage(@NotNull StringBuilder sb) {
int descriptionStart = sb.length() + OPTION_NAME_PADDING_WIDTH;
sb.append(" ");

View File

@@ -22,7 +22,6 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -38,7 +37,6 @@ import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleGraph
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.isValidJavaFqName
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME
@@ -54,13 +52,10 @@ class ClasspathRootsResolver(
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?,
private val javaFileManager: KotlinCliJavaFileManager
private val outputDirectory: VirtualFile?
) {
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
private val searchScope = GlobalSearchScope.allScope(psiManager.project)
data class RootsAndModules(val roots: List<JavaRoot>, val modules: List<JavaModule>)
private data class RootWithPrefix(val root: VirtualFile, val packagePrefix: String?)
@@ -165,7 +160,7 @@ class ClasspathRootsResolver(
}
if (moduleInfoFile != null) {
val moduleInfo = JavaModuleInfo.read(moduleInfoFile, javaFileManager, searchScope) ?: return null
val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null
return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(root, isBinary = true)), moduleInfoFile)
}

View File

@@ -37,7 +37,7 @@ class CliKotlinAsJavaSupport(
return findFacadeFilesInPackage(packageFqName, scope)
.groupBy { it.javaFileFacadeFqName }
.mapNotNull { (facadeClassFqName, _) ->
KtLightClassForFacadeImpl.createForFacade(psiManager, facadeClassFqName, scope)
KtLightClassForFacade.createForFacade(psiManager, facadeClassFqName, scope)
}
}
@@ -54,7 +54,7 @@ class CliKotlinAsJavaSupport(
.orEmpty()
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
return listOfNotNull(KtLightClassForFacadeImpl.createForFacade(psiManager, facadeFqName, scope))
return listOfNotNull(KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope))
}
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {

View File

@@ -35,10 +35,6 @@ class CliVirtualFileFinder(
override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? =
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
override fun findSourceOrBinaryVirtualFile(classId: ClassId) =
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
?: findSourceClass(classId, classId.relativeClassName.asString() + ".java")
override fun findMetadata(classId: ClassId): InputStream? {
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
@@ -65,11 +61,8 @@ class CliVirtualFileFinder(
return findBinaryClass(classId, BuiltInSerializerProtocol.getBuiltInsFileName(packageFqName))?.inputStream
}
private fun findClass(classId: ClassId, fileName: String, rootType: Set<JavaRoot.RootType>) =
index.findClass(classId, acceptedRootTypes = rootType) { dir, _ ->
private fun findBinaryClass(classId: ClassId, fileName: String): VirtualFile? =
index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
dir.findChild(fileName)?.takeIf(VirtualFile::isValid)
}?.takeIf { it in scope }
private fun findBinaryClass(classId: ClassId, fileName: String) = findClass(classId, fileName, JavaRoot.OnlyBinary)
private fun findSourceClass(classId: ClassId, fileName: String) = findClass(classId, fileName, JavaRoot.OnlySource)
}

View File

@@ -1,234 +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.cli.jvm.compiler
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensionsImpl
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.jvmPhases
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenFactory
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionFactory.createSessionWithDependencies
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.diagnostics.SimpleGenericDiagnostics
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File
object FirKotlinToJvmBytecodeCompiler {
fun compileModulesUsingFrontendIR(
environment: KotlinCoreEnvironment,
buildFile: File?,
chunk: List<Module>,
extendedAnalysisMode: Boolean
): Boolean {
val project = environment.project
val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER)
environment.messageCollector.report(
STRONG_WARNING,
"ATTENTION!\n This build uses in-dev FIR: \n -Xuse-fir"
)
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
val projectConfiguration = environment.configuration
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val outputs = newLinkedHashMapWithExpectedSize<Module, GenerationState>(chunk.size)
val targetIds = environment.configuration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId)
val incrementalComponents = environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS)
for (module in chunk) {
performanceManager?.notifyAnalysisStarted()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val ktFiles = module.getSourceFiles(environment, localFileSystem, chunk.size > 1, buildFile)
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile ->
AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, environment.messageCollector).isHasErrors or errorsFound
}
val moduleConfiguration = projectConfiguration.applyModuleProperties(module, buildFile)
val sourceScope = GlobalSearchScope.filesWithoutLibrariesScope(project, ktFiles.map { it.virtualFile })
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
var librariesScope = ProjectScope.getLibrariesScope(project)
val providerAndScopeForIncrementalCompilation = run {
if (targetIds == null || incrementalComponents == null) return@run null
val fileSystem = environment.projectEnvironment.environment.localFileSystem
val directoryWithIncrementalPartsFromPreviousCompilation =
moduleConfiguration[JVMConfigurationKeys.OUTPUT_DIRECTORY]
?: return@run null
val previouslyCompiledFiles = directoryWithIncrementalPartsFromPreviousCompilation.walk()
.filter { it.extension == "class" }
.mapNotNull { fileSystem.findFileByIoFile(it) }
.toList()
.takeIf { it.isNotEmpty() }
?: return@run null
val packagePartProvider = IncrementalPackagePartProvider(
environment.createPackagePartProvider(sourceScope),
targetIds.map(incrementalComponents::getIncrementalCache)
)
val incrementalCompilationScope = GlobalSearchScope.filesWithoutLibrariesScope(
project,
previouslyCompiledFiles
)
librariesScope = librariesScope.intersectWith(GlobalSearchScope.notScope(incrementalCompilationScope))
FirSessionFactory.ProviderAndScopeForIncrementalCompilation(packagePartProvider, incrementalCompilationScope)
}
val languageVersionSettings = moduleConfiguration.languageVersionSettings
val session = createSessionWithDependencies(
Name.identifier(module.getModuleName()),
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices,
externalSessionProvider = null,
project,
languageVersionSettings,
sourceScope,
librariesScope,
lookupTracker = environment.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
providerAndScopeForIncrementalCompilation,
getPackagePartProvider = { environment.createPackagePartProvider(it) },
dependenciesConfigurator = {
dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() })
dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() })
friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
},
sessionConfigurator = {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
)
val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles)
firAnalyzerFacade.runResolution()
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
AnalyzerWithCompilerReport.reportDiagnostics(
SimpleGenericDiagnostics(firDiagnostics),
environment.messageCollector
)
performanceManager?.notifyAnalysisFinished()
if (syntaxErrors || firDiagnostics.any { it.severity == Severity.ERROR }) {
return false
}
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val extensions = JvmGeneratorExtensionsImpl()
val (moduleFragment, symbolTable, components) = firAnalyzerFacade.convertToIr(extensions)
performanceManager?.notifyIRTranslationFinished()
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val codegenFactory = JvmIrCodegenFactory(moduleConfiguration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases))
// Create and initialize the module and its dependencies
val container = TopDownAnalyzerFacadeForJVM.createContainer(
project, ktFiles, NoScopeRecordCliBindingTrace(), environment.configuration, environment::createPackagePartProvider,
::FileBasedDeclarationProviderFactory, CompilerEnvironment,
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles), emptyList()
)
val generationState = GenerationState.Builder(
environment.project, ClassBuilderFactories.BINARIES,
container.get(), dummyBindingContext, ktFiles,
moduleConfiguration
).codegenFactory(
codegenFactory
).withModule(
module
).onIndependentPartCompilationEnd(
createOutputFilesFlushingCallbackIfPossible(moduleConfiguration)
).isIrBackend(
true
).jvmBackendClassResolver(
FirJvmBackendClassResolver(components)
).build()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
performanceManager?.notifyIRLoweringStarted()
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components)
) {
performanceManager?.notifyIRLoweringFinished()
performanceManager?.notifyIRGenerationStarted()
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
AnalyzerWithCompilerReport.reportDiagnostics(
FilteredJvmDiagnostics(
generationState.collectedExtraJvmDiagnostics,
dummyBindingContext.diagnostics
),
environment.messageCollector
)
performanceManager?.notifyIRGenerationFinished()
performanceManager?.notifyGenerationFinished()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
outputs[module] = generationState
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
Disposer.dispose(environment.project)
}
val mainClassFqName: FqName? =
if (chunk.size == 1 && projectConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null)
TODO(".jar output is not yet supported for -Xuse-fir: KT-42868")
else null
return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName)
}
}

View File

@@ -82,7 +82,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = BinaryClassSignatureParser()
fun findClass(classId: ClassId, searchScope: GlobalSearchScope) = findClass(JavaClassFinder.Request(classId), searchScope)
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
val (classId, classFileContentFromRequest, outerClassFromRequest) = request

View File

@@ -190,17 +190,11 @@ class KotlinCoreEnvironment private constructor(
sourceFiles.sortBy { it.virtualFile.path }
val javaFileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
val javaModuleFinder = CliJavaModuleFinder(
jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
},
javaFileManager,
project
)
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
})
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
@@ -213,8 +207,7 @@ class KotlinCoreEnvironment private constructor(
this::contentRootToVirtualFile,
javaModuleFinder,
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
outputDirectory?.let(this::findLocalFile),
javaFileManager
outputDirectory?.let(this::findLocalFile)
)
val (initialRoots, javaModules) =
@@ -238,7 +231,7 @@ class KotlinCoreEnvironment private constructor(
updateClasspathFromRootsIndex(this)
}
javaFileManager.initialize(
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
rootsIndex,
packagePartProviders,
SingleJavaFileRootsIndex(singleJavaFileRoots),
@@ -247,7 +240,7 @@ class KotlinCoreEnvironment private constructor(
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList(), project)
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)

View File

@@ -78,7 +78,10 @@ import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.extensions.*
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor
@@ -190,16 +193,11 @@ class KotlinCoreEnvironment private constructor(
sourceFiles.sortBy { it.virtualFile.path }
val javaFileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
val javaModuleFinder = CliJavaModuleFinder(
jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
},
javaFileManager
)
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
})
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
@@ -212,8 +210,7 @@ class KotlinCoreEnvironment private constructor(
this::contentRootToVirtualFile,
javaModuleFinder,
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
outputDirectory?.let(this::findLocalFile),
javaFileManager
outputDirectory?.let(this::findLocalFile)
)
val (initialRoots, javaModules) =
@@ -237,7 +234,7 @@ class KotlinCoreEnvironment private constructor(
updateClasspathFromRootsIndex(this)
}
javaFileManager.initialize(
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
rootsIndex,
packagePartProviders,
SingleJavaFileRootsIndex(singleJavaFileRoots),
@@ -246,7 +243,7 @@ class KotlinCoreEnvironment private constructor(
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList(), project)
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)

View File

@@ -17,42 +17,140 @@
package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.*
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiJavaModule
import com.intellij.psi.search.DelegatingGlobalSearchScope
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensionsImpl
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.jvmPhases
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.common.output.writeAll
import org.jetbrains.kotlin.cli.common.toLogger
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenFactory
import org.jetbrains.kotlin.codegen.DefaultCodegenFactory
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.createSessionWithDependencies
import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.diagnostics.SimpleGenericDiagnostics
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File
import kotlin.collections.set
object KotlinToJVMBytecodeCompiler {
private fun writeOutput(
configuration: CompilerConfiguration,
outputFiles: OutputFileCollection,
mainClassFqName: FqName?
) {
val reportOutputFiles = configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
val jarPath = configuration.get(JVMConfigurationKeys.OUTPUT_JAR)
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
if (jarPath != null) {
val includeRuntime = configuration.get(JVMConfigurationKeys.INCLUDE_RUNTIME, false)
val noReflect = configuration.get(JVMConfigurationKeys.NO_REFLECT, false)
val resetJarTimestamps = !configuration.get(JVMConfigurationKeys.NO_RESET_JAR_TIMESTAMPS, false)
CompileEnvironmentUtil.writeToJar(jarPath, includeRuntime, noReflect, resetJarTimestamps, mainClassFqName, outputFiles, messageCollector)
if (reportOutputFiles) {
val message = OutputMessageUtil.formatOutputMessage(outputFiles.asList().flatMap { it.sourceFiles }.distinct(), jarPath)
messageCollector.report(OUTPUT, message)
}
return
}
val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) ?: File(".")
outputFiles.writeAll(outputDir, messageCollector, reportOutputFiles)
}
private fun createOutputFilesFlushingCallbackIfPossible(configuration: CompilerConfiguration): GenerationStateEventCallback {
if (configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) == null) {
return GenerationStateEventCallback.DO_NOTHING
}
return GenerationStateEventCallback { state ->
val currentOutput = SimpleOutputFileCollection(state.factory.currentOutput)
writeOutput(configuration, currentOutput, null)
if (!configuration.get(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false)) {
state.factory.releaseGeneratedOutput()
}
}
}
private fun Module.getSourceFiles(
environment: KotlinCoreEnvironment,
localFileSystem: VirtualFileSystem,
multiModuleChunk: Boolean,
buildFile: File?
): List<KtFile> {
return if (multiModuleChunk) {
// filter out source files from other modules
assert(buildFile != null) { "Compiling multiple modules, but build file is null" }
val (moduleSourceDirs, moduleSourceFiles) =
getBuildFilePaths(buildFile, getSourceFiles())
.mapNotNull(localFileSystem::findFileByPath)
.partition(VirtualFile::isDirectory)
environment.getSourceFiles().filter { file ->
val virtualFile = file.virtualFile
virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir ->
VfsUtilCore.isAncestor(dir, virtualFile, true)
}
}
} else {
environment.getSourceFiles()
}
}
private fun CompilerConfiguration.applyModuleProperties(module: Module, buildFile: File?): CompilerConfiguration {
return copy().apply {
if (buildFile != null) {
fun checkKeyIsNull(key: CompilerConfigurationKey<*>, name: String) {
assert(get(key) == null) { "$name should be null, when buildFile is used" }
}
checkKeyIsNull(JVMConfigurationKeys.OUTPUT_DIRECTORY, "OUTPUT_DIRECTORY")
checkKeyIsNull(JVMConfigurationKeys.OUTPUT_JAR, "OUTPUT_JAR")
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory()))
}
}
}
internal fun compileModules(
environment: KotlinCoreEnvironment,
buildFile: File?,
@@ -84,7 +182,7 @@ object KotlinToJVMBytecodeCompiler {
val projectConfiguration = environment.configuration
if (projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR)) {
val extendedAnalysisMode = projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS)
return FirKotlinToJvmBytecodeCompiler.compileModulesUsingFrontendIR(environment, buildFile, chunk, extendedAnalysisMode)
return compileModulesUsingFrontendIR(environment, buildFile, chunk, extendedAnalysisMode)
}
val result = repeatAnalysisIfNeeded(analyze(environment), environment)
@@ -116,6 +214,40 @@ object KotlinToJVMBytecodeCompiler {
return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName)
}
private fun writeOutputs(
environment: KotlinCoreEnvironment,
projectConfiguration: CompilerConfiguration,
chunk: List<Module>,
outputs: Map<Module, GenerationState>,
mainClassFqName: FqName?
): Boolean {
try {
for ((_, state) in outputs) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
writeOutput(state.configuration, state.factory, mainClassFqName)
}
} finally {
outputs.values.forEach(GenerationState::destroy)
}
if (projectConfiguration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)) {
val singleModule = chunk.singleOrNull()
if (singleModule != null) {
return JavacWrapper.getInstance(environment.project).use {
it.compile(File(singleModule.getOutputDirectory()))
}
} else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " +
"-Xuse-javac option couldn't be used to compile java files"
)
JavacWrapper.getInstance(environment.project).close()
}
}
return true
}
internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List<Module>, buildFile: File? = null) {
for (module in chunk) {
@@ -163,6 +295,162 @@ object KotlinToJVMBytecodeCompiler {
configuration.addAll(JVMConfigurationKeys.MODULES, chunk)
}
private fun compileModulesUsingFrontendIR(
environment: KotlinCoreEnvironment,
buildFile: File?,
chunk: List<Module>,
extendedAnalysisMode: Boolean
): Boolean {
val project = environment.project
val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER)
environment.messageCollector.report(
STRONG_WARNING,
"ATTENTION!\n This build uses in-dev FIR: \n -Xuse-fir"
)
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
val projectConfiguration = environment.configuration
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val outputs = newLinkedHashMapWithExpectedSize<Module, GenerationState>(chunk.size)
val targetIds = environment.configuration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId)
val incrementalComponents = environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS)
for (module in chunk) {
performanceManager?.notifyAnalysisStarted()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val ktFiles = module.getSourceFiles(environment, localFileSystem, chunk.size > 1, buildFile)
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile ->
AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, environment.messageCollector).isHasErrors or errorsFound
}
val moduleConfiguration = projectConfiguration.applyModuleProperties(module, buildFile)
val sourceScope = GlobalSearchScope.filesScope(project, ktFiles.map { it.virtualFile })
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
val librariesScope = ProjectScope.getLibrariesScope(project)
val languageVersionSettings = moduleConfiguration.languageVersionSettings
val session = createSessionWithDependencies(
module,
project,
languageVersionSettings,
sourceScope,
librariesScope,
lookupTracker = environment.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
getPackagePartProvider = { environment.createPackagePartProvider(it) },
getAdditionalModulePackagePartProvider = {
if (targetIds == null || incrementalComponents == null) null
else IncrementalPackagePartProvider(
environment.createPackagePartProvider(it),
targetIds.map(incrementalComponents::getIncrementalCache)
)
}
) {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles)
firAnalyzerFacade.runResolution()
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
AnalyzerWithCompilerReport.reportDiagnostics(
SimpleGenericDiagnostics(firDiagnostics),
environment.messageCollector
)
performanceManager?.notifyAnalysisFinished()
if (syntaxErrors || firDiagnostics.any { it.severity == Severity.ERROR }) {
return false
}
performanceManager?.notifyGenerationStarted()
performanceManager?.notifyIRTranslationStarted()
val extensions = JvmGeneratorExtensionsImpl()
val (moduleFragment, symbolTable, components) = firAnalyzerFacade.convertToIr(extensions)
performanceManager?.notifyIRTranslationFinished()
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
val codegenFactory = JvmIrCodegenFactory(moduleConfiguration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases))
// Create and initialize the module and its dependencies
val container = TopDownAnalyzerFacadeForJVM.createContainer(
project, ktFiles, NoScopeRecordCliBindingTrace(), environment.configuration, environment::createPackagePartProvider,
::FileBasedDeclarationProviderFactory, CompilerEnvironment,
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles), emptyList()
)
val generationState = GenerationState.Builder(
environment.project, ClassBuilderFactories.BINARIES,
container.get<ModuleDescriptor>(), dummyBindingContext, ktFiles,
moduleConfiguration
).codegenFactory(
codegenFactory
).withModule(
module
).onIndependentPartCompilationEnd(
createOutputFilesFlushingCallbackIfPossible(moduleConfiguration)
).isIrBackend(
true
).jvmBackendClassResolver(
FirJvmBackendClassResolver(components)
).build()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
performanceManager?.notifyIRLoweringStarted()
generationState.beforeCompile()
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, extensions, FirJvmBackendExtension(session, components)
) {
performanceManager?.notifyIRLoweringFinished()
performanceManager?.notifyIRGenerationStarted()
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
AnalyzerWithCompilerReport.reportDiagnostics(
FilteredJvmDiagnostics(
generationState.collectedExtraJvmDiagnostics,
dummyBindingContext.diagnostics
),
environment.messageCollector
)
performanceManager?.notifyIRGenerationFinished()
performanceManager?.notifyGenerationFinished()
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
outputs[module] = generationState
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
Disposer.dispose(environment.project)
}
val mainClassFqName: FqName? =
if (chunk.size == 1 && projectConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null)
TODO(".jar output is not yet supported for -Xuse-fir: KT-42868")
else null
return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName)
}
private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> =
if (buildFile == null) sourceFilePaths
else sourceFilePaths.map { path ->
(File(path).takeIf(File::isAbsolute) ?: buildFile.resolveSibling(path)).absolutePath
}
fun compileBunchOfSources(environment: KotlinCoreEnvironment): Boolean {
val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project)
@@ -289,6 +577,15 @@ object KotlinToJVMBytecodeCompiler {
override fun toString() = "All files under: $directories"
}
private fun GenerationState.Builder.withModule(module: Module?) =
apply {
if (module != null) {
targetId(TargetId(module))
moduleName(module.getModuleName())
outDirectory(File(module.getOutputDirectory()))
}
}
private fun generate(
environment: KotlinCoreEnvironment,
configuration: CompilerConfiguration,
@@ -335,4 +632,7 @@ object KotlinToJVMBytecodeCompiler {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
return generationState
}
private val KotlinCoreEnvironment.messageCollector: MessageCollector
get() = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
}

View File

@@ -209,8 +209,7 @@ object TopDownAnalyzerFacadeForJVM {
moduleClassResolver.compiledCodeResolver.packageFragmentProvider,
dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>(),
dependenciesContainer.get<OptionalAnnotationPackageFragmentProvider>()
),
"CompositeProvider@TopDownAnalyzerForJvm for dependencies ${dependenciesContext.module}"
)
)
)
dependenciesContext.module
@@ -284,8 +283,7 @@ object TopDownAnalyzerFacadeForJVM {
listOf(
container.get<KotlinCodeAnalyzer>().packageFragmentProvider,
container.get<OptionalAnnotationPackageFragmentProvider>()
) + additionalProviders,
"CompositeProvider@TopDownAnalzyerForJvm for $module"
) + additionalProviders
)
)

View File

@@ -1,150 +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.cli.jvm.compiler
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileSystem
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.common.output.writeAll
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
fun Module.getSourceFiles(
environment: KotlinCoreEnvironment,
localFileSystem: VirtualFileSystem,
multiModuleChunk: Boolean,
buildFile: File?
): List<KtFile> {
return if (multiModuleChunk) {
// filter out source files from other modules
assert(buildFile != null) { "Compiling multiple modules, but build file is null" }
val (moduleSourceDirs, moduleSourceFiles) =
getBuildFilePaths(buildFile, getSourceFiles())
.mapNotNull(localFileSystem::findFileByPath)
.partition(VirtualFile::isDirectory)
environment.getSourceFiles().filter { file ->
val virtualFile = file.virtualFile
virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir ->
VfsUtilCore.isAncestor(dir, virtualFile, true)
}
}
} else {
environment.getSourceFiles()
}
}
fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> =
if (buildFile == null) sourceFilePaths
else sourceFilePaths.map { path ->
(File(path).takeIf(File::isAbsolute) ?: buildFile.resolveSibling(path)).absolutePath
}
fun GenerationState.Builder.withModule(module: Module?) =
apply {
if (module != null) {
targetId(TargetId(module))
moduleName(module.getModuleName())
outDirectory(File(module.getOutputDirectory()))
}
}
fun createOutputFilesFlushingCallbackIfPossible(configuration: CompilerConfiguration): GenerationStateEventCallback {
if (configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) == null) {
return GenerationStateEventCallback.DO_NOTHING
}
return GenerationStateEventCallback { state ->
val currentOutput = SimpleOutputFileCollection(state.factory.currentOutput)
writeOutput(configuration, currentOutput, null)
if (!configuration.get(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false)) {
state.factory.releaseGeneratedOutput()
}
}
}
fun writeOutput(
configuration: CompilerConfiguration,
outputFiles: OutputFileCollection,
mainClassFqName: FqName?
) {
val reportOutputFiles = configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
val jarPath = configuration.get(JVMConfigurationKeys.OUTPUT_JAR)
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
if (jarPath != null) {
val includeRuntime = configuration.get(JVMConfigurationKeys.INCLUDE_RUNTIME, false)
val noReflect = configuration.get(JVMConfigurationKeys.NO_REFLECT, false)
val resetJarTimestamps = !configuration.get(JVMConfigurationKeys.NO_RESET_JAR_TIMESTAMPS, false)
CompileEnvironmentUtil.writeToJar(
jarPath,
includeRuntime,
noReflect,
resetJarTimestamps,
mainClassFqName,
outputFiles,
messageCollector
)
if (reportOutputFiles) {
val message = OutputMessageUtil.formatOutputMessage(outputFiles.asList().flatMap { it.sourceFiles }.distinct(), jarPath)
messageCollector.report(CompilerMessageSeverity.OUTPUT, message)
}
return
}
val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) ?: File(".")
outputFiles.writeAll(outputDir, messageCollector, reportOutputFiles)
}
fun writeOutputs(
environment: KotlinCoreEnvironment,
projectConfiguration: CompilerConfiguration,
chunk: List<Module>,
outputs: Map<Module, GenerationState>,
mainClassFqName: FqName?
): Boolean {
try {
for ((_, state) in outputs) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
writeOutput(state.configuration, state.factory, mainClassFqName)
}
} finally {
outputs.values.forEach(GenerationState::destroy)
}
if (projectConfiguration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)) {
val singleModule = chunk.singleOrNull()
if (singleModule != null) {
return JavacWrapper.getInstance(environment.project).use {
it.compile(File(singleModule.getOutputDirectory()))
}
} else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
CompilerMessageSeverity.WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " +
"-Xuse-javac option couldn't be used to compile java files"
)
JavacWrapper.getInstance(environment.project).close()
}
}
return true
}

View File

@@ -15,13 +15,10 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.extensions.PreprocessedFileCreator
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import java.io.File
@@ -82,22 +79,4 @@ fun createSourceFilesFromSourceRoots(
}
return result
}
val KotlinCoreEnvironment.messageCollector: MessageCollector
get() = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
fun CompilerConfiguration.applyModuleProperties(module: Module, buildFile: File?): CompilerConfiguration {
return copy().apply {
if (buildFile != null) {
fun checkKeyIsNull(key: CompilerConfigurationKey<*>, name: String) {
assert(get(key) == null) { "$name should be null, when buildFile is used" }
}
checkKeyIsNull(JVMConfigurationKeys.OUTPUT_DIRECTORY, "OUTPUT_DIRECTORY")
checkKeyIsNull(JVMConfigurationKeys.OUTPUT_JAR, "OUTPUT_JAR")
put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory()))
}
}
}
}

View File

@@ -49,9 +49,6 @@ fun CompilerConfiguration.addJvmSdkRoots(files: List<File>) {
val CompilerConfiguration.jvmClasspathRoots: List<File>
get() = getList(CLIConfigurationKeys.CONTENT_ROOTS).filterIsInstance<JvmClasspathRoot>().map(JvmContentRoot::file)
val CompilerConfiguration.jvmModularRoots: List<File>
get() = getList(CLIConfigurationKeys.CONTENT_ROOTS).filterIsInstance<JvmModulePathRoot>().map(JvmContentRoot::file)
@JvmOverloads
fun CompilerConfiguration.addJavaSourceRoot(file: File, packagePrefix: String? = null) {
add(CLIConfigurationKeys.CONTENT_ROOTS, JavaSourceRoot(file, packagePrefix))

View File

@@ -45,7 +45,6 @@ data class JavaRoot(val file: VirtualFile, val type: RootType, val prefixFqName:
companion object RootTypes {
val OnlyBinary: Set<RootType> = EnumSet.of(RootType.BINARY)
val OnlySource: Set<RootType> = EnumSet.of(RootType.SOURCE)
val SourceAndBinary: Set<RootType> = EnumSet.of(RootType.BINARY, RootType.SOURCE)
}
}

View File

@@ -16,25 +16,16 @@
package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
class CliJavaModuleFinder(
jrtFileSystemRoot: VirtualFile?,
private val javaFileManager: KotlinCliJavaFileManager,
project: Project
) : JavaModuleFinder {
class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
private val modulesRoot = jrtFileSystemRoot?.findChild("modules")
private val userModules = linkedMapOf<String, JavaModule>()
private val allScope = GlobalSearchScope.allScope(project)
fun addUserModule(module: JavaModule) {
userModules.putIfAbsent(module.name, module)
}
@@ -50,7 +41,7 @@ class CliJavaModuleFinder(
private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null
val moduleInfo = JavaModuleInfo.read(file, javaFileManager, allScope) ?: return null
val moduleInfo = JavaModuleInfo.read(file) ?: return null
return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(moduleRoot, isBinary = true)), file)
}
}

View File

@@ -18,24 +18,18 @@ package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import java.util.concurrent.ConcurrentHashMap
class CliJavaModuleResolver(
private val moduleGraph: JavaModuleGraph,
private val userModules: List<JavaModule>,
private val systemModules: List<JavaModule.Explicit>,
private val project: Project
private val systemModules: List<JavaModule.Explicit>
) : JavaModuleResolver {
init {
assert(userModules.count(JavaModule::isSourceModule) <= 1) {
@@ -43,14 +37,6 @@ class CliJavaModuleResolver(
}
}
private val virtualFileFinder by lazy { VirtualFileFinder.getInstance(project) }
override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List<JavaAnnotation>? {
val virtualFile = virtualFileFinder.findSourceOrBinaryVirtualFile(classId) ?: return null
return (findJavaModule(virtualFile) as? JavaModule.Explicit)?.moduleInfo?.annotations
}
private val sourceModule: JavaModule? = userModules.firstOrNull(JavaModule::isSourceModule)
private fun findJavaModule(file: VirtualFile): JavaModule? {
@@ -91,8 +77,4 @@ class CliJavaModuleResolver(
return null
}
companion object {
private const val MODULE_ANNOTATIONS_CACHE_SIZE = 10000
}
}

View File

@@ -101,11 +101,7 @@ object KotlinCompilerClient {
fun CompileService.leaseImpl(): CompileServiceSession? {
// the newJVMOptions could be checked here for additional parameters, if needed
registerClient(clientAliveFlagFile.absolutePath)
val javaExecutablePath = compilerId.javaExecutable?.absolutePath ?: "'user jvm'"
reportingTargets.report(
DaemonReportCategory.DEBUG,
"connected to the daemon. Daemon is using following 'java' executable to run itself: $javaExecutablePath"
)
reportingTargets.report(DaemonReportCategory.DEBUG, "connected to the daemon")
if (!leaseSession) return CompileServiceSession(this, CompileService.NO_SESSION)

View File

@@ -13,13 +13,13 @@ plugins {
dependencies {
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
testApi(intellijDep())
testApi(projectTests(":compiler:test-infrastructure"))
testApi(projectTests(":compiler:test-infrastructure-utils"))
testApi(projectTests(":compiler:tests-compiler-utils"))
testApi(projectTests(":compiler:tests-common-new"))
testApi(project(":compiler:cli"))
testApi(project(":compiler:fir:checkers"))
testApi(project(":compiler:fir:checkers:checkers.jvm"))
testApi(project(":compiler:fir:fir-serialization"))
testApi(project(":compiler:fir:entrypoint"))
testApi(project(":compiler:frontend"))

View File

@@ -20,7 +20,6 @@ dependencies {
testCompileOnly(project(":kotlin-test:kotlin-test-junit"))
testApi(projectTests(":compiler:tests-common"))
testApi(project(":compiler:fir:checkers"))
testApi(project(":compiler:fir:checkers:checkers.jvm"))
testApi(project(":compiler:fir:entrypoint"))
testApi(project(":compiler:frontend"))

View File

@@ -561,11 +561,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/integerLiteralTypes.kt");
}
@TestMetadata("integerOverloads.kt")
public void testIntegerOverloads() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/integerOverloads.kt");
}
@TestMetadata("invoke.kt")
public void testInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/invoke.kt");
@@ -975,11 +970,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
public void testConstValWithGetterOrDelegate() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/constVal/constValWithGetterOrDelegate.kt");
}
@TestMetadata("constValWithTypealiasType.kt")
public void testConstValWithTypealiasType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/constVal/constValWithTypealiasType.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/constructors")
@@ -2416,11 +2406,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/inference/definitelyNotNullIntersectionType.kt");
}
@TestMetadata("elvisAndUnit.kt")
public void testElvisAndUnit() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/elvisAndUnit.kt");
}
@TestMetadata("extensionCallableReferences.kt")
public void testExtensionCallableReferences() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
@@ -2490,11 +2475,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
public void testTypeDepthForTypeAlias() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/typeDepthForTypeAlias.kt");
}
@TestMetadata("unitUpperBound.kt")
public void testUnitUpperBound() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/unitUpperBound.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/inlineClasses")
@@ -2809,11 +2789,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/problems/secondaryConstructorCfg.kt");
}
@TestMetadata("symbolsAndDescriptors.kt")
public void testSymbolsAndDescriptors() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/symbolsAndDescriptors.kt");
}
@TestMetadata("transform.kt")
public void testTransform() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/transform.kt");
@@ -3465,11 +3440,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
public void testCastToBareType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/types/castToBareType.kt");
}
@TestMetadata("typeAliasInArguments.kt")
public void testTypeAliasInArguments() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/types/typeAliasInArguments.kt");
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.ObsoleteTestInfrastructure
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -31,7 +30,6 @@ abstract class AbstractFirLoadCompiledKotlin : AbstractFirLoadBinariesTest() {
return createEnvironmentWithMockJdk(ConfigurationKind.JDK_NO_RUNTIME)
}
@OptIn(ObsoleteTestInfrastructure::class)
fun doTest(path: String) {
val moduleDescriptor = compileKtFileToTmpDir(path)

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.ObsoleteTestInfrastructure
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.serialization.builtins.BuiltinsTestUtils
import org.jetbrains.kotlin.test.ConfigurationKind
@@ -17,7 +16,6 @@ class BuiltInsDeserializationForFirTestCase : AbstractFirLoadBinariesTest() {
return createEnvironmentWithJdk(ConfigurationKind.ALL, TestJdkKind.FULL_JDK)
}
@OptIn(ObsoleteTestInfrastructure::class)
fun testBuiltInPackagesContent() {
val moduleDescriptor = BuiltinsTestUtils.compileBuiltinsModule(environment)
val session = createSessionForTests(environment, GlobalSearchScope.allScope(project))

View File

@@ -16,7 +16,6 @@ import com.intellij.psi.PsiPackageStatement
import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.ObsoleteTestInfrastructure
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
@@ -83,7 +82,6 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
}
}
@OptIn(ObsoleteTestInfrastructure::class)
fun doTest(path: String) {
val javaFile = File(path)
val javaLines = javaFile.readLines()

View File

@@ -81,7 +81,7 @@ public final class CharRange : R|kotlin/ranges/CharProgression|, R|kotlin/ranges
}
public abstract interface ClosedRange<T : R|kotlin/Comparable<T>|> : R|kotlin/Any| {
public abstract interface ClosedRange<T> : R|kotlin/Any| {
public open operator fun contains(value: R|T|): R|kotlin/Boolean|
public open fun isEmpty(): R|kotlin/Boolean|

View File

@@ -12,9 +12,9 @@ public final fun doubleArrayOf(vararg elements: R|kotlin/DoubleArray|): R|kotlin
public final inline fun <reified T> emptyArray(): R|kotlin/Array<T>|
@R|kotlin/SinceKotlin|(version = String(1.1)) public final inline fun <reified T : R|kotlin/Enum<T>|> enumValueOf(name: R|kotlin/String|): R|T|
@R|kotlin/SinceKotlin|(version = String(1.1)) public final inline fun <reified T> enumValueOf(name: R|kotlin/String|): R|T|
@R|kotlin/SinceKotlin|(version = String(1.1)) public final inline fun <reified T : R|kotlin/Enum<T>|> enumValues(): R|kotlin/Array<T>|
@R|kotlin/SinceKotlin|(version = String(1.1)) public final inline fun <reified T> enumValues(): R|kotlin/Array<T>|
public final fun floatArrayOf(vararg elements: R|kotlin/FloatArray|): R|kotlin/FloatArray|
@@ -529,7 +529,7 @@ public final class DoubleArray : R|kotlin/Any|, R|kotlin/Cloneable|, R|java/io/S
}
public abstract class Enum<E : R|kotlin/Enum<E>|> : R|kotlin/Comparable<E>|, R|java/io/Serializable| {
public abstract class Enum<E> : R|kotlin/Comparable<E>|, R|java/io/Serializable| {
public final companion object Companion : R|kotlin/Any| {
private constructor(): R|kotlin/Enum.Companion|
@@ -551,7 +551,7 @@ public abstract class Enum<E : R|kotlin/Enum<E>|> : R|kotlin/Comparable<E>|, R|j
public final val ordinal: R|kotlin/Int|
public get(): R|kotlin/Int|
public constructor<E : R|kotlin/Enum<E>|>(name: R|kotlin/String| = STUB, ordinal: R|kotlin/Int| = STUB): R|kotlin/Enum<E>|
public constructor<E>(name: R|kotlin/String| = STUB, ordinal: R|kotlin/Int| = STUB): R|kotlin/Enum<E>|
}

View File

@@ -1,17 +1,17 @@
FILE: annotationUsedAsAnnotationArgument.kt
@R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final annotation class Ann : R|kotlin/Annotation| {
public final annotation class Ann : R|kotlin/Annotation| {
public constructor(): R|Ann| {
super<R|kotlin/Any|>()
}
}
@R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final annotation class Ann2 : R|kotlin/Annotation| {
public final annotation class Ann2 : R|kotlin/Annotation| {
public constructor(): R|Ann2| {
super<R|kotlin/Any|>()
}
}
@R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final annotation class Ann3 : R|kotlin/Annotation| {
public final annotation class Ann3 : R|kotlin/Annotation| {
public constructor(arg: R|kotlin/Int|, s: R|kotlin/String|): R|Ann3| {
super<R|kotlin/Any|>()
}

View File

@@ -1,19 +1,11 @@
// WITH_RUNTIME
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class Ann
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class Ann2
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class Ann3(val arg: Int, val s: String)
<!WRONG_ANNOTATION_TARGET!>@Ann3(
@Ann3(
<!ANNOTATION_USED_AS_ANNOTATION_ARGUMENT!>@Ann3(
<!ANNOTATION_USED_AS_ANNOTATION_ARGUMENT!>@Ann<!> 5, ""
)<!> <!ANNOTATION_USED_AS_ANNOTATION_ARGUMENT!>@Ann2<!> 1, ""
)<!> val a = 0
) val a = 0

View File

@@ -37,8 +37,8 @@ FILE: destructuring.kt
}
)
R|/foo1|(<L> = foo1@fun <anonymous>(<destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
lval x: R|kotlin/String| = R|<local>/<destruct>|.<CS errors: /C.component1>#()
lval y: R|kotlin/Int| = R|<local>/<destruct>|.<CS errors: /C.component2>#()
lval x: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component1|()
lval y: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component2|()
<Inapplicable(INAPPLICABLE): /C.C>#(R|<local>/x|, R|<local>/y|)
}
)
@@ -59,10 +59,10 @@ FILE: destructuring.kt
}
)
R|/foo2|(<L> = foo2@fun <anonymous>(<destruct>: R|C|, <destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
lval x: R|kotlin/String| = R|<local>/<destruct>|.<CS errors: /C.component1>#()
lval y: R|kotlin/Int| = R|<local>/<destruct>|.<CS errors: /C.component2>#()
lval z: R|kotlin/String| = R|<local>/<destruct>|.<CS errors: /C.component1>#()
lval w: R|kotlin/Int| = R|<local>/<destruct>|.<CS errors: /C.component2>#()
lval x: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component1|()
lval y: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component2|()
lval z: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component1|()
lval w: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component2|()
<Inapplicable(INAPPLICABLE): /C.C>#(R|<local>/x|.R|kotlin/String.plus|(R|<local>/z|), R|<local>/y|.R|kotlin/Int.plus|(R|<local>/w|))
}
)

View File

@@ -1,5 +1,5 @@
fun test(
f: String.() -> Int = { length }
val f: String.() -> Int = { length }
): Int {
return "".f()
}

View File

@@ -1,21 +0,0 @@
FILE: x.kt
public final fun f(x: R|kotlin/Byte|): R|kotlin/Unit| {
}
public final fun f(x: R|kotlin/Int|): R|kotlin/Unit| {
}
public final fun f(x: R|kotlin/Long|): R|kotlin/Unit| {
}
public final fun g(x: R|kotlin/Byte?|): R|kotlin/Unit| {
}
public final fun g(x: R|kotlin/Int?|): R|kotlin/Unit| {
}
public final fun g(x: R|kotlin/Long?|): R|kotlin/Unit| {
}
public final fun main(): R|kotlin/Unit| {
Q|J|.R|/J.f|(Int(123))
Q|J|.R|/J.f|(Long(123123123123))
R|/f|(Int(123))
R|/f|(Long(123123123123))
R|/g|(Int(123))
R|/g|(Long(123123123123))
}

View File

@@ -1,24 +0,0 @@
// FILE: J.java
public class J {
public static fun f(Byte x) {}
public static fun f(Integer x) {}
public static fun f(Long x) {}
}
// FILE: x.kt
fun f(x: Byte) {}
fun f(x: Int) {}
fun f(x: Long) {}
fun g(x: Byte?) {}
fun g(x: Int?) {}
fun g(x: Long?) {}
fun main() {
J.f(123)
J.f(123123123123)
f(123)
f(123123123123)
g(123)
g(123123123123)
}

View File

@@ -7,7 +7,7 @@ FILE: main.kt
public abstract interface PsiClass : R|kotlin/Any| {
}
public final fun test(): R|kotlin/Unit| {
lval processor: R|AdapterProcessor<ft<PsiMethod, PsiMethod?>, ft<PsiClass, PsiClass?>>| = R|/AdapterProcessor.AdapterProcessor|<R|ft<PsiMethod, PsiMethod?>|, R|ft<PsiClass, PsiClass?>|>(R|/Function|<R|ft<PsiMethod, PsiMethod?>|, R|ft<PsiClass, PsiClass?>|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|ft<PsiClass, PsiClass?>| <inline=NoInline> {
lval processor: R|AdapterProcessor<ft<PsiMethod, PsiMethod?>, ft<PsiClass, PsiClass?>>| = R|/AdapterProcessor.AdapterProcessor|<R|ft<PsiMethod, PsiMethod?>|, R|ft<PsiClass, PsiClass?>|>(R|/Function|<R|ft<PsiMethod, PsiMethod?>|, R|PsiClass?|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|PsiClass?| <inline=NoInline> {
^ R|<local>/method|?.{ $subj$.R|/PsiMethod.containingClass| }
}
))

View File

@@ -10,7 +10,7 @@ FILE: A.kt
}
FILE: main.kt
public final fun test_1(): R|kotlin/Unit| {
lval a: <ERROR TYPE REF: Unresolved name: A> = <Unresolved name: A>#()
lval a: R|ERROR CLASS: Unresolved name: A| = <Unresolved name: A>#()
lval b: R|foo/A| = R|foo/A.A|()
lval c: R|foo/A| = <Unresolved name: A>#()
}

View File

@@ -18,7 +18,7 @@ FILE: cast.kt
}
public get(): R|(kotlin/String) -> kotlin/Boolean|
public final val hError: R|(ERROR CLASS: No type for parameter) -> kotlin/Boolean| = fun <anonymous>(_: <ERROR TYPE REF: No type for parameter>): R|kotlin/Boolean| <inline=Unknown> {
public final val hError: R|(ERROR CLASS: No type for parameter) -> kotlin/Boolean| = fun <anonymous>(_: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| <inline=Unknown> {
^ Boolean(true)
}

View File

@@ -9,15 +9,15 @@ fun <T : Throwable> test() {
try {} catch (<!TYPE_PARAMETER_IN_CATCH_CLAUSE!>e: T<!>) {}
try {} catch (<!THROWABLE_TYPE_MISMATCH!>e: () -> Int<!>) {}
try {} catch (<!TYPE_MISMATCH!>e: () -> Int<!>) {}
try {} catch (<!THROWABLE_TYPE_MISMATCH!>e: StringType<!>) {}
try {} catch (<!TYPE_MISMATCH!>e: StringType<!>) {}
try {} catch (<!CATCH_PARAMETER_WITH_DEFAULT_VALUE, THROWABLE_TYPE_MISMATCH!>e: Int = 5<!>) {}
try {} catch (<!CATCH_PARAMETER_WITH_DEFAULT_VALUE, TYPE_MISMATCH!>e: Int = 5<!>) {}
try {} catch (e: Throwable) {}
}
inline fun <reified T> anotherTest() {
try {} catch (<!REIFIED_TYPE_IN_CATCH_CLAUSE, THROWABLE_TYPE_MISMATCH!>e: T<!>) {}
try {} catch (<!REIFIED_TYPE_IN_CATCH_CLAUSE, TYPE_MISMATCH!>e: T<!>) {}
}

View File

@@ -13,6 +13,6 @@ interface B
fun test_2(x: Any?) {
if (x is A && x is B) {
<!USELESS_IS_CHECK!>x is A<!>
x is A
}
}

View File

@@ -1,4 +0,0 @@
FILE: constValWithTypealiasType.kt
public final typealias Foo = R|kotlin/Int|
public final const val x: R|Foo| = Int(10)
public get(): R|Foo|

View File

@@ -1,3 +0,0 @@
typealias Foo = Int
const val x: Foo = 10

View File

@@ -26,7 +26,7 @@ FILE: kt41982.kt
super<R|DelegateProvider<kotlin/Any>|>()
}
public final var start: R|kotlin/Long|by this@R|/Test|.R|/long|<R|Test|, R|Test|>(<L> = long@fun <anonymous>(): R|kotlin/Long?| <inline=NoInline> {
public final var start: R|kotlin/Long|by this@R|/Test|.R|/long|<R|Test?|, R|Test?|>(<L> = long@fun <anonymous>(): R|kotlin/Long?| <inline=NoInline> {
^ Long(0)
}
)

View File

@@ -1,5 +1,5 @@
FILE: classInSupertypeForEnum.kt
public open class A : R|kotlin/Any| {
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}

View File

@@ -1,5 +1,5 @@
open class A
class A
interface C
enum class B : C, <!CLASS_IN_SUPERTYPE_FOR_ENUM!>A<!>(), <!MANY_CLASSES_IN_SUPERTYPE_LIST!>Any<!>()
enum class B : C, <!CLASS_IN_SUPERTYPE_FOR_ENUM!>A<!>(), Any()

View File

@@ -1,5 +1,3 @@
// FIR_IDE_IGNORE
<!CONFLICTING_OVERLOADS!>fun test(x: Int)<!> {}
<!CONFLICTING_OVERLOADS!>fun test(y: Int)<!> {}
@@ -18,7 +16,7 @@ fun test(z: Int, c: Char) {}
}<!>
<!REDECLARATION!>class B : <!FINAL_SUPERTYPE, SUPERTYPE_NOT_INITIALIZED!>A<!> {
<!REDECLARATION!>class B : <!SUPERTYPE_NOT_INITIALIZED!>A<!> {
<!CONFLICTING_OVERLOADS!>override fun rest(s: String)<!> {}
<!CONFLICTING_OVERLOADS!>fun rest(s: String)<!> {}

View File

@@ -3,5 +3,5 @@ interface <!CONSTRUCTOR_IN_INTERFACE!>A(val s: String)<!>
interface <!CONSTRUCTOR_IN_INTERFACE!>B constructor(val s: String)<!>
interface C {
<!CONSTRUCTOR_IN_INTERFACE!>constructor(s: String)<!> {}
<!CONSTRUCTOR_IN_INTERFACE!>constructor(val s: String)<!> {}
}

View File

@@ -125,7 +125,7 @@ FILE: cyclicConstructorDelegationCall.kt
}
}
public open class M : R|kotlin/Any| {
public final class M : R|kotlin/Any| {
public constructor(m: R|kotlin/Int|): R|M| {
super<R|kotlin/Any|>()
}

View File

@@ -58,7 +58,7 @@ class K(x: Int) {
constructor() : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>() {}
}
open class M {
class M {
constructor(m: Int)
}

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