diff options
author | Jim Sproch <jsproch@google.com> | 2020-07-16 17:13:03 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-07-16 17:13:03 +0000 |
commit | f62e107f6d6faeebd8d6a580eb3a070a29bd4490 (patch) | |
tree | 0bfdeb43ac06dcaf0f358e82998a323ae4a87ec9 | |
parent | 3110d0f59f9e8da269878a51c759bf61c33f9dc2 (diff) | |
parent | d9c8ed2109a21834c0aa507362eb968c9664c7d4 (diff) | |
download | kotlin-f62e107f6d6faeebd8d6a580eb3a070a29bd4490.tar.gz |
Merge "Cleanup obsolete divergences from R4A history, rebase." into compose-dev
319 files changed, 4927 insertions, 1262 deletions
diff --git a/ChangeLog.md b/ChangeLog.md index 61ebd7db129..59e456444f3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,504 @@ # CHANGELOG +## 1.4-M3 + +### Compiler + +#### New Features + +- [`KT-23575`](https://youtrack.jetbrains.com/issue/KT-23575) Deprecate with replacement and SinceKotlin +- [`KT-38652`](https://youtrack.jetbrains.com/issue/KT-38652) Do not generate optional annotations to class files on JVM +- [`KT-38777`](https://youtrack.jetbrains.com/issue/KT-38777) Hide Throwable.addSuppressed member and prefer extension instead + +#### Performance Improvements + +- [`KT-38489`](https://youtrack.jetbrains.com/issue/KT-38489) Compilation of kotlin html DSL increasingly slow +- [`KT-28650`](https://youtrack.jetbrains.com/issue/KT-28650) Type inference for argument type is very slow if several interfaces with a type parameter is used as an upper bound of a type parameter + +#### Fixes + +- [`KT-15971`](https://youtrack.jetbrains.com/issue/KT-15971) Incorrect bytecode generated when inheriting default arguments not from the first supertype +- [`KT-25290`](https://youtrack.jetbrains.com/issue/KT-25290) NI: "AssertionError: If original type is SAM type, then candidate should have same type constructor" on out projection of Java class +- [`KT-28672`](https://youtrack.jetbrains.com/issue/KT-28672) Contracts on calls with implicit receivers +- [`KT-30279`](https://youtrack.jetbrains.com/issue/KT-30279) Support non-reified type parameters in typeOf +- [`KT-31908`](https://youtrack.jetbrains.com/issue/KT-31908) NI: CCE on passing lambda to function which accepts vararg SAM interface +- [`KT-32156`](https://youtrack.jetbrains.com/issue/KT-32156) New inference issue with generics +- [`KT-32229`](https://youtrack.jetbrains.com/issue/KT-32229) New inference algorithm not taking into account the upper bound class +- [`KT-33455`](https://youtrack.jetbrains.com/issue/KT-33455) Override equals/hashCode in functional interface wrappers +- [`KT-34902`](https://youtrack.jetbrains.com/issue/KT-34902) AnalyzerException: Argument 1: expected I, but found R for unsigned types in generic data class +- [`KT-35075`](https://youtrack.jetbrains.com/issue/KT-35075) AssertionError: "No resolved call for ..." with conditional function references +- [`KT-35468`](https://youtrack.jetbrains.com/issue/KT-35468) Overcome ambiguity between typealias kotlin.Throws and the aliased type kotlin.jvm.Throws +- [`KT-35494`](https://youtrack.jetbrains.com/issue/KT-35494) NI: Multiple duplicate error diagnostics (in IDE popup) with NULL_FOR_NONNULL_TYPE +- [`KT-35681`](https://youtrack.jetbrains.com/issue/KT-35681) Wrong common supertype between raw and integer literal type leads to unsound code +- [`KT-35937`](https://youtrack.jetbrains.com/issue/KT-35937) Error "Declaration has several compatible actuals" on incremental build +- [`KT-36013`](https://youtrack.jetbrains.com/issue/KT-36013) Functional interface conversion not happens on a value of functional type with smart cast to a relevant functional type +- [`KT-36045`](https://youtrack.jetbrains.com/issue/KT-36045) Do not depend on the order of lambda arguments to coerce result to `Unit` +- [`KT-36448`](https://youtrack.jetbrains.com/issue/KT-36448) NI: fix tests after enabling NI in the compiler +- [`KT-36706`](https://youtrack.jetbrains.com/issue/KT-36706) Prohibit functional interface constructor references +- [`KT-36969`](https://youtrack.jetbrains.com/issue/KT-36969) Generate @NotNull on instance parameters of Interface$DefaultImpls methods +- [`KT-37058`](https://youtrack.jetbrains.com/issue/KT-37058) Incorrect overload resolution ambiguity on callable reference in a conditional expression with new inference +- [`KT-37120`](https://youtrack.jetbrains.com/issue/KT-37120) [FIR] False UNRESOLVED_REFERENCE for public and protected member functions and properties which are declared in object inner class +- [`KT-37149`](https://youtrack.jetbrains.com/issue/KT-37149) Conversion when generic specified by type argument of SAM type +- [`KT-37249`](https://youtrack.jetbrains.com/issue/KT-37249) false TYPE_MISMATCH when When-expression branches have try-catch blocks +- [`KT-37341`](https://youtrack.jetbrains.com/issue/KT-37341) NI: Type mismatch with combination of lambda and function reference +- [`KT-37436`](https://youtrack.jetbrains.com/issue/KT-37436) AME: "Receiver class does not define or inherit an implementation of the resolved method" in runtime on usage of non-abstract method of fun interface +- [`KT-37510`](https://youtrack.jetbrains.com/issue/KT-37510) NI infers `java.lang.Void` from the expression in a lazy property delegate and throws ClassCastException at runtime +- [`KT-37541`](https://youtrack.jetbrains.com/issue/KT-37541) SAM conversion with fun interface without a function fails on compiling and IDE analysis in SamAdapterFunctionsScope.getSamConstructor() +- [`KT-37574`](https://youtrack.jetbrains.com/issue/KT-37574) NI: Type mismatch with Kotlin object extending functional type passed as @FunctionalInterface to Java +- [`KT-37630`](https://youtrack.jetbrains.com/issue/KT-37630) NI: ILT suitability in a call is broken if there are CST calculation and calling function's type parameters +- [`KT-37665`](https://youtrack.jetbrains.com/issue/KT-37665) NI: applicability error due to implicitly inferred Nothing for returning T with expected type +- [`KT-37712`](https://youtrack.jetbrains.com/issue/KT-37712) No extension receiver in functional interface created with lambda +- [`KT-37715`](https://youtrack.jetbrains.com/issue/KT-37715) NI: VerifyError: Bad type on operand stack with varargs generic value when type is inferred +- [`KT-37721`](https://youtrack.jetbrains.com/issue/KT-37721) NI: Function reference with vararg parameter treated as array and missing default parameter is rejected +- [`KT-37887`](https://youtrack.jetbrains.com/issue/KT-37887) NI: Smart casting for Map doesn't work if the variable is already "smart casted" +- [`KT-37914`](https://youtrack.jetbrains.com/issue/KT-37914) NI: broken inference for a casting to subtype function within the common constraint system with this subtype +- [`KT-37952`](https://youtrack.jetbrains.com/issue/KT-37952) NI: improve lambdas completion through separation the lambdas analysis into several steps +- [`KT-38069`](https://youtrack.jetbrains.com/issue/KT-38069) Callable reference adaptation should have dependency on API version 1.4 +- [`KT-38143`](https://youtrack.jetbrains.com/issue/KT-38143) New type inference fails when calling extension function defined on generic type with type arguments nested too deep +- [`KT-38156`](https://youtrack.jetbrains.com/issue/KT-38156) FIR Metadata generation +- [`KT-38197`](https://youtrack.jetbrains.com/issue/KT-38197) java.lang.OutOfMemoryError: Java heap space: failed reallocation of scalar replaced objects +- [`KT-38259`](https://youtrack.jetbrains.com/issue/KT-38259) NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER for provideDelegate +- [`KT-38337`](https://youtrack.jetbrains.com/issue/KT-38337) Map delegation fails for inline classes +- [`KT-38401`](https://youtrack.jetbrains.com/issue/KT-38401) FIR: protected effective visibility is handled unprecisely +- [`KT-38416`](https://youtrack.jetbrains.com/issue/KT-38416) FIR: infinite loop in BB coroutine test 'overrideDefaultArgument.kt' +- [`KT-38432`](https://youtrack.jetbrains.com/issue/KT-38432) FIR: incorrect effective visibility in anonymous object +- [`KT-38434`](https://youtrack.jetbrains.com/issue/KT-38434) Implement resolution of suspend-conversion on FE only, but give error if suspend conversion is called +- [`KT-38437`](https://youtrack.jetbrains.com/issue/KT-38437) [FIR] String(CharArray) is resolved to java.lang.String constructor instead of kotlin.text.String pseudo-constructor +- [`KT-38439`](https://youtrack.jetbrains.com/issue/KT-38439) NI: anonymous functions without receiver is allowed if there is an expected type with receiver +- [`KT-38473`](https://youtrack.jetbrains.com/issue/KT-38473) FIR: ConeIntegerLiteralType in signature +- [`KT-38537`](https://youtrack.jetbrains.com/issue/KT-38537) IllegalArgumentException: "marginPrefix must be non-blank string" with raw strings and space as margin prefix in trimMargin() call +- [`KT-38604`](https://youtrack.jetbrains.com/issue/KT-38604) Implicit suspend conversion on call arguments doesn't work on vararg elements +- [`KT-38680`](https://youtrack.jetbrains.com/issue/KT-38680) NSME when calling generic interface method with default parameters overriden with inline class type argument +- [`KT-38681`](https://youtrack.jetbrains.com/issue/KT-38681) Wrong bytecode generated when calling generic interface method with default parameters overriden with primitive type argument +- [`KT-38691`](https://youtrack.jetbrains.com/issue/KT-38691) NI: overload resolution ambiguity if take `R` and `() -> R`, and pass literal lambda, which returns `R` +- [`KT-38799`](https://youtrack.jetbrains.com/issue/KT-38799) False positive USELESS_CAST for lambda parameter +- [`KT-38802`](https://youtrack.jetbrains.com/issue/KT-38802) Generated code crashes by ClassCastException when delegating with inline class +- [`KT-38853`](https://youtrack.jetbrains.com/issue/KT-38853) Backend Internal error: Error type encountered: Unresolved type for nested class used in an annotation argument on an interface method +- [`KT-38890`](https://youtrack.jetbrains.com/issue/KT-38890) NI: false negative Type mismatch for values with fun keyword +- [`KT-39010`](https://youtrack.jetbrains.com/issue/KT-39010) NI: Regression with false-positive smartcast on var of generic type +- [`KT-39013`](https://youtrack.jetbrains.com/issue/KT-39013) 202, ASM 8: "AnalyzerException: Execution can fall off the end of the code" +- [`KT-39260`](https://youtrack.jetbrains.com/issue/KT-39260) "AssertionError: Unsigned type expected: Int" in range +- [`KT-39305`](https://youtrack.jetbrains.com/issue/KT-39305) NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER: unable to infer deeply nested type bound when class implements generic interface +- [`KT-39408`](https://youtrack.jetbrains.com/issue/KT-39408) Using unsigned arrays as generics fails in 1.4-M2 with class cast exception +- [`KT-39533`](https://youtrack.jetbrains.com/issue/KT-39533) NI: Wrong overload resolution for methods with SAM converted function reference arguments +- [`KT-39535`](https://youtrack.jetbrains.com/issue/KT-39535) NI: Inference fails for the parameters of SAM converted lambdas with type parameters +- [`KT-39603`](https://youtrack.jetbrains.com/issue/KT-39603) Require explicit override in JVM default compatibility mode on implicit generic specialization of inherited methods in classes +- [`KT-39671`](https://youtrack.jetbrains.com/issue/KT-39671) Couldn't inline method call 'expectBody' +- [`KT-39816`](https://youtrack.jetbrains.com/issue/KT-39816) NI:ClassCastException and no IDE error with provideDelegate when DELEGATE_SPECIAL_FUNCTION_MISSING in OI +- [`KT-32779`](https://youtrack.jetbrains.com/issue/KT-32779) `Rewrite at slice` in array access resolution in coroutine inference +- [`KT-39387`](https://youtrack.jetbrains.com/issue/KT-39387) Can't build Kotlin project due to overload resolution ambiguity on flatMap calls +- [`KT-39229`](https://youtrack.jetbrains.com/issue/KT-39229) NI: resolution to wrong candidate (SAM-type against similar functional type) + +### Docs & Examples + +- [`KT-36245`](https://youtrack.jetbrains.com/issue/KT-36245) Document that @kotlin.native.ThreadLocal annotation doesn't work anywhere except in Kotlin/Native +- [`KT-37943`](https://youtrack.jetbrains.com/issue/KT-37943) Conflicting overloads in the factory functions sample code in Coding Conventions Page + +### IDE + +#### New Features + +- [`KT-10974`](https://youtrack.jetbrains.com/issue/KT-10974) Add Code Style: Import Layout Configuration Table +- [`KT-39065`](https://youtrack.jetbrains.com/issue/KT-39065) "Join lines" should remove trailing comma on call site + +#### Fixes + +- [`KT-9065`](https://youtrack.jetbrains.com/issue/KT-9065) Wrong result when move statement through if block with call with lambda +- [`KT-14757`](https://youtrack.jetbrains.com/issue/KT-14757) Move statement up breaks code in function parameter list +- [`KT-14946`](https://youtrack.jetbrains.com/issue/KT-14946) Move statement up/down (with Ctrl+Shift+Up/Down) messes with empty lines +- [`KT-15143`](https://youtrack.jetbrains.com/issue/KT-15143) Kotlin: Colors&Fonts -> "Enum entry" should use Language Default -> Classes - Static field +- [`KT-17887`](https://youtrack.jetbrains.com/issue/KT-17887) Moving statement (Ctrl/Cmd+Shift+Down) messes with use block +- [`KT-34187`](https://youtrack.jetbrains.com/issue/KT-34187) UAST cannot get type of array access +- [`KT-34524`](https://youtrack.jetbrains.com/issue/KT-34524) "PSI and index do not match" and IDE freeze with library import from `square/workflow` +- [`KT-35574`](https://youtrack.jetbrains.com/issue/KT-35574) UAST: UBreakExpression in when expression should be UYieldExpression +- [`KT-36801`](https://youtrack.jetbrains.com/issue/KT-36801) IDE: Unsupported language version value is represented with "latest stable" in GUI +- [`KT-37378`](https://youtrack.jetbrains.com/issue/KT-37378) Remove IDE option "Enable new type inference algorithm..." in 1.4 +- [`KT-38003`](https://youtrack.jetbrains.com/issue/KT-38003) "Analyze Data Flow from Here" should work on parameter of abstract method +- [`KT-38173`](https://youtrack.jetbrains.com/issue/KT-38173) Reified types do no have extends information +- [`KT-38217`](https://youtrack.jetbrains.com/issue/KT-38217) Make Kotlin plugin settings searchable +- [`KT-38247`](https://youtrack.jetbrains.com/issue/KT-38247) "IncorrectOperationException: Incorrect expression" through UltraLightUtils.kt: inlined string is not escaped before parsing +- [`KT-38293`](https://youtrack.jetbrains.com/issue/KT-38293) Throwable: "'codestyle.name.kotlin' is not found in java.util.PropertyResourceBundle" at KotlinLanguageCodeStyleSettingsProvider.getConfigurableDisplayName() +- [`KT-38407`](https://youtrack.jetbrains.com/issue/KT-38407) Drop components from plugin.xml +- [`KT-38443`](https://youtrack.jetbrains.com/issue/KT-38443) No error on change in property initializer +- [`KT-38521`](https://youtrack.jetbrains.com/issue/KT-38521) ISE: Loop in parent structure when converting a DOT_QUALIFIED_EXPRESSION with parent ANNOTATED_EXPRESSION +- [`KT-38571`](https://youtrack.jetbrains.com/issue/KT-38571) Rework deprecated EPs +- [`KT-38632`](https://youtrack.jetbrains.com/issue/KT-38632) Change the code style to official in tests + +### IDE. Code Style, Formatting + +#### Fixes + +- [`KT-24750`](https://youtrack.jetbrains.com/issue/KT-24750) Formatter: Minimum blank lines after class header does nothing +- [`KT-31169`](https://youtrack.jetbrains.com/issue/KT-31169) IDEA settings search fails to find "Tabs and Indents" tab in Kotlin code style settings +- [`KT-35359`](https://youtrack.jetbrains.com/issue/KT-35359) Incorrect indent for multiline expression in string template +- [`KT-37420`](https://youtrack.jetbrains.com/issue/KT-37420) Add setting to disable inserting empty line between declaration and declaration with comment +- [`KT-37891`](https://youtrack.jetbrains.com/issue/KT-37891) Formatter inserts empty lines between annotated properties +- [`KT-38036`](https://youtrack.jetbrains.com/issue/KT-38036) Use trailing comma setting does not apply to code example in Settings dialog +- [`KT-38568`](https://youtrack.jetbrains.com/issue/KT-38568) False positive: weak warning "Missing line break" on -> in when expression +- [`KT-39024`](https://youtrack.jetbrains.com/issue/KT-39024) Add option for blank lines before declaration with comment or annotation on separate line +- [`KT-39079`](https://youtrack.jetbrains.com/issue/KT-39079) Trailing comma: add base support for call site +- [`KT-39123`](https://youtrack.jetbrains.com/issue/KT-39123) Option `Align 'when' branches in columns` does nothing +- [`KT-39180`](https://youtrack.jetbrains.com/issue/KT-39180) Move trailing comma settings in Other tab + +### IDE. Completion + +- [`KT-18538`](https://youtrack.jetbrains.com/issue/KT-18538) Completion of static members of grand-super java class inserts unnecessary qualifier +- [`KT-38445`](https://youtrack.jetbrains.com/issue/KT-38445) Fully qualified class name is used instead after insertion of `delay` method + +### IDE. Debugger + +#### Fixes + +- [`KT-14057`](https://youtrack.jetbrains.com/issue/KT-14057) Debugger couldn't step into Reader.read +- [`KT-14828`](https://youtrack.jetbrains.com/issue/KT-14828) Bad step into/over behavior for functions with default parameters +- [`KT-36403`](https://youtrack.jetbrains.com/issue/KT-36403) Method breakpoints don't work for libraries +- [`KT-36404`](https://youtrack.jetbrains.com/issue/KT-36404) Evaluate: "AssertionError: Argument expression is not saved for a SAM constructor" +- [`KT-37486`](https://youtrack.jetbrains.com/issue/KT-37486) Kotlin plugin keeps reference to stream debugger support classes after stream debugger plugin is disabled +- [`KT-38484`](https://youtrack.jetbrains.com/issue/KT-38484) Coroutines Debugger: IAE “Requested element count -1 is less than zero.” is thrown by calling dumpCoroutines +- [`KT-38606`](https://youtrack.jetbrains.com/issue/KT-38606) Coroutine Debugger: OCE from org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.BaseMirror.isCompatible +- [`KT-39143`](https://youtrack.jetbrains.com/issue/KT-39143) NPE on setCurrentStackFrame to Kotlin inner compiled class content +- [`KT-39412`](https://youtrack.jetbrains.com/issue/KT-39412) Failed to find Premain-Class manifest attribute when debugging main method with ktor +- [`KT-39634`](https://youtrack.jetbrains.com/issue/KT-39634) (CoroutineDebugger) Agent doesn't start if using kotlinx-coroutines-core only dependency +- [`KT-39648`](https://youtrack.jetbrains.com/issue/KT-39648) Coroutines debugger doesn't see stacktraces in case of the project has kotlinx-coroutines-debug dependency + +### IDE. Gradle Integration + +#### Performance Improvements + +- [`KT-39059`](https://youtrack.jetbrains.com/issue/KT-39059) Poor performance of `modifyDependenciesOnMppModules` + +#### Fixes + +- [`KT-35921`](https://youtrack.jetbrains.com/issue/KT-35921) Gradle Import fails with "Unsupported major.minor version 52.0" on pure Java project in case "Gradle JDK" is lower 1.8 and Kotlin plugin is enabled +- [`KT-36673`](https://youtrack.jetbrains.com/issue/KT-36673) Gradle Project importing: move ModelBuilders and ModelProviders to kotlin-gradle-tooling jar +- [`KT-36792`](https://youtrack.jetbrains.com/issue/KT-36792) IDEA 2020.1: Some module->module dependencies in HMPP project are missed after import from Gradle +- [`KT-37125`](https://youtrack.jetbrains.com/issue/KT-37125) Imported modules structure for MPP project is displayed messy in UI in IDEA 2020.1 +- [`KT-37428`](https://youtrack.jetbrains.com/issue/KT-37428) NPE at KotlinFacetSettings.setLanguageLevel() on the first project import +- [`KT-38706`](https://youtrack.jetbrains.com/issue/KT-38706) IDE Gradle import creates 4 JavaScript modules for MPP source sets with BOTH compiler type +- [`KT-38767`](https://youtrack.jetbrains.com/issue/KT-38767) Published hierarchical multiplatform library symbols are unresolved in IDE (master) +- [`KT-38842`](https://youtrack.jetbrains.com/issue/KT-38842) False positive [INVISIBLE_MEMBER] for `internal` declaration of commonMain called from commonTest +- [`KT-39213`](https://youtrack.jetbrains.com/issue/KT-39213) IDE: references from MPP project to JavaScript library are unresolved, when project and library are compiled with "both" mode +- [`KT-39657`](https://youtrack.jetbrains.com/issue/KT-39657) Language settings for intermediate source-sets are lost during import + +### IDE. Gradle. Script + +#### New Features + +- [`KT-34481`](https://youtrack.jetbrains.com/issue/KT-34481) `*.gradle.kts`: use Intellij IDEA Gradle project sync mechanics for updating script configuration + +#### Performance Improvements + +- [`KT-34138`](https://youtrack.jetbrains.com/issue/KT-34138) Deadlock in `ScriptTemplatesFromDependenciesProvider` +- [`KT-38875`](https://youtrack.jetbrains.com/issue/KT-38875) Deadlock in ScriptClassRootsUpdater.checkInvalidSdks + +#### Fixes + +- [`KT-34265`](https://youtrack.jetbrains.com/issue/KT-34265) Bogus "build configuration failed, run 'gradle tasks' for more information" message and other issues related to "script dependencies" +- [`KT-34444`](https://youtrack.jetbrains.com/issue/KT-34444) *.gradle.kts: special storage of all scripts configuration on one file +- [`KT-35153`](https://youtrack.jetbrains.com/issue/KT-35153) build.gradle.kts: scripts in removed subproject remain imported, but shouldn't +- [`KT-35573`](https://youtrack.jetbrains.com/issue/KT-35573) Request for gradle build script configuration only after explicit click on notification +- [`KT-36675`](https://youtrack.jetbrains.com/issue/KT-36675) move .gradle.kts ModelBuilders and ModelProviders to kotlin-gradle-tooling jar +- [`KT-37178`](https://youtrack.jetbrains.com/issue/KT-37178) build.gradle.kts: Rework the notification for scripts out of project +- [`KT-37631`](https://youtrack.jetbrains.com/issue/KT-37631) Unnecessary loading dependencies after opening build.gradle.kts after project import with Gradle 6 +- [`KT-37863`](https://youtrack.jetbrains.com/issue/KT-37863) Scanning dependencies for script definitions takes too long or indefinitely during Gradle import +- [`KT-38296`](https://youtrack.jetbrains.com/issue/KT-38296) MISSING_DEPENDENCY_SUPERCLASS in the build.gradle.kts editor while Gradle runs Ok +- [`KT-38541`](https://youtrack.jetbrains.com/issue/KT-38541) "Invalid file" exception in ScriptChangeListener.getAnalyzableKtFileForScript() +- [`KT-39104`](https://youtrack.jetbrains.com/issue/KT-39104) “Gradle Kotlin DSL script configuration is missing” after importing project in IJ201, Gradle 6.3 +- [`KT-39469`](https://youtrack.jetbrains.com/issue/KT-39469) Gradle version is not updated in script dependencies if the version of gradle was changed in gradle-wrapper.properties +- [`KT-39771`](https://youtrack.jetbrains.com/issue/KT-39771) Freeze 30s from org.jetbrains.kotlin.scripting.resolve.ApiChangeDependencyResolverWrapper.resolve on loading script configuration with Gradle 5.6.4 + +### IDE. Inspections and Intentions + +#### New Features + +- [`KT-14884`](https://youtrack.jetbrains.com/issue/KT-14884) Intention to add missing "class" keyword for enum and annotation top-level declarations +- [`KT-17209`](https://youtrack.jetbrains.com/issue/KT-17209) Provide intention to fix platform declaration clash (CONFLICTING_JVM_DECLARATIONS) +- [`KT-24522`](https://youtrack.jetbrains.com/issue/KT-24522) Suggest to move typealias outside the class +- [`KT-30263`](https://youtrack.jetbrains.com/issue/KT-30263) Detect redundant conversions of unsigned types +- [`KT-35893`](https://youtrack.jetbrains.com/issue/KT-35893) Support Inspection for unnecessary asSequence() call +- [`KT-38559`](https://youtrack.jetbrains.com/issue/KT-38559) "Change JVM name" (@JvmName) quickfix: improve name suggester for generic functions +- [`KT-38597`](https://youtrack.jetbrains.com/issue/KT-38597) Expand Boolean intention +- [`KT-38982`](https://youtrack.jetbrains.com/issue/KT-38982) Add "Logger initialized with foreign class" inspection +- [`KT-39131`](https://youtrack.jetbrains.com/issue/KT-39131) TrailingCommaInspection: should suggest fixes for call-site without warnings + +#### Fixes + +- [`KT-5271`](https://youtrack.jetbrains.com/issue/KT-5271) Missing QuickFix for Multiple supertypes available +- [`KT-11865`](https://youtrack.jetbrains.com/issue/KT-11865) "Create secondary constructor" quick fix always inserts parameter-less call to `this()` +- [`KT-14021`](https://youtrack.jetbrains.com/issue/KT-14021) Quickfix to add parameter to function gives strange name to parameter +- [`KT-17121`](https://youtrack.jetbrains.com/issue/KT-17121) "Implement members" quick fix is not suggested +- [`KT-17368`](https://youtrack.jetbrains.com/issue/KT-17368) Don't highlight members annotated with @JsName as unused +- [`KT-20795`](https://youtrack.jetbrains.com/issue/KT-20795) "replace explicit parameter with it" creates invalid code in case of overload ambiguities +- [`KT-22014`](https://youtrack.jetbrains.com/issue/KT-22014) Intention "convert lambda to reference" should be available for implicit 'this' +- [`KT-22015`](https://youtrack.jetbrains.com/issue/KT-22015) Intention "Convert lambda to reference" should be available in spite of the lambda in or out of parentheses +- [`KT-22142`](https://youtrack.jetbrains.com/issue/KT-22142) Intentions: "Convert to primary constructor" changes semantics for property with custom setter +- [`KT-22878`](https://youtrack.jetbrains.com/issue/KT-22878) Empty argument list at the call site of custom function named "suspend" shouldn't be reported as unnecessary +- [`KT-24281`](https://youtrack.jetbrains.com/issue/KT-24281) Importing of invoke() from the same file is reported as unused even if it isn't +- [`KT-25050`](https://youtrack.jetbrains.com/issue/KT-25050) False-positive inspection "Call replaceable with binary operator" for 'equals' +- [`KT-26361`](https://youtrack.jetbrains.com/issue/KT-26361) @Deprecated "ReplaceWith" quickfix inserts 'this' incorrectly when using function imports +- [`KT-27651`](https://youtrack.jetbrains.com/issue/KT-27651) 'Condition is always true' inspection should not be triggered when the condition has references to a named constant +- [`KT-29934`](https://youtrack.jetbrains.com/issue/KT-29934) False negative `Change type` quickfix on primary constructor override val parameter when it has wrong type +- [`KT-31682`](https://youtrack.jetbrains.com/issue/KT-31682) 'Convert lambda to reference' intention inside class with function which return object produces uncompilable code +- [`KT-31760`](https://youtrack.jetbrains.com/issue/KT-31760) Implement Abstract Function/Property intentions position generated member improperly +- [`KT-32511`](https://youtrack.jetbrains.com/issue/KT-32511) Create class quick fix is not suggested in super type list in case of missing primary constructor +- [`KT-32565`](https://youtrack.jetbrains.com/issue/KT-32565) False positive "Variable is the same as 'credentials' and should be inlined" with object declared and returned from lambda +- [`KT-32801`](https://youtrack.jetbrains.com/issue/KT-32801) False positive "Call on collection type may be reduced" with mapNotNull, generic lambda block and new inference +- [`KT-33951`](https://youtrack.jetbrains.com/issue/KT-33951) ReplaceWith quickfix with unqualified object member call doesn't substitute argument for parameter +- [`KT-34378`](https://youtrack.jetbrains.com/issue/KT-34378) "Convert lambda to reference" refactoring does not work for suspend functions +- [`KT-34677`](https://youtrack.jetbrains.com/issue/KT-34677) False positive "Collection count can be converted to size" with `Iterable` +- [`KT-34696`](https://youtrack.jetbrains.com/issue/KT-34696) Wrong 'Redundant qualifier name' for 'MyEnum.values' usage +- [`KT-34713`](https://youtrack.jetbrains.com/issue/KT-34713) "Condition is always 'false'": quickfix "Delete expression" doesn't remove `else` keyword (may break control flow) +- [`KT-35015`](https://youtrack.jetbrains.com/issue/KT-35015) ReplaceWith doesn't substitute parameters with argument expressions +- [`KT-35329`](https://youtrack.jetbrains.com/issue/KT-35329) Replace 'when' with 'if' intention: do not suggest if 'when' is used as expression and it has no 'else' branch +- [`KT-36194`](https://youtrack.jetbrains.com/issue/KT-36194) "Add braces to 'for' statement" inserts extra line break and moves the following single-line comment +- [`KT-36406`](https://youtrack.jetbrains.com/issue/KT-36406) "To ordinary string literal" intention adds unnecessary escapes to characters in template expression +- [`KT-36461`](https://youtrack.jetbrains.com/issue/KT-36461) "Create enum constant" quick fix adds after semicolon, if the last entry has a comma +- [`KT-36462`](https://youtrack.jetbrains.com/issue/KT-36462) "Create enum constant" quick fix doesn't add trailing comma +- [`KT-36508`](https://youtrack.jetbrains.com/issue/KT-36508) False positive "Replace 'to' with infix form" when 'to' lambda generic type argument is specified explicitly +- [`KT-36930`](https://youtrack.jetbrains.com/issue/KT-36930) Intention "Specify type explicitly" adds NotNull annotation when calling java method with the annotation +- [`KT-37148`](https://youtrack.jetbrains.com/issue/KT-37148) "Remove redundant `.let` call doesn't remove extra calls +- [`KT-37156`](https://youtrack.jetbrains.com/issue/KT-37156) "Unused unary operator" inspection highlighting is hard to see +- [`KT-37173`](https://youtrack.jetbrains.com/issue/KT-37173) "Replace with string templates" intention for String.format produces uncompilable string template +- [`KT-37181`](https://youtrack.jetbrains.com/issue/KT-37181) Don't show "Remove redundant qualifier name" inspection on qualified Companion imported with star import +- [`KT-37214`](https://youtrack.jetbrains.com/issue/KT-37214) "Convert lambda to reference" with a labeled "this" receiver fails +- [`KT-37256`](https://youtrack.jetbrains.com/issue/KT-37256) False positive `PlatformExtensionReceiverOfInline` inspection if a platform type value is passed to a nullable receiver +- [`KT-37744`](https://youtrack.jetbrains.com/issue/KT-37744) "Convert lambda to reference" inspection quick fix create incompilable code when type is inferred from lambda parameter +- [`KT-37746`](https://youtrack.jetbrains.com/issue/KT-37746) "Redundant suspend modifier" should not be reported for functions with actual keyword +- [`KT-37842`](https://youtrack.jetbrains.com/issue/KT-37842) "Convert to anonymous function" creates broken code with suspend functions +- [`KT-37908`](https://youtrack.jetbrains.com/issue/KT-37908) "Convert to anonymous object" quickfix: false negative when interface has concrete functions +- [`KT-37967`](https://youtrack.jetbrains.com/issue/KT-37967) Replace 'invoke' with direct call intention adds unnecessary parenthesis +- [`KT-37977`](https://youtrack.jetbrains.com/issue/KT-37977) "Replace 'invoke' with direct call" intention: false positive when function is not operator +- [`KT-38062`](https://youtrack.jetbrains.com/issue/KT-38062) Reactor Quickfix throws `NotImplementedError` for Kotlin +- [`KT-38240`](https://youtrack.jetbrains.com/issue/KT-38240) False positive redundant semicolon with `as` cast and `not` unary operator on next line +- [`KT-38261`](https://youtrack.jetbrains.com/issue/KT-38261) Redundant 'let' call removal leaves ?. operator and makes code uncompilable +- [`KT-38310`](https://youtrack.jetbrains.com/issue/KT-38310) Remove explicit type annotation intention drops 'suspend' +- [`KT-38492`](https://youtrack.jetbrains.com/issue/KT-38492) False positive "Add import" intention for already imported class +- [`KT-38520`](https://youtrack.jetbrains.com/issue/KT-38520) SetterBackingFieldAssignmentInspection throws exception +- [`KT-38649`](https://youtrack.jetbrains.com/issue/KT-38649) False positive quickfix "Assignment should be lifted out of when" in presence of smartcasts +- [`KT-38677`](https://youtrack.jetbrains.com/issue/KT-38677) Invalid psi tree after `Lift assigment out of...` +- [`KT-38790`](https://youtrack.jetbrains.com/issue/KT-38790) "Convert sealed subclass to object" for data classes doesn't remove 'data' keyword +- [`KT-38829`](https://youtrack.jetbrains.com/issue/KT-38829) 'Remove redundant backticks' can be broken with @ in name +- [`KT-38831`](https://youtrack.jetbrains.com/issue/KT-38831) 'Replace with assignment' can be broken with fast code change +- [`KT-38832`](https://youtrack.jetbrains.com/issue/KT-38832) "Remove curly braces" intention may produce CCE +- [`KT-38948`](https://youtrack.jetbrains.com/issue/KT-38948) False positive quickfix "Make containing function suspend" for anonymous function +- [`KT-38961`](https://youtrack.jetbrains.com/issue/KT-38961) "Useless call on collection type" for filterNotNull on non-null array where list return type is expected +- [`KT-39069`](https://youtrack.jetbrains.com/issue/KT-39069) Improve TrailingCommaInspection +- [`KT-39151`](https://youtrack.jetbrains.com/issue/KT-39151) False positive inspection to replace Java forEach with Kotlin forEach when using ConcurrentHashMap + +### IDE. JS + +- [`KT-39275`](https://youtrack.jetbrains.com/issue/KT-39275) Kotlin JS Browser template for kotlin dsl doesn't include index.html + +### IDE. KDoc + +- [`KT-32163`](https://youtrack.jetbrains.com/issue/KT-32163) Open Quick Documentation when cursor inside function / constructor brackets + +### IDE. Navigation + +- [`KT-32245`](https://youtrack.jetbrains.com/issue/KT-32245) Method in Kotlin class is not listed among implementing methods +- [`KT-33510`](https://youtrack.jetbrains.com/issue/KT-33510) There is no gutter icon to navigate from `actual` to `expect` if `expect` and the corresponding `actual` declarations are in the same file +- [`KT-38260`](https://youtrack.jetbrains.com/issue/KT-38260) Navigation bar doesn't show directories of files with a single top level Kotlin class +- [`KT-38466`](https://youtrack.jetbrains.com/issue/KT-38466) Top level functions/properties aren't shown in navigation panel + +### IDE. Project View + +- [`KT-36444`](https://youtrack.jetbrains.com/issue/KT-36444) Structure view: add ability to sort by visibility +- [`KT-38276`](https://youtrack.jetbrains.com/issue/KT-38276) Structure view: support visibility filter for class properties + +### IDE. REPL + +- [`KT-38454`](https://youtrack.jetbrains.com/issue/KT-38454) Kotlin REPL in IntelliJ doesn't take module's JVM target setting into account + +### IDE. Refactorings + +- [`KT-12878`](https://youtrack.jetbrains.com/issue/KT-12878) "Change signature" forces line breaks after every parameter declaration +- [`KT-30128`](https://youtrack.jetbrains.com/issue/KT-30128) Change Signature should move lambda outside of parentheses if the arguments are reordered so that the lambda goes last +- [`KT-35338`](https://youtrack.jetbrains.com/issue/KT-35338) Move/rename refactorings mess up code formatting by wrapping lines +- [`KT-38449`](https://youtrack.jetbrains.com/issue/KT-38449) Extract variable refactoring is broken by NPE +- [`KT-38543`](https://youtrack.jetbrains.com/issue/KT-38543) Copy can't work to package with escaped package +- [`KT-38627`](https://youtrack.jetbrains.com/issue/KT-38627) Rename package refactorings mess up code formatting by wrapping lines + +### IDE. Run Configurations + +- [`KT-34516`](https://youtrack.jetbrains.com/issue/KT-34516) Don't suggest incompatible targets in a drop-down list for run test gutter icon in multiplatform projects +- [`KT-38102`](https://youtrack.jetbrains.com/issue/KT-38102) DeprecatedMethodException ConfigurationFactory.getId + +### IDE. Scratch + +- [`KT-38455`](https://youtrack.jetbrains.com/issue/KT-38455) Kotlin scratch files don't take module's JVM target setting into account + +### IDE. Script + +- [`KT-39791`](https://youtrack.jetbrains.com/issue/KT-39791) Kotlin plugin loads VFS in the output directories + +### IDE. Structural Search + +- [`KT-39721`](https://youtrack.jetbrains.com/issue/KT-39721) Optimize Kotlin SSR by using the index +- [`KT-39733`](https://youtrack.jetbrains.com/issue/KT-39733) Augmented assignment matching +- [`KT-39769`](https://youtrack.jetbrains.com/issue/KT-39769) "When expressions" predefined template doesn't match all when expressions + +### IDE. Wizards + +- [`KT-38673`](https://youtrack.jetbrains.com/issue/KT-38673) New Project Wizard: multiplatform templates are generated having unsupported Gradle version in a wrapper +- [`KT-38810`](https://youtrack.jetbrains.com/issue/KT-38810) Incorrect order of build phases in Xcode project from new wizard +- [`KT-38952`](https://youtrack.jetbrains.com/issue/KT-38952) Remove old new_project_wizards +- [`KT-39503`](https://youtrack.jetbrains.com/issue/KT-39503) New Project wizard 1.4+: release kotlinx.html version is added to dependencies with milestone IDE plugin +- [`KT-39700`](https://youtrack.jetbrains.com/issue/KT-39700) Wizard: group project templates on the first step by the project type +- [`KT-39770`](https://youtrack.jetbrains.com/issue/KT-39770) CSS Support in Kotlin wizards +- [`KT-39826`](https://youtrack.jetbrains.com/issue/KT-39826) Fix Android app in New Template Wizard +- [`KT-39843`](https://youtrack.jetbrains.com/issue/KT-39843) Change imports in JS/browser wizard + +### JS. Tools + +- [`KT-32273`](https://youtrack.jetbrains.com/issue/KT-32273) Kotlin/JS console error on hot reload +- [`KT-39498`](https://youtrack.jetbrains.com/issue/KT-39498) Update dukat version in toolchain near to release of 1.4-M3 + +### JavaScript + +- [`KT-29916`](https://youtrack.jetbrains.com/issue/KT-29916) Implement `typeOf` on JS +- [`KT-35857`](https://youtrack.jetbrains.com/issue/KT-35857) Kotlin/JS CLI bundled to IDEA plugin can't compile using IR back-end out of the box +- [`KT-36798`](https://youtrack.jetbrains.com/issue/KT-36798) KJS: prohibit using @JsExport on a non-top-level declaration +- [`KT-37771`](https://youtrack.jetbrains.com/issue/KT-37771) KJS: Generated TypeScript does not recursively export base classes (can fail with generics) +- [`KT-38113`](https://youtrack.jetbrains.com/issue/KT-38113) Review public API of JS stdlib for IR BE +- [`KT-38765`](https://youtrack.jetbrains.com/issue/KT-38765) [JS / IR] AssertionError: class EventEmitter: Super class should be any: with nested class extending parent class +- [`KT-38768`](https://youtrack.jetbrains.com/issue/KT-38768) KJS IR: generate ES2015 (aka ES6) classes + +### Libraries + +#### New Features + +- [`KT-11253`](https://youtrack.jetbrains.com/issue/KT-11253) Function to sum long or other numeric property of items in a collection +- [`KT-28933`](https://youtrack.jetbrains.com/issue/KT-28933) capitalize() with Locale argument in the JDK stdlib +- [`KT-34142`](https://youtrack.jetbrains.com/issue/KT-34142) Create SortedMap with Comparator and items +- [`KT-34506`](https://youtrack.jetbrains.com/issue/KT-34506) Add Sequence.flatMap overload that works on Iterable +- [`KT-36894`](https://youtrack.jetbrains.com/issue/KT-36894) Support flatMapIndexed in the Collections API +- [`KT-38480`](https://youtrack.jetbrains.com/issue/KT-38480) Introduce experimental annotation for enabling overload resolution by lambda result +- [`KT-38708`](https://youtrack.jetbrains.com/issue/KT-38708) minOf/maxOf functions to return min/max value provided by selector +- [`KT-39707`](https://youtrack.jetbrains.com/issue/KT-39707) Make some interfaces in stdlib functional + +#### Performance Improvements + +- [`KT-23142`](https://youtrack.jetbrains.com/issue/KT-23142) toHashSet is suboptimal for inputs with a lot of duplicates + +#### Fixes + +- [`KT-21266`](https://youtrack.jetbrains.com/issue/KT-21266) Add module-info for standard library artifacts +- [`KT-23322`](https://youtrack.jetbrains.com/issue/KT-23322) Document 'reduce' operation behavior on empty collections +- [`KT-28753`](https://youtrack.jetbrains.com/issue/KT-28753) Comparing floating point values in array/list operations 'contains', 'indexOf', 'lastIndexOf': IEEE 754 or total order +- [`KT-30083`](https://youtrack.jetbrains.com/issue/KT-30083) Annotate KTypeProjection.STAR with JvmField in a compatible way +- [`KT-30084`](https://youtrack.jetbrains.com/issue/KT-30084) Annotate functions in KTypeProjection.Companion with JvmStatic +- [`KT-31343`](https://youtrack.jetbrains.com/issue/KT-31343) Deprecate old String <-> CharArray, ByteArray conversion api +- [`KT-34596`](https://youtrack.jetbrains.com/issue/KT-34596) Add some validation to KTypeProjection constructor +- [`KT-35978`](https://youtrack.jetbrains.com/issue/KT-35978) Review and remove experimental stdlib API status for 1.4 +- [`KT-38388`](https://youtrack.jetbrains.com/issue/KT-38388) Document `fromIndex` and `toIndex` parameters +- [`KT-38854`](https://youtrack.jetbrains.com/issue/KT-38854) Gradually change the return type of collection min/max functions to non-nullable +- [`KT-39023`](https://youtrack.jetbrains.com/issue/KT-39023) Document split(Pattern) extension differences from Pattern.split +- [`KT-39064`](https://youtrack.jetbrains.com/issue/KT-39064) Introduce minOrNull and maxOrNull extension functions on collections +- [`KT-39235`](https://youtrack.jetbrains.com/issue/KT-39235) Lift experimental annotation from bit operations +- [`KT-39237`](https://youtrack.jetbrains.com/issue/KT-39237) Lift experimental annotation from common StringBuilder +- [`KT-39238`](https://youtrack.jetbrains.com/issue/KT-39238) Appendable.appendRange - remove nullability +- [`KT-39239`](https://youtrack.jetbrains.com/issue/KT-39239) Lift experimental annotation from String <-> utf8 conversion api +- [`KT-39244`](https://youtrack.jetbrains.com/issue/KT-39244) KJS: update polyfills, all or most of them must not be enumerable +- [`KT-39330`](https://youtrack.jetbrains.com/issue/KT-39330) Migrate declarations from kotlin.dom and kotlin.browser packages to kotlinx.* + +### Middle-end. IR + +- [`KT-31088`](https://youtrack.jetbrains.com/issue/KT-31088) need a way to compute fake overrides for pure IR +- [`KT-33207`](https://youtrack.jetbrains.com/issue/KT-33207) Kotlin/Native: KNPE during deserialization of an inner class +- [`KT-33267`](https://youtrack.jetbrains.com/issue/KT-33267) Kotlin/Native: Deserialization error for an "inner" extension property imported from a class +- [`KT-37255`](https://youtrack.jetbrains.com/issue/KT-37255) Make psi2ir aware of declarations provided by compiler plugins + +### Reflection + +- [`KT-22936`](https://youtrack.jetbrains.com/issue/KT-22936) Not all things can be changed to `createType` yet, and now `defaultType` methods are starting to fail +- [`KT-32241`](https://youtrack.jetbrains.com/issue/KT-32241) Move KType.javaType into stdlib from reflect +- [`KT-34344`](https://youtrack.jetbrains.com/issue/KT-34344) KType.javaType implementation throws when invoked with a typeOf<T>() +- [`KT-38491`](https://youtrack.jetbrains.com/issue/KT-38491) IllegalArgumentException when using callBy on function with inline class parameters and default arguments +- [`KT-38881`](https://youtrack.jetbrains.com/issue/KT-38881) Add KClass.isFun modifier of functional interfaces to reflection + +### Tools. Android Extensions + +- [`KT-25807`](https://youtrack.jetbrains.com/issue/KT-25807) Kotlin extension annotation @Parcelize in AIDL returns Object instead of original T + +### Tools. CLI + +- [`KT-30211`](https://youtrack.jetbrains.com/issue/KT-30211) Support a way to pass arguments to the underlying JVM in kotlinc batch scripts on Windows +- [`KT-30778`](https://youtrack.jetbrains.com/issue/KT-30778) kotlin-compiler.jar contains shaded but not relocated kotlinx.coroutines +- [`KT-38070`](https://youtrack.jetbrains.com/issue/KT-38070) Compiler option to bypass prerelease metadata incompatibility error +- [`KT-38413`](https://youtrack.jetbrains.com/issue/KT-38413) Add JVM target bytecode version 14 + +### Tools. Compiler Plugins + +- [`KT-39274`](https://youtrack.jetbrains.com/issue/KT-39274) [KJS / IR] Custom serializer for class without zero argument constructor doesn't compile + +### Tools. Gradle + +- [`KT-25428`](https://youtrack.jetbrains.com/issue/KT-25428) Kotlin Gradle Plugin: Use new Gradle API for Lazy tasks +- [`KT-34487`](https://youtrack.jetbrains.com/issue/KT-34487) Gradle build fails with "Cannot run program "java": error=7, Argument list too long +- [`KT-35957`](https://youtrack.jetbrains.com/issue/KT-35957) MPP IC fails with "X has several compatible actual declarations" error +- [`KT-38250`](https://youtrack.jetbrains.com/issue/KT-38250) Drop support for Gradle versions older than 5.3 in the Kotlin Gradle plugin + +### Tools. Gradle. JS + +#### New Features + +- [`KT-30619`](https://youtrack.jetbrains.com/issue/KT-30619) Support NPM transitive dependencies in multi-platform JS target +- [`KT-38286`](https://youtrack.jetbrains.com/issue/KT-38286) [Gradle, JS] Error handling on Webpack problems + +#### Fixes + +- [`KT-31669`](https://youtrack.jetbrains.com/issue/KT-31669) Gradle/JS: rise error when plugin loaded more than once +- [`KT-32531`](https://youtrack.jetbrains.com/issue/KT-32531) [Gradle/JS] Add scoped NPM dependencies +- [`KT-34832`](https://youtrack.jetbrains.com/issue/KT-34832) [Kotlin/JS] Failed build after webpack run (Karma not found) +- [`KT-35194`](https://youtrack.jetbrains.com/issue/KT-35194) Kotlin/JS: browserRun fails with "address already in use" when trying to connect to local server +- [`KT-35611`](https://youtrack.jetbrains.com/issue/KT-35611) Kotlin Gradle plugin should report `kotlin2js` plugin ID as deprecated +- [`KT-35641`](https://youtrack.jetbrains.com/issue/KT-35641) Kotlin Gradle plugin should report `kotlin-dce-js` plugin ID as deprecated +- [`KT-36410`](https://youtrack.jetbrains.com/issue/KT-36410) JS: Collect stats about IR backend usage +- [`KT-36451`](https://youtrack.jetbrains.com/issue/KT-36451) KJS Adding npm dependency breaks Webpack devserver reloading +- [`KT-37258`](https://youtrack.jetbrains.com/issue/KT-37258) Kotlin/JS + Gradle: in continuous mode kotlinNpmInstall time to time outputs "ENOENT: no such file or directory" error +- [`KT-38109`](https://youtrack.jetbrains.com/issue/KT-38109) [Gradle, JS] Error handling on Karma launcher problems +- [`KT-38331`](https://youtrack.jetbrains.com/issue/KT-38331) Add an ability to control generating externals for npm deps individually +- [`KT-38485`](https://youtrack.jetbrains.com/issue/KT-38485) [Gradle, JS] Unable to configure JS compiler with string +- [`KT-38683`](https://youtrack.jetbrains.com/issue/KT-38683) Remove possibility to set NPM dependency without version +- [`KT-38990`](https://youtrack.jetbrains.com/issue/KT-38990) Support multiple range versions for NPM dependencies +- [`KT-38994`](https://youtrack.jetbrains.com/issue/KT-38994) Remove possibility to set NPM dependency with npm(org, name, version) +- [`KT-39109`](https://youtrack.jetbrains.com/issue/KT-39109) ArithmeticException: "/ by zero" caused by kotlinNodeJsSetup task with enabled gradle caching on Windows +- [`KT-39210`](https://youtrack.jetbrains.com/issue/KT-39210) Kotlin/JS: with both JS and MPP modules in the same project Gradle configuration fails on `nodejs {}` and `browser {}` +- [`KT-39377`](https://youtrack.jetbrains.com/issue/KT-39377) Use standard source-map-loader instead of custom one + +### Tools. Gradle. Multiplatform + +- [`KT-39184`](https://youtrack.jetbrains.com/issue/KT-39184) Support publication of Kotlin-distributed libraries with Gradle Metadata +- [`KT-39304`](https://youtrack.jetbrains.com/issue/KT-39304) Gradle import error `java.util.NoSuchElementException: Key source set foo is missing in the map` on unused source set + +### Tools. Gradle. Native + +- [`KT-37514`](https://youtrack.jetbrains.com/issue/KT-37514) CocoaPods Gradle plugin: Support building from terminal projects for several platforms +- [`KT-38440`](https://youtrack.jetbrains.com/issue/KT-38440) Make error message about missing Podfile path for cocoapods integration actionable for a user +- [`KT-38991`](https://youtrack.jetbrains.com/issue/KT-38991) Gradle MPP plugin: Enable parallel in-process execution for K/N compiler +- [`KT-39935`](https://youtrack.jetbrains.com/issue/KT-39935) Support overriding the `KotlinNativeCompile` task sources +- [`KT-37512`](https://youtrack.jetbrains.com/issue/KT-37512) Cocoapods Gradle plugin: Improve error logging for external tools + +### Tools. J2K + +- [`KT-35169`](https://youtrack.jetbrains.com/issue/KT-35169) Do not show "Inline local variable" popup during "Cleaning up code" phase of J2K +- [`KT-38004`](https://youtrack.jetbrains.com/issue/KT-38004) J2K breaks java getter call in java code +- [`KT-38450`](https://youtrack.jetbrains.com/issue/KT-38450) J2K should convert Java SAM interfaces to Kotlin fun interfaces + +### Tools. JPS + +- [`KT-27458`](https://youtrack.jetbrains.com/issue/KT-27458) The Kotlin standard library is not found in the module graph ... in a non-Kotlin project. +- [`KT-29552`](https://youtrack.jetbrains.com/issue/KT-29552) Project is completely rebuilt after each gradle sync. + +### Tools. Scripts + +- [`KT-37766`](https://youtrack.jetbrains.com/issue/KT-37766) Impossible to apply compiler plugins onto scripts with the new scripting API + +### Tools. kapt + +- [`KT-29355`](https://youtrack.jetbrains.com/issue/KT-29355) Provide access to default values for primary constructor properties + + ## 1.4-M2 ### Compiler diff --git a/build.gradle.kts b/build.gradle.kts index cd046e3cbd1..6aa090b4dc8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -187,7 +187,7 @@ extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion extra["versions.ktor-network"] = "1.0.1" if (!project.hasProperty("versions.kotlin-native")) { - extra["versions.kotlin-native"] = "1.4-M3-eap-10" + extra["versions.kotlin-native"] = "1.4-rc1-18" } val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled) diff --git a/busytown.sh b/busytown.sh index 057fb90261a..39bbf33dd15 100755 --- a/busytown.sh +++ b/busytown.sh @@ -11,15 +11,16 @@ readonly DIST_DIR="$(realpath $DIST)" function set_java_home() { case `uname -s` in Darwin) - export JAVA_HOME=../../../prebuilts/jdk/jdk8/darwin-x86 - export JDK_9=../../../prebuilts/jdk/jdk9/darwin-x86 + export JAVA_HOME=$(realpath "$PROG_DIR/../../../prebuilts/jdk/jdk8/darwin-x86") + export JDK_9=$(realpath "$PROG_DIR/../../../prebuilts/jdk/jdk9/darwin-x86") ;; *) - export JAVA_HOME=../../../prebuilts/jdk/jdk8/linux-x86 - export JDK_9=../../../prebuilts/jdk/jdk9/linux-x86 + export JAVA_HOME=$(realpath "$PROG_DIR/../../../prebuilts/jdk/jdk8/linux-x86") + export JDK_9=$(realpath "$PROG_DIR/../../../prebuilts/jdk/jdk9/linux-x86") ;; esac } + readonly R4A_BUILD_NUMBER=1.4.0 function copy_jar_into_maven_repo() { local SOURCE_JAR="$1" diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 1193ddaf1b4..afeee9f266b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1257,7 +1257,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme throw new IllegalStateException("Can't get outer value in " + this + " for " + d); } - protected StackValueWithLeaveTask generateBlock( + private StackValueWithLeaveTask generateBlock( @NotNull List<KtExpression> statements, boolean isStatement, @Nullable Label labelBeforeLastExpression, diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index e4f187702b9..9fa9862c191 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -388,6 +388,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() { put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED) put(LanguageFeature.SamConversionPerArgument, LanguageFeature.State.ENABLED) put(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType, LanguageFeature.State.ENABLED) + put(LanguageFeature.DisableCompatibilityModeForNewInference, LanguageFeature.State.ENABLED) } if (inlineClasses) { @@ -467,6 +468,8 @@ abstract class CommonCompilerArguments : CommonToolArguments() { if (!functionReferenceWithDefaultValueFeaturePassedExplicitly) put(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType, LanguageFeature.State.ENABLED) + + put(LanguageFeature.DisableCompatibilityModeForNewInference, LanguageFeature.State.ENABLED) } if (featuresThatForcePreReleaseBinaries.isNotEmpty()) { diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 955da379040..1a69dc7399f 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -1924,6 +1924,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/callableReference/noAmbiguityWhenAllReferencesAreInapplicable.kt"); } + @TestMetadata("noCompatibilityResolveWithProressiveModeForNI.kt") + public void testNoCompatibilityResolveWithProressiveModeForNI() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.kt"); + } + @TestMetadata("noExceptionOnRedCodeWithArrayLikeCall.kt") public void testNoExceptionOnRedCodeWithArrayLikeCall() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/noExceptionOnRedCodeWithArrayLikeCall.kt"); @@ -2798,6 +2803,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveReferenceAgainstKFunctionAndKPrpoerty.kt"); } + @TestMetadata("resolveTwoReferencesAgainstGenerics.kt") + public void testResolveTwoReferencesAgainstGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.kt"); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt"); @@ -6525,6 +6535,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedHidden.kt"); } + @TestMetadata("deprecatedHiddenOnCallableReferenceArgument.kt") + public void testDeprecatedHiddenOnCallableReferenceArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.kt"); + } + @TestMetadata("deprecatedInheritance.kt") public void testDeprecatedInheritance() throws Exception { runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedInheritance.kt"); @@ -6667,6 +6682,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinDeclaration.kt"); } + @TestMetadata("deprecatedSinceKotlinHiddenOnReferenceArgument.kt") + public void testDeprecatedSinceKotlinHiddenOnReferenceArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.kt"); + } + @TestMetadata("deprecatedSinceKotlinOutsideKotlinPackage.kt") public void testDeprecatedSinceKotlinOutsideKotlinPackage() throws Exception { runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinOutsideKotlinPackage.kt"); @@ -10049,6 +10069,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/commonSuperTypeOfErrorTypes.kt"); } + @TestMetadata("compatibilityResolveWhenVariableHasComplexIntersectionType.kt") + public void testCompatibilityResolveWhenVariableHasComplexIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt"); + } + @TestMetadata("completeInferenceIfManyFailed.kt") public void testCompleteInferenceIfManyFailed() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt"); @@ -10199,6 +10224,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/intersectionTypeMultipleBoundsAsReceiver.kt"); } + @TestMetadata("intersectionTypesWithContravariantTypes.kt") + public void testIntersectionTypesWithContravariantTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt"); + } + @TestMetadata("intersectionWithEnum.kt") public void testIntersectionWithEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/intersectionWithEnum.kt"); @@ -10389,6 +10419,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt"); } + @TestMetadata("skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt") + public void testSkipedUnresolvedInBuilderInferenceWithStubReceiverType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt"); + } + @TestMetadata("starApproximation.kt") public void testStarApproximation() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/starApproximation.kt"); @@ -10644,6 +10679,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coerctionToUnitForATypeWithUpperBound.kt") + public void testCoerctionToUnitForATypeWithUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt"); + } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); @@ -24609,6 +24649,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/unitConversion/chainedUnitSuspendConversion.kt"); } + @TestMetadata("noUnitConversionForGenericTypeFromArrow.kt") + public void testNoUnitConversionForGenericTypeFromArrow() throws Exception { + runTest("compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.kt"); + } + + @TestMetadata("noUnitConversionOnReturningGenericFunctionalType.kt") + public void testNoUnitConversionOnReturningGenericFunctionalType() throws Exception { + runTest("compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.kt"); + } + @TestMetadata("unitConversionCompatibility.kt") public void testUnitConversionCompatibility() throws Exception { runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt"); diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index d8a3ede6279..f0b2464982b 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -1707,6 +1707,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") diff --git a/compiler/fir/tree/tree-generator/build.gradle.kts b/compiler/fir/tree/tree-generator/build.gradle.kts index df06fe46958..35f36631b4c 100644 --- a/compiler/fir/tree/tree-generator/build.gradle.kts +++ b/compiler/fir/tree/tree-generator/build.gradle.kts @@ -49,12 +49,3 @@ sourceSets { } "test" {} } - -allprojects { - tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> { - kotlinOptions { - freeCompilerArgs += "-Xskip-metadata-version-check" - } - } -} - diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt index 3650a4346bf..1b121a2009b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt @@ -5,22 +5,15 @@ package org.jetbrains.kotlin.resolve.calls.inference -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.psi.KtDotQualifiedExpression -import org.jetbrains.kotlin.psi.KtDoubleColonExpression -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtReferenceExpression +import org.jetbrains.kotlin.descriptors.impl.* +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.MissingSupertypesResolver -import org.jetbrains.kotlin.resolve.TemporaryBindingTrace +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.components.CompletedCallInfo import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl @@ -34,10 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver -import org.jetbrains.kotlin.types.StubType -import org.jetbrains.kotlin.types.TypeApproximator -import org.jetbrains.kotlin.types.TypeConstructor -import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.typeUtil.contains @@ -64,6 +54,10 @@ class CoroutineInferenceSession( psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns ) { private val commonCalls = arrayListOf<PSICompletedCallInfo>() + + // Simple calls are calls which might not have gone through type inference, but may contain unsubstituted postponed variables inside their types. + private val simpleCommonCalls = arrayListOf<KtExpression>() + private val diagnostics = arrayListOf<KotlinCallDiagnostic>() private var hasInapplicableCall = false @@ -85,6 +79,10 @@ class CoroutineInferenceSession( } || candidate.getSubResolvedAtoms().any { it.hasPostponed() } } + fun addSimpleCall(callExpression: KtExpression) { + simpleCommonCalls.add(callExpression) + } + override fun addCompletedCallInfo(callInfo: CompletedCallInfo) { require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" } @@ -260,38 +258,43 @@ class CoroutineInferenceSession( return commonSystem to effectivelyEmptyCommonSystem } + private fun reportDiagnostics(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, diagnostics: List<KotlinCallDiagnostic>) { + kotlinToResolvedCallTransformer.reportCallDiagnostic( + completedCall.context, + trace, + completedCall.callResolutionResult.resultCallAtom, + resolvedCall.resultingDescriptor, + diagnostics + ) + } + private fun updateCalls(lambda: ResolvedLambdaAtom, commonSystem: NewConstraintSystemImpl) { val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor() val commonSystemSubstitutor = commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor val nonFixedTypesToResult = nonFixedToVariablesSubstitutor.map.mapValues { commonSystemSubstitutor.safeSubstitute(it.value) } - val nonFixedTypesToResultSubstitutor = ComposedSubstitutor(commonSystemSubstitutor, nonFixedToVariablesSubstitutor) + val atomCompleter = createResolvedAtomCompleter(nonFixedTypesToResultSubstitutor, topLevelCallContext) + for (completedCall in commonCalls) { updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult) - - kotlinToResolvedCallTransformer.reportCallDiagnostic( - completedCall.context, - trace, - completedCall.callResolutionResult.resultCallAtom, - completedCall.resolvedCall.resultingDescriptor, - commonSystem.diagnostics - ) + reportDiagnostics(completedCall, completedCall.resolvedCall, commonSystem.diagnostics) } - val lambdaAtomCompleter = createResolvedAtomCompleter(nonFixedTypesToResultSubstitutor, topLevelCallContext) for (callInfo in partiallyResolvedCallsInfo) { - val resolvedCall = completeCall(callInfo, lambdaAtomCompleter) ?: continue - kotlinToResolvedCallTransformer.reportCallDiagnostic( - callInfo.context, - trace, - callInfo.callResolutionResult.resultCallAtom, - resolvedCall.resultingDescriptor, - commonSystem.diagnostics - ) + val resolvedCall = completeCall(callInfo, atomCompleter) ?: continue + reportDiagnostics(callInfo, resolvedCall, commonSystem.diagnostics) } - lambdaAtomCompleter.completeAll(lambda) + + for (simpleCall in simpleCommonCalls) { + when (simpleCall) { + is KtCallableReferenceExpression -> updateCallableReferenceType(simpleCall, nonFixedTypesToResultSubstitutor) + else -> throw Exception("Unsupported call expression type") + } + } + + atomCompleter.completeAll(lambda) } private fun updateCall( @@ -313,6 +316,28 @@ class CoroutineInferenceSession( completeCall(completedCall, atomCompleter) } + private fun updateCallableReferenceType(expression: KtCallableReferenceExpression, substitutor: NewTypeSubstitutor) { + val functionDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression) as? SimpleFunctionDescriptorImpl ?: return + val returnType = functionDescriptor.returnType + + fun KotlinType.substituteAndApproximate() = typeApproximator.approximateDeclarationType( + substitutor.safeSubstitute(this.unwrap()), + local = true, + languageVersionSettings = topLevelCallContext.languageVersionSettings + ) + + if (returnType != null && returnType.contains { it is StubType }) { + functionDescriptor.setReturnType(returnType.substituteAndApproximate()) + } + + for (valueParameter in functionDescriptor.valueParameters) { + if (valueParameter !is ValueParameterDescriptorImpl || valueParameter.type !is StubType) + continue + + valueParameter.setOutType(valueParameter.type.substituteAndApproximate()) + } + } + private fun completeCall( callInfo: CallInfo, atomCompleter: ResolvedAtomCompleter diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt index 5f17c62867f..74207c411d7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt @@ -39,6 +39,8 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeIntersector import org.jetbrains.kotlin.utils.addToStdlib.safeAs class KotlinResolutionStatelessCallbacksImpl( @@ -68,6 +70,18 @@ class KotlinResolutionStatelessCallbacksImpl( kotlinCall is PSIKotlinCallImpl && kotlinCall.psiCall.isCallWithSuperReceiver(), ) + override fun isHiddenInResolution( + descriptor: DeclarationDescriptor, + kotlinCallArgument: KotlinCallArgument, + resolutionCallbacks: KotlinResolutionCallbacks + ): Boolean = + deprecationResolver.isHiddenInResolution( + descriptor, + kotlinCallArgument.psiCallArgument.psiExpression, + (resolutionCallbacks as? KotlinResolutionCallbacksImpl)?.trace?.bindingContext, + isSuperCall = false, + ) + override fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean = receiver?.psiExpression is KtSuperExpression @@ -87,6 +101,10 @@ class KotlinResolutionStatelessCallbacksImpl( return org.jetbrains.kotlin.resolve.calls.inference.isApplicableCallForBuilderInference(descriptor, languageVersionSettings) } + override fun isOldIntersectionIsEmpty(types: Collection<KotlinType>): Boolean { + return TypeIntersector.intersectTypes(types) == null + } + override fun createConstraintSystemForOverloadResolution( constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns, ): SimpleConstraintSystem { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index d1cd7bfaec5..4f405b74530 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.builtins.createFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtNamedFunction @@ -209,13 +210,24 @@ class ResolvedAtomCompleter( resultSubstitutor.safeSubstitute(lambda.returnType) } + val approximatedValueParameterTypes = lambda.parameters.map { + // Do substitution and approximation only for stub types, which can appear from builder inference (as postponed variables) + if (it is StubType) { + typeApproximator.approximateDeclarationType( + resultSubstitutor.safeSubstitute(it), + local = true, + languageVersionSettings = topLevelCallContext.languageVersionSettings + ) + } else it + } + val approximatedReturnType = typeApproximator.approximateDeclarationType( returnType, local = true, languageVersionSettings = topLevelCallContext.languageVersionSettings ) - updateTraceForLambda(lambda, topLevelTrace, approximatedReturnType) + updateTraceForLambda(lambda, topLevelTrace, approximatedReturnType, approximatedValueParameterTypes) for (lambdaResult in resultArgumentsInfo.nonErrorArguments) { val resultValueArgument = lambdaResult as? PSIKotlinCallArgument ?: continue @@ -235,7 +247,12 @@ class ResolvedAtomCompleter( } } - private fun updateTraceForLambda(lambda: ResolvedLambdaAtom, trace: BindingTrace, returnType: UnwrappedType) { + private fun updateTraceForLambda( + lambda: ResolvedLambdaAtom, + trace: BindingTrace, + returnType: UnwrappedType, + valueParameters: List<UnwrappedType> + ) { val psiCallArgument = lambda.atom.psiCallArgument val ktArgumentExpression: KtExpression @@ -254,8 +271,15 @@ class ResolvedAtomCompleter( val functionDescriptor = trace.bindingContext.get(BindingContext.FUNCTION, ktFunction) as? FunctionDescriptorImpl ?: throw AssertionError("No function descriptor for resolved lambda argument") + functionDescriptor.setReturnType(returnType) + for ((i, valueParameter) in functionDescriptor.valueParameters.withIndex()) { + if (valueParameter !is ValueParameterDescriptorImpl || valueParameter.type !is StubType) + continue + valueParameter.setOutType(valueParameters[i]) + } + val existingLambdaType = trace.getType(ktArgumentExpression) if (existingLambdaType == null) { if (ktFunction is KtNamedFunction && ktFunction.nameIdentifier != null) return // it's a statement diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt index eba8e094b0d..72ddd49288c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.Call +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.SinceKotlinAccessibility import org.jetbrains.kotlin.resolve.calls.checkers.isOperatorMod @@ -64,6 +65,14 @@ class DeprecationResolver( call: Call? = null, bindingContext: BindingContext? = null, isSuperCall: Boolean = false + ): Boolean = + isHiddenInResolution(descriptor, call?.callElement, bindingContext, isSuperCall) + + fun isHiddenInResolution( + descriptor: DeclarationDescriptor, + callElement: KtElement?, + bindingContext: BindingContext?, + isSuperCall: Boolean ): Boolean { if (descriptor is FunctionDescriptor) { if (descriptor.isHiddenToOvercomeSignatureClash) return true @@ -74,10 +83,10 @@ class DeprecationResolver( if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessible) return true if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessibleButWasExperimental) { - if (call != null && bindingContext != null) { + if (callElement != null && bindingContext != null) { return with(ExperimentalUsageChecker) { sinceKotlinAccessibility.markerClasses.any { classDescriptor -> - !call.callElement.isExperimentalityAccepted(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext) + !callElement.isExperimentalityAccepted(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt index 921ea5cee20..30c7a96f4d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt @@ -149,6 +149,7 @@ interface SyntheticResolveExtension { * or null in case it needs to run resolution and inference and/or it is very costly. * Override this method if resolution started to fail with recursion. */ + @JvmDefault fun getPossibleSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name>? = getSyntheticNestedClassNames(thisDescriptor) fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 166917e6ee2..5f5f61e5dc7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.calls.context.* +import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSession import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo @@ -49,10 +50,7 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport.LanguageVersionDependent import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo import org.jetbrains.kotlin.types.refinement.TypeRefinement -import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable -import org.jetbrains.kotlin.types.typeUtil.makeNullable +import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.yieldIfNotNull import java.util.* import javax.inject.Inject @@ -558,6 +556,11 @@ class DoubleColonExpressionResolver( val (lhs, resolutionResults) = resolveCallableReference(expression, c, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS) val result = getCallableReferenceType(expression, lhs, resolutionResults, c) val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo + + if (c.inferenceSession is CoroutineInferenceSession && result?.contains { it is StubType } == true) { + c.inferenceSession.addSimpleCall(expression) + } + return dataFlowAnalyzer.checkType(createTypeInfo(result, dataFlowInfo), expression, c) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingFacade.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingFacade.java index ec8cf61c9ee..31df5278731 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingFacade.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingFacade.java @@ -28,6 +28,4 @@ public interface ExpressionTypingFacade { @NotNull KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, ExpressionTypingContext context, boolean isStatement); - - void checkType(@NotNull KtExpression expression, ExpressionTypingContext context); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java index 3b2aa0a61cf..e47863a21e8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java @@ -15,8 +15,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.ScriptDescriptor; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; @@ -34,7 +32,6 @@ import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt; import org.jetbrains.kotlin.util.slicedMap.WritableSlice; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -43,7 +40,7 @@ import static org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_T public class ExpressionTypingServices { - public final ExpressionTypingFacade expressionTypingFacade; + private final ExpressionTypingFacade expressionTypingFacade; private final ExpressionTypingComponents expressionTypingComponents; @NotNull private final AnnotationChecker annotationChecker; @@ -211,7 +208,7 @@ public class ExpressionTypingServices { return r; } - + @NotNull public KotlinType getBodyExpressionType( @NotNull BindingTrace trace, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java index 02a34b907f4..738d33e8853 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -138,12 +138,6 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin @Override @NotNull - public final void checkType(@NotNull KtExpression expression, ExpressionTypingContext context) { - components.dataFlowAnalyzer.checkType(getTypeInfo(expression, context).getType(), expression, context); - } - - @Override - @NotNull public final KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, ExpressionTypingContext context, boolean isStatement) { ExpressionTypingContext newContext = context; if (CodeFragmentUtilKt.suppressDiagnosticsInDebugMode(expression)) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index 504db684142..323faf5f2e3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -180,7 +180,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre ) if (functionTypeExpected) { - components.dataFlowAnalyzer.checkType(resultType, expression, context.replaceExpectedType(resultType)) + // all checks were done before return createTypeInfo(resultType, context) } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 786cbfe303a..aa07ecb8aa5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -53,10 +53,15 @@ open class DefaultArgumentStubGenerator( } private fun lower(irFunction: IrFunction): List<IrFunction>? { - val visibility = defaultArgumentStubVisibility(irFunction) val newIrFunction = - irFunction.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods, forceSetOverrideSymbols, visibility) - ?: return null + irFunction.generateDefaultsFunction( + context, + skipInlineMethods, + skipExternalMethods, + forceSetOverrideSymbols, + defaultArgumentStubVisibility(irFunction), + useConstructorMarker(irFunction) + ) ?: return null if (newIrFunction.isFakeOverride) { return listOf(irFunction, newIrFunction) } @@ -185,7 +190,8 @@ open class DefaultArgumentStubGenerator( protected open fun IrBlockBodyBuilder.generateSuperCallHandlerCheckIfNeeded( irFunction: IrFunction, - newIrFunction: IrFunction) { + newIrFunction: IrFunction + ) { //NO-OP Stub } @@ -202,6 +208,8 @@ open class DefaultArgumentStubGenerator( protected open fun defaultArgumentStubVisibility(function: IrFunction) = Visibilities.PUBLIC + protected open fun useConstructorMarker(function: IrFunction) = function is IrConstructor + private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } } @@ -310,15 +318,20 @@ open class DefaultParameterInjector( val startOffset = expression.startOffset val endOffset = expression.endOffset val declaration = expression.symbol.owner - val visibility = defaultArgumentStubVisibility(declaration) // We *have* to find the actual function here since on the JVM, a default stub for a function implemented // in an interface does not leave an abstract method after being moved to DefaultImpls (see InterfaceLowering). // Calling the fake override on an implementation of that interface would then result in a call to a method // that does not actually exist as DefaultImpls is not part of the inheritance hierarchy. val stubFunction = declaration.findBaseFunctionWithDefaultArguments(skipInline, skipExternalMethods) - ?.generateDefaultsFunction(context, skipInline, skipExternalMethods, forceSetOverrideSymbols, visibility) - ?: return null + ?.generateDefaultsFunction( + context, + skipInline, + skipExternalMethods, + forceSetOverrideSymbols, + defaultArgumentStubVisibility(declaration), + useConstructorMarker(declaration) + ) ?: return null log { "$declaration -> $stubFunction" } @@ -367,6 +380,8 @@ open class DefaultParameterInjector( protected open fun defaultArgumentStubVisibility(function: IrFunction) = Visibilities.PUBLIC + protected open fun useConstructorMarker(function: IrFunction) = function is IrConstructor + private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" } } @@ -416,7 +431,8 @@ private fun IrFunction.generateDefaultsFunction( skipInlineMethods: Boolean, skipExternalMethods: Boolean, forceSetOverrideSymbols: Boolean, - visibility: Visibility + visibility: Visibility, + useConstructorMarker: Boolean ): IrFunction? { if (skipInlineMethods && isInline) return null if (skipExternalMethods && isExternalOrInheritedFromExternal()) return null @@ -425,7 +441,7 @@ private fun IrFunction.generateDefaultsFunction( if (this is IrSimpleFunction) { // If this is an override of a function with default arguments, produce a fake override of a default stub. if (overriddenSymbols.any { it.owner.findBaseFunctionWithDefaultArguments(skipInlineMethods, skipExternalMethods) != null }) - return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FAKE_OVERRIDE, visibility, isFakeOverride = true).also { + return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FAKE_OVERRIDE, visibility, true, useConstructorMarker).also { context.mapping.defaultArgumentsDispatchFunction[this] = it context.mapping.defaultArgumentsOriginalFunction[it] = this @@ -436,7 +452,8 @@ private fun IrFunction.generateDefaultsFunction( skipInlineMethods, skipExternalMethods, forceSetOverrideSymbols, - visibility + visibility, + useConstructorMarker )?.symbol as IrSimpleFunctionSymbol? } } @@ -454,7 +471,7 @@ private fun IrFunction.generateDefaultsFunction( // binaries, it's way too late to fix it. Hence the workaround. if (valueParameters.any { it.defaultValue != null }) { return generateDefaultsFunctionImpl( - context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility, isFakeOverride = false + context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility, false, useConstructorMarker ).also { context.mapping.defaultArgumentsDispatchFunction[this] = it context.mapping.defaultArgumentsOriginalFunction[it] = this @@ -467,7 +484,8 @@ private fun IrFunction.generateDefaultsFunctionImpl( context: CommonBackendContext, newOrigin: IrDeclarationOrigin, newVisibility: Visibility, - isFakeOverride: Boolean + isFakeOverride: Boolean, + useConstructorMarker: Boolean ): IrFunction { val newFunction = when (this) { is IrConstructor -> @@ -515,7 +533,7 @@ private fun IrFunction.generateDefaultsFunctionImpl( for (i in 0 until (valueParameters.size + 31) / 32) { newFunction.addValueParameter("mask$i".synthesizedString, context.irBuiltIns.intType, IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION) } - if (this is IrConstructor) { + if (useConstructorMarker) { val markerType = context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable() newFunction.addValueParameter("marker".synthesizedString, markerType, IrDeclarationOrigin.DEFAULT_CONSTRUCTOR_MARKER) } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt index 8385567a2e5..2500c038043 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt @@ -196,7 +196,8 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass } private fun createKTypeParameter(typeParameter: IrTypeParameter, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression { - if (typeParameter in visitedTypeParams) return buildCall(context.intrinsics.getStarKTypeProjection!!) + // See KT-40173 + if (typeParameter in visitedTypeParams) TODO("Non-reified type parameters with recursive bounds are not supported yet") visitedTypeParams.add(typeParameter) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt index 7c5be4888ce..3e82f658a7e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt @@ -31,6 +31,7 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object SYNTHETIC_INLINE_CLASS_MEMBER : IrDeclarationOriginImpl("SYNTHETIC_INLINE_CLASS_MEMBER", isSynthetic = true) object INLINE_CLASS_GENERATED_IMPL_METHOD : IrDeclarationOriginImpl("INLINE_CLASS_GENERATED_IMPL_METHOD") object STATIC_INLINE_CLASS_REPLACEMENT : IrDeclarationOriginImpl("STATIC_INLINE_CLASS_REPLACEMENT") + object STATIC_INLINE_CLASS_CONSTRUCTOR : IrDeclarationOriginImpl("STATIC_INLINE_CLASS_CONSTRUCTOR") object GENERATED_ASSERTION_ENABLED_FIELD : IrDeclarationOriginImpl("GENERATED_ASSERTION_ENABLED_FIELD", isSynthetic = true) object GENERATED_EXTENDED_MAIN : IrDeclarationOriginImpl("GENERATED_EXTENDED_MAIN", isSynthetic = true) object SUSPEND_IMPL_STATIC_FUNCTION : IrDeclarationOriginImpl("SUSPEND_IMPL_STATIC_FUNCTION", isSynthetic = true) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt index 1d3bd1aa38a..01b8170d3ef 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt @@ -136,7 +136,6 @@ object JvmBackendFacade { if (loweredClass !is IrClass) { throw AssertionError("File-level declaration should be IrClass after JvmLower, got: " + loweredClass.render()) } - ClassCodegen.getOrCreate(loweredClass, context).generate() } } catch (e: Throwable) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index 9866e204902..c8eceebd32f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering import org.jetbrains.kotlin.backend.common.lower.allOverridden import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor @@ -119,9 +120,9 @@ private fun IrFunction.isBridgeToSuspendImplMethod(): Boolean = } private fun IrFunction.isStaticInlineClassReplacementDelegatingCall(): Boolean = - this is IrAttributeContainer && origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT && + this is IrAttributeContainer && !isStaticInlineClassReplacement && parentAsClass.declarations.find { it is IrAttributeContainer && it.attributeOwnerId == attributeOwnerId && it !== this } - ?.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT + ?.isStaticInlineClassReplacement == true internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspendOfContinuation() && // These are tail-call bridges and do not require any bytecode modifications. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt index bf3f3d98f9c..db2f875b2fe 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault +import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -313,7 +314,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { // remapped name or signature and forward to the actually declared method. if (caller.origin == IrDeclarationOrigin.BRIDGE || caller.origin == IrDeclarationOrigin.BRIDGE_SPECIAL) return null // Do not remap calls to static replacements of inline class methods, since they have completely different signatures. - if (callee.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT) return null + if (callee.isStaticInlineClassReplacement) return null val overriddenSpecialBuiltinFunction = callee.descriptor.original.getOverriddenBuiltinReflectingJvmDescriptor() if (overriddenSpecialBuiltinFunction != null && !superCall) { return mapSignatureSkipGeneric(context.referenceFunction(overriddenSpecialBuiltinFunction.original).owner) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index 22235c01a49..520b3083541 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -345,3 +345,7 @@ fun IrProperty.needsAccessor(accessor: IrSimpleFunction): Boolean = when { // We do not produce default accessors for private fields else -> accessor.origin != IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR || !Visibilities.isPrivate(accessor.visibility) } + +val IrDeclaration.isStaticInlineClassReplacement: Boolean + get() = origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT + || origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt index 184990f3938..4210f88652d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.* import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.backend.jvm.ir.defaultValue +import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement import org.jetbrains.kotlin.backend.jvm.localDeclarationsPhase import org.jetbrains.kotlin.codegen.coroutines.* import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX @@ -640,7 +641,7 @@ private fun IrFunction.suspendFunctionViewOrStub(context: JvmBackendContext): Ir } internal fun IrFunction.suspendFunctionOriginal(): IrFunction = - if (this is IrSimpleFunction && isSuspend && origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT) + if (this is IrSimpleFunction && isSuspend && !isStaticInlineClassReplacement) attributeOwnerId as IrFunction else this diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt index 6c2c8646f0c..b8d5ff8b5bd 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irNot import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* @@ -48,6 +49,9 @@ class JvmDefaultArgumentStubGenerator(override val context: JvmBackendContext) : override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub() + override fun useConstructorMarker(function: IrFunction): Boolean = + function is IrConstructor || function.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR + override fun IrBlockBodyBuilder.generateSuperCallHandlerCheckIfNeeded( irFunction: IrFunction, newIrFunction: IrFunction diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt index 9f59400fa53..61af4736a82 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt @@ -7,8 +7,10 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.ir.defaultValue import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub +import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -27,4 +29,7 @@ class JvmDefaultParameterInjector(context: JvmBackendContext) : } override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub() + + override fun useConstructorMarker(function: IrFunction): Boolean = + function is IrConstructor || function.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt index caf47ec5443..69140701f81 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt @@ -9,25 +9,19 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom -import org.jetbrains.kotlin.backend.common.lower.allOverridden import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.codegen.MethodSignatureMapper -import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.* -import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.inlineClassFieldName import org.jetbrains.kotlin.config.ApiVersion -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addConstructor -import org.jetbrains.kotlin.ir.builders.declarations.addFunction import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt index dd60afc9f39..b17ee69a13a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companio import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.calculateOwnerKClass import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.kClassToJavaClass import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi +import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineClassFieldGetter import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrStatement @@ -119,7 +120,8 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class // private properties in multifile-part classes. val needsDummySignature = getter.owner.correspondingPropertySymbol?.owner?.needsAccessor(getter.owner) == false || - getter.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR && getter.owner.parentAsClass.isInline + // Internal underlying vals of inline classes have no getter method + getter.owner.isInlineClassFieldGetter && getter.owner.visibility == Visibilities.INTERNAL putValueArgument( 0, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt index 9e292ea7be4..985acc9de83 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/VarargLowering.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly val varargPhase = makeIrFilePhase( @@ -103,7 +102,7 @@ private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass, context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) private val IrFunctionSymbol.isArrayOf: Boolean - get() = this.descriptor.name == Name.identifier("arrayOf") || owner.isArrayOf + get() = owner.isArrayOf private val IrFunctionSymbol.isEmptyArray: Boolean get() = owner.name.asString() == "emptyArray" && diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt index f695511e9a2..7b118bc18a6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTypeParameters import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.Modality @@ -47,9 +48,14 @@ class MemoizedInlineClassReplacements(private val mangleReturnTypes: Boolean) { // Don't mangle anonymous or synthetic functions it.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA || (it.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR && it.visibility == Visibilities.LOCAL) || - it.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT || - it.origin.isSynthetic || - it.isInlineClassFieldGetter -> null + it.isStaticInlineClassReplacement || + it.origin.isSynthetic -> null + + it.isInlineClassFieldGetter -> + if (it.hasMangledReturnType) + createMethodReplacement(it) + else + null // Mangle all functions in the body of an inline class it.parent.safeAs<IrClass>()?.isInline == true -> @@ -183,10 +189,17 @@ class MemoizedInlineClassReplacements(private val mangleReturnTypes: Boolean) { body: IrFunctionImpl.() -> Unit ) = buildFunWithDescriptorForInlining(function.descriptor) { updateFrom(function) - origin = if (function.origin == IrDeclarationOrigin.GENERATED_INLINE_CLASS_MEMBER) { - JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD - } else { - replacementOrigin + if (function is IrConstructor) { + // The [updateFrom] call will set the modality to FINAL for constructors, while the JVM backend would use OPEN here. + modality = Modality.OPEN + } + origin = when { + function.origin == IrDeclarationOrigin.GENERATED_INLINE_CLASS_MEMBER -> + JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD + function is IrConstructor && function.constructedClass.isInline -> + JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR + else -> + replacementOrigin } if (noFakeOverride) { isFakeOverride = false diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt index 4c0544f2e28..80e72651e0a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt @@ -133,7 +133,7 @@ class StandaloneDeclarationGenerator(private val context: GeneratorContext) { protected fun generateValueParameterDeclarations( irFunction: IrFunction, functionDescriptor: FunctionDescriptor, - defaultArgumentFactory: IrFunction.(ValueParameterDescriptor) -> IrExpressionBody? + defaultArgumentFactory: IrFunction.(IrValueParameter) -> IrExpressionBody? ) { // TODO: KtElements @@ -150,14 +150,14 @@ class StandaloneDeclarationGenerator(private val context: GeneratorContext) { irFunction.valueParameters = functionDescriptor.valueParameters.map { valueParameterDescriptor -> val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter declareParameter(valueParameterDescriptor, ktParameter, irFunction).also { - it.defaultValue = irFunction.defaultArgumentFactory(valueParameterDescriptor) + it.defaultValue = irFunction.defaultArgumentFactory(it) } } } fun generateConstructor( startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassConstructorDescriptor, symbol: IrConstructorSymbol, - defaultArgumentFactory: IrFunction.(ValueParameterDescriptor) -> IrExpressionBody? = { null } + defaultArgumentFactory: IrFunction.(IrValueParameter) -> IrExpressionBody? = { null } ): IrConstructor { val irConstructor = IrConstructorImpl(startOffset, endOffset, origin, symbol, IrUninitializedType, descriptor) irConstructor.metadata = MetadataSource.Function(descriptor) @@ -178,7 +178,7 @@ class StandaloneDeclarationGenerator(private val context: GeneratorContext) { fun generateSimpleFunction( startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: FunctionDescriptor, symbol: IrSimpleFunctionSymbol, - defaultArgumentFactory: IrFunction.(ValueParameterDescriptor) -> IrExpressionBody? = { null } + defaultArgumentFactory: IrFunction.(IrValueParameter) -> IrExpressionBody? = { null } ): IrSimpleFunction { val irFunction = IrFunctionImpl(startOffset, endOffset, origin, symbol, IrUninitializedType, descriptor) irFunction.metadata = MetadataSource.Function(descriptor) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt index 23dd2527b4e..81290af1863 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt @@ -31,16 +31,15 @@ class SyntheticDeclarationsGenerator(context: GeneratorContext) : DeclarationDes return this } - private val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT) - - private fun IrFunction.defaultArgumentFactory(descriptor: ValueParameterDescriptor): IrExpressionBody? { + private fun IrFunction.defaultArgumentFactory(parameter: IrValueParameter): IrExpressionBody? { + val descriptor = parameter.descriptor as ValueParameterDescriptor if (!descriptor.declaresDefaultValue()) return null val description = "Default Argument Value stub for ${descriptor.name}|${descriptor.index}" - return IrExpressionBodyImpl(IrErrorExpressionImpl(startOffset, endOffset, errorType, description)) + return IrExpressionBodyImpl(IrErrorExpressionImpl(startOffset, endOffset, parameter.type, description)) } - private val defaultFactoryReference: IrFunction.(ValueParameterDescriptor) -> IrExpressionBody? = { defaultArgumentFactory(it) } + private val defaultFactoryReference: IrFunction.(IrValueParameter) -> IrExpressionBody? = { defaultArgumentFactory(it) } override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: IrDeclarationContainer?) { error("Unexpected declaration descriptor $descriptor") diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index 1971de08751..aded9a24f6e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.util.coerceToUnit +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -341,9 +342,7 @@ internal class InsertImplicitCasts( val notNullableExpectedType = expectedType.makeNotNullable() - // NOTE(lmr): originalKotlinType can sometimes be null and was causing a failure. Changing this - // to return this instead fixes it, but I am unsure if this is the proper fix. - val valueType = this.type.originalKotlinType ?: return this + val valueType = this.type.originalKotlinType ?: error("Expecting original kotlin type for IrType ${type.render()}") return when { expectedType.isUnit() -> diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFileImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFileImpl.kt index 8c5323a835f..ffa24d56888 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFileImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFileImpl.kt @@ -60,8 +60,8 @@ class IrFileImpl( } override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) { - for (i in 0 until declarations.size) { - declarations[i] = declarations[i].transform(transformer, data) as IrDeclaration + declarations.forEachIndexed { i, irDeclaration -> + declarations[i] = irDeclaration.transform(transformer, data) as IrDeclaration } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt index 86ba8ba0be6..c4cfb3fff5f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrPublicSymbolBase.kt @@ -26,11 +26,9 @@ abstract class IrBindablePublicSymbolBase<out D : DeclarationDescriptor, B : IrS IrBindableSymbol<D, B>, IrPublicSymbolBase<D>(descriptor, sig) { init { - /* assert(isOriginalDescriptor(descriptor)) { "Substituted descriptor $descriptor for ${descriptor.original}" } - */ assert(sig.isPublic) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 9031324bee9..a378750ed38 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -139,11 +139,9 @@ open class SymbolTable( inline fun referenced(d: D, orElse: () -> S): S { @Suppress("UNCHECKED_CAST") val d0 = d.original as D - // NOTE(lmr): Inner classes seem to fail this assertion right now. Commenting out - // appears to fix, but it is probably not fixing the underlying issue. See b/130241466 -// assert(d0 === d) { -// "Non-original descriptor in declaration: $d\n\tExpected: $d0" -// } + assert(d0 === d) { + "Non-original descriptor in declaration: $d\n\tExpected: $d0" + } val s = get(d0) if (s == null) { val new = orElse() diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 501bd9ff318..74201710f85 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -310,7 +310,6 @@ fun GeneratorContext.generateModuleFragmentWithPlugins( ): IrModuleFragment { val signaturer = IdSignatureDescriptor(JsManglerDesc) val psi2Ir = Psi2IrTranslator(languageVersionSettings, configuration, signaturer) - val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable) val extensions = IrGenerationExtension.getInstances(project) diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractKotlinParsing.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractKotlinParsing.java index fc583c1d93d..0af6879e70c 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractKotlinParsing.java +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractKotlinParsing.java @@ -50,7 +50,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; } } - public final SemanticWhitespaceAwarePsiBuilder myBuilder; + protected final SemanticWhitespaceAwarePsiBuilder myBuilder; public AbstractKotlinParsing(SemanticWhitespaceAwarePsiBuilder builder) { this.myBuilder = builder; @@ -65,11 +65,11 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; return myBuilder.rawLookup(-i); } - public boolean expect(KtToken expectation, String message) { + protected boolean expect(KtToken expectation, String message) { return expect(expectation, message, null); } - public PsiBuilder.Marker mark() { + protected PsiBuilder.Marker mark() { return myBuilder.mark(); } @@ -101,7 +101,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; error(message); } - public void errorWithRecovery(String message, TokenSet recoverySet) { + protected void errorWithRecovery(String message, TokenSet recoverySet) { IElementType tt = tt(); if (recoverySet == null || recoverySet.contains(tt) || @@ -114,7 +114,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; } } - public void errorAndAdvance(String message) { + protected void errorAndAdvance(String message) { errorAndAdvance(message, 1); } @@ -128,7 +128,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; return myBuilder.eof(); } - public void advance() { + protected void advance() { // TODO: how to report errors on bad characters? (Other than highlighting) myBuilder.advanceLexer(); } @@ -166,7 +166,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; return false; } - public boolean at(IElementType expectation) { + protected boolean at(IElementType expectation) { if (_at(expectation)) return true; IElementType token = tt(); if (token == IDENTIFIER && expectation instanceof KtKeywordToken) { @@ -207,11 +207,11 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; return false; } - public boolean atSet(IElementType... tokens) { + protected boolean atSet(IElementType... tokens) { return atSet(TokenSet.create(tokens)); } - public boolean atSet(TokenSet set) { + protected boolean atSet(TokenSet set) { if (_atSet(set)) return true; IElementType token = tt(); if (token == IDENTIFIER) { @@ -233,7 +233,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*; return false; } - public IElementType lookahead(int k) { + protected IElementType lookahead(int k) { return myBuilder.lookAhead(k); } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt index 1220fa17d82..56a1d5a0118 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt @@ -186,7 +186,8 @@ class CallableReferencesCandidateFactory( val scopeTower: ImplicitScopeTower, val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit, val expectedType: UnwrappedType?, - private val csBuilder: ConstraintSystemOperation + private val csBuilder: ConstraintSystemOperation, + private val resolutionCallbacks: KotlinResolutionCallbacks ) : CandidateFactory<CallableReferenceCandidate> { fun createCallableProcessor(explicitReceiver: DetailedReceiver?) = @@ -212,8 +213,19 @@ class CallableReferencesCandidateFactory( callComponents.builtIns ) + fun createReferenceCandidate(): CallableReferenceCandidate = + CallableReferenceCandidate( + candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver, + explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation, diagnostics + ) + + if (callComponents.statelessCallbacks.isHiddenInResolution(candidateDescriptor, argument, resolutionCallbacks)) { + diagnostics.add(HiddenDescriptor) + return createReferenceCandidate() + } + if (needCompatibilityResolveForCallableReference(callableReferenceAdaptation, candidateDescriptor)) { - diagnostics.add(LowerPriorityToPreserveCompatibility) + markCandidateForCompatibilityResolve(diagnostics) } if (callableReferenceAdaptation != null && @@ -254,10 +266,7 @@ class CallableReferencesCandidateFactory( ) } - return CallableReferenceCandidate( - candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver, - explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation, diagnostics - ) + return createReferenceCandidate() } private fun needCompatibilityResolveForCallableReference( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt index 809b2223de8..73c45f5a653 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor -import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.FlatSignature import org.jetbrains.kotlin.resolve.calls.results.OverloadingConflictResolver @@ -76,13 +75,14 @@ class CallableReferenceResolver( fun processCallableReferenceArgument( csBuilder: ConstraintSystemBuilder, resolvedAtom: ResolvedCallableReferenceAtom, - diagnosticsHolder: KotlinDiagnosticsHolder + diagnosticsHolder: KotlinDiagnosticsHolder, + resolutionCallbacks: KotlinResolutionCallbacks ) { val argument = resolvedAtom.atom val expectedType = resolvedAtom.expectedType?.let { (csBuilder.buildCurrentSubstitutor() as NewTypeSubstitutor).safeSubstitute(it) } val scopeTower = callComponents.statelessCallbacks.getScopeTowerForCallableReferenceArgument(argument) - val candidates = runRHSResolution(scopeTower, argument, expectedType, csBuilder) { checkCallableReference -> + val candidates = runRHSResolution(scopeTower, argument, expectedType, csBuilder, resolutionCallbacks) { checkCallableReference -> csBuilder.runTransaction { checkCallableReference(this); false } } @@ -144,10 +144,11 @@ class CallableReferenceResolver( callableReference: CallableReferenceKotlinCallArgument, expectedType: UnwrappedType?, // this type can have not fixed type variable inside csBuilder: ConstraintSystemBuilder, + resolutionCallbacks: KotlinResolutionCallbacks, compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be rolled back ): Set<CallableReferenceCandidate> { val factory = CallableReferencesCandidateFactory( - callableReference, callComponents, scopeTower, compatibilityChecker, expectedType, csBuilder + callableReference, callComponents, scopeTower, compatibilityChecker, expectedType, csBuilder, resolutionCallbacks ) val processor = createCallableReferenceProcessor(factory) val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true, name = callableReference.rhsName) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index 6bfcd1aacd1..4262dae37a8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.UnwrappedType @@ -27,6 +28,10 @@ interface KotlinResolutionStatelessCallbacks { fun isOperatorCall(kotlinCall: KotlinCall): Boolean fun isSuperOrDelegatingConstructorCall(kotlinCall: KotlinCall): Boolean fun isHiddenInResolution( + descriptor: DeclarationDescriptor, kotlinCallArgument: KotlinCallArgument, resolutionCallbacks: KotlinResolutionCallbacks + ): Boolean + + fun isHiddenInResolution( descriptor: DeclarationDescriptor, kotlinCall: KotlinCall, resolutionCallbacks: KotlinResolutionCallbacks ): Boolean @@ -36,6 +41,8 @@ interface KotlinResolutionStatelessCallbacks { fun isCoroutineCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean + fun isOldIntersectionIsEmpty(types: Collection<KotlinType>): Boolean + fun createConstraintSystemForOverloadResolution( constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns ): SimpleConstraintSystem diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index 53e217c4ca3..43b884e7d12 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem -import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible +import org.jetbrains.kotlin.resolve.calls.inference.addEqualityConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle @@ -101,11 +101,8 @@ class KotlinCallCompleter( return candidates } - val newAtoms = mutableMapOf<KotlinResolutionCandidate, ResolvedLambdaAtom>() - for ((candidate, atom) in lambdas.entries) { - val newAtom = kotlinConstraintSystemCompleter.prepareLambdaAtomForFactoryPattern(atom, candidate, candidate) - newAtoms[candidate] = newAtom - candidate.addResolvedKtPrimitive(newAtom) + val newAtoms = lambdas.mapValues { (candidate, atom) -> + kotlinConstraintSystemCompleter.prepareLambdaAtomForFactoryPattern(atom, candidate, candidate) } val diagnosticHolderForLambda = KotlinDiagnosticsHolder.SimpleHolder() @@ -285,7 +282,7 @@ class KotlinCallCompleter( } expectedType === TypeUtils.UNIT_EXPECTED_TYPE -> - csBuilder.addSubtypeConstraintIfCompatible( + csBuilder.addEqualityConstraintIfCompatible( returnType, csBuilder.builtIns.unitType, ExpectedTypeConstraintPosition(resolvedCall.atom) ) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt index 5b627811850..b3480170c80 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt @@ -35,7 +35,6 @@ class PostponedArgumentsAnalyzer( fun canBeProper(type: KotlinTypeMarker): Boolean fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean - fun hasEqualNothingConstraint(type: KotlinTypeMarker): Boolean // mutable operations fun addOtherSystem(otherSystem: ConstraintStorage) @@ -59,7 +58,7 @@ class PostponedArgumentsAnalyzer( ) is ResolvedCallableReferenceAtom -> - callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder) + callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder, resolutionCallbacks) is ResolvedCollectionLiteralAtom -> TODO("Not supported") @@ -123,7 +122,7 @@ class PostponedArgumentsAnalyzer( c.canBeProper(rawReturnType) -> substitute(rawReturnType) // For Unit-coercion - c.hasUpperOrEqualUnitConstraint(rawReturnType) && !c.hasEqualNothingConstraint(rawReturnType) -> builtIns.unitType + c.hasUpperOrEqualUnitConstraint(rawReturnType) -> builtIns.unitType else -> null } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 19a6decf14a..8117f10a9eb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -28,6 +28,8 @@ import org.jetbrains.kotlin.types.model.typeConstructor import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable +import org.jetbrains.kotlin.utils.SmartList +import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal object CheckVisibility : ResolutionPart() { @@ -249,6 +251,24 @@ internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() { } } +internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPart() { + override fun KotlinResolutionCandidate.process(workIndex: Int) { + for ((_, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) { + val constraints = variableWithConstraints.constraints.filter { csBuilder.isProperType(it.type) } + + if (constraints.size <= 1) continue + if (constraints.any { it.kind.isLower() || it.kind.isEqual() }) continue + + // See TypeBoundsImpl.computeValues(). It returns several values for such situation which means an error in OI + if (callComponents.statelessCallbacks.isOldIntersectionIsEmpty(constraints.map { it.type }.cast())) { + markCandidateForCompatibilityResolve() + return + } + } + + } +} + internal object CheckExplicitReceiverKindConsistency : ResolutionPart() { private fun KotlinResolutionCandidate.hasError(): Nothing = error( @@ -314,27 +334,28 @@ internal object CollectionTypeVariableUsagesInfo : ResolutionPart() { dependentTypeParametersSeen: List<Pair<TypeConstructorMarker, KotlinTypeMarker?>> = listOf() ): List<Pair<TypeConstructorMarker, KotlinTypeMarker?>> { val context = asConstraintSystemCompleterContext() - val dependentTypeParameters = getBuilder().currentStorage().notFixedTypeVariables.mapNotNull { (typeConstructor, constraints) -> - val upperBounds = constraints.constraints.filter { - it.position.from is DeclaredUpperBoundConstraintPosition && it.kind == ConstraintKind.UPPER - } + val dependentTypeParameters = getBuilder().currentStorage().notFixedTypeVariables.asSequence() + .flatMap { (typeConstructor, constraints) -> + val upperBounds = constraints.constraints.filter { + it.position.from is DeclaredUpperBoundConstraintPosition && it.kind == ConstraintKind.UPPER + } - upperBounds.mapNotNull { constraint -> - if (constraint.type.typeConstructor(context) != variable) { - val suitableUpperBound = upperBounds.find { upperBound -> - with(context) { upperBound.type.contains { it.typeConstructor() == variable } } - }?.type + upperBounds.mapNotNull { constraint -> + if (constraint.type.typeConstructor(context) != variable) { + val suitableUpperBound = upperBounds.find { upperBound -> + with(context) { upperBound.type.contains { it.typeConstructor() == variable } } + }?.type - if (suitableUpperBound != null) typeConstructor to suitableUpperBound else null - } else typeConstructor to null - } - }.flatten().filter { it !in dependentTypeParametersSeen && it.first != variable } + if (suitableUpperBound != null) typeConstructor to suitableUpperBound else null + } else typeConstructor to null + } + }.filter { it !in dependentTypeParametersSeen && it.first != variable }.toList() - return dependentTypeParameters + dependentTypeParameters.mapNotNull { (typeConstructor, _) -> + return dependentTypeParameters + dependentTypeParameters.flatMapTo(SmartList()) { (typeConstructor, _) -> if (typeConstructor != variable) { getDependentTypeParameters(typeConstructor, dependentTypeParameters + dependentTypeParametersSeen) - } else null - }.flatten() + } else emptyList() + } } private fun NewConstraintSystem.isContainedInInvariantOrContravariantPositionsAmongUpperBound( @@ -617,7 +638,7 @@ internal object EagerResolveOfCallableReferences : ResolutionPart() { getSubResolvedAtoms() .filterIsInstance<EagerCallableReferenceAtom>() .forEach { - callableReferenceResolver.processCallableReferenceArgument(csBuilder, it, this) + callableReferenceResolver.processCallableReferenceArgument(csBuilder, it, this, resolutionCallbacks) } } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt index 1615b5ba61b..2f8a441c1c8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt @@ -91,7 +91,7 @@ object SamTypeConversions : ParameterTypeConversion { ) if (needCompatibilityResolveForSAM(candidate, expectedParameterType)) { - candidate.addDiagnostic(LowerPriorityToPreserveCompatibility) + candidate.markCandidateForCompatibilityResolve() } val samDescriptor = originalExpectedType.constructor.declarationDescriptor diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SuspendConversionUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SuspendConversionUtils.kt index a3e469b3a50..c2c35b279d0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SuspendConversionUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SuspendConversionUtils.kt @@ -52,7 +52,7 @@ object SuspendTypeConversions : ParameterTypeConversion { candidate.resolvedCall.registerArgumentWithSuspendConversion(argument, nonSuspendParameterType) - candidate.addDiagnostic(LowerPriorityToPreserveCompatibility) + candidate.markCandidateForCompatibilityResolve() return nonSuspendParameterType } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/UnitTypeConversions.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/UnitTypeConversions.kt index b9fee3061ac..0becae26121 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/UnitTypeConversions.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/UnitTypeConversions.kt @@ -7,10 +7,11 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.descriptors.ParameterDescriptor -import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility +import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.model.markCandidateForCompatibilityResolve import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.isDynamic @@ -27,8 +28,8 @@ object UnitTypeConversions : ParameterTypeConversion { if (argument !is SimpleKotlinCallArgument) return true val receiver = argument.receiver - if (receiver.receiverValue.type.hasUnitOrSubtypeReturnType()) return true - if (receiver.typesFromSmartCasts.any { it.hasUnitOrSubtypeReturnType() }) return true + if (receiver.receiverValue.type.hasUnitOrSubtypeReturnType(candidate.csBuilder)) return true + if (receiver.typesFromSmartCasts.any { it.hasUnitOrSubtypeReturnType(candidate.csBuilder) }) return true if ( !expectedParameterType.isBuiltinFunctionalType || @@ -38,10 +39,15 @@ object UnitTypeConversions : ParameterTypeConversion { return false } - private fun KotlinType.hasUnitOrSubtypeReturnType(): Boolean = - isFunctionOrKFunctionTypeWithAnySuspendability && arguments.last().type.isUnitOrSubtype() + private fun KotlinType.hasUnitOrSubtypeReturnType(c: ConstraintSystemOperation): Boolean = + isFunctionOrKFunctionTypeWithAnySuspendability && arguments.last().type.isUnitOrSubtypeOrVariable(c) + + private fun KotlinType.isUnitOrSubtypeOrVariable(c: ConstraintSystemOperation): Boolean = + isUnitOrSubtype() || c.isTypeVariable(this) + + private fun KotlinType.isUnitOrSubtype(): Boolean = + isUnit() || isDynamic() || isNothing() - private fun KotlinType.isUnitOrSubtype(): Boolean = isUnit() || isDynamic() || isNothing() override fun conversionIsNeededBeforeSubtypingCheck(argument: KotlinCallArgument): Boolean = argument is SimpleKotlinCallArgument && argument.receiver.stableType.isFunctionType @@ -52,7 +58,7 @@ object UnitTypeConversions : ParameterTypeConversion { var isFunctionTypeOrSubtype = false val hasReturnTypeInSubtypes = argument.receiver.stableType.isFunctionTypeOrSubtype { isFunctionTypeOrSubtype = true - it.getReturnTypeFromFunctionType().isUnitOrSubtype() + it.getReturnTypeFromFunctionType().isUnitOrSubtype() // there is no need to check for variable as it was done earlier } if (!isFunctionTypeOrSubtype) return false @@ -78,7 +84,7 @@ object UnitTypeConversions : ParameterTypeConversion { candidate.resolvedCall.registerArgumentWithUnitConversion(argument, nonUnitReturnedParameterType) - candidate.addDiagnostic(LowerPriorityToPreserveCompatibility) + candidate.markCandidateForCompatibilityResolve() return nonUnitReturnedParameterType } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt index 5f427d3b707..63d31ab71c2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.calls.inference import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer +import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument @@ -62,9 +63,30 @@ fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible( lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition +): Boolean = + addConstraintIfCompatible(lowerType, upperType, position, ConstraintKind.LOWER) + +fun ConstraintSystemBuilder.addEqualityConstraintIfCompatible( + lowerType: KotlinTypeMarker, + upperType: KotlinTypeMarker, + position: ConstraintPosition +): Boolean = + addConstraintIfCompatible(lowerType, upperType, position, ConstraintKind.EQUALITY) + +private fun ConstraintSystemBuilder.addConstraintIfCompatible( + lowerType: KotlinTypeMarker, + upperType: KotlinTypeMarker, + position: ConstraintPosition, + kind: ConstraintKind ) = runTransaction { - if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position) + if (!hasContradiction) { + when (kind) { + ConstraintKind.LOWER -> addSubtypeConstraint(lowerType, upperType, position) + ConstraintKind.UPPER -> addSubtypeConstraint(upperType, lowerType, position) + ConstraintKind.EQUALITY -> addEqualityConstraint(lowerType, upperType, position) + } + } !hasContradiction } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt index 2d6240bacd5..f2a6d3d739e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstit import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* +import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -98,7 +99,7 @@ class ConstraintIncorporator( for (otherTypeVariable in otherInMyConstraint) { // to avoid ConcurrentModificationException - val otherConstraints = ArrayList(this.getConstraintsForVariable(otherTypeVariable)) + val otherConstraints = SmartList(this.getConstraintsForVariable(otherTypeVariable)) for (otherConstraint in otherConstraints) { generateNewConstraint(typeVariable, constraint, otherTypeVariable, otherConstraint) } @@ -231,7 +232,7 @@ class ConstraintIncorporator( ) ) return - val derivedFrom = (baseConstraint.derivedFrom + otherConstraint.derivedFrom).toMutableSet() + val derivedFrom = SmartSet.create(baseConstraint.derivedFrom).also { it.addAll(otherConstraint.derivedFrom) } if (otherVariable in derivedFrom) return derivedFrom.add(otherVariable) @@ -274,7 +275,7 @@ class ConstraintIncorporator( } fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> = - getNestedArguments(type).mapNotNull { getTypeVariable(it.getType().typeConstructor()) } + getNestedArguments(type).mapNotNullTo(SmartList()) { getTypeVariable(it.getType().typeConstructor()) } private fun KotlinTypeMarker.substitute(c: Context, typeVariable: TypeVariableMarker, value: KotlinTypeMarker): KotlinTypeMarker { @@ -289,7 +290,7 @@ class ConstraintIncorporator( } private fun TypeSystemInferenceExtensionContext.getNestedArguments(type: KotlinTypeMarker): List<TypeArgumentMarker> { - val result = ArrayList<TypeArgumentMarker>() + val result = SmartList<TypeArgumentMarker>() val stack = ArrayDeque<TypeArgumentMarker>() when (type) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt index 7bf47656283..4a288a28568 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addToStdlib.safeAs class PostponedArgumentInputTypesResolver( @@ -21,7 +22,7 @@ class PostponedArgumentInputTypesResolver( ) { interface Context : KotlinConstraintSystemCompleter.Context - data class ParameterTypesInfo( + private class ParameterTypesInfo( val parametersFromDeclaration: List<UnwrappedType?>?, val parametersFromDeclarationOfRelatedLambdas: Set<List<UnwrappedType?>>?, val parametersFromConstraints: Set<List<TypeWithKind>>?, @@ -48,11 +49,11 @@ class PostponedArgumentInputTypesResolver( val dependentVariables = variableDependencyProvider.getShallowlyDependentVariables(typeVariableTypeConstructor).orEmpty() + typeVariableTypeConstructor - return dependentVariables.mapNotNull { type -> - val constraints = notFixedTypeVariables[type]?.constraints ?: return@mapNotNull null + return dependentVariables.flatMap { type -> + val constraints = notFixedTypeVariables[type]?.constraints ?: return@flatMap emptyList() val constraintsWithFunctionalType = constraints.filter { (it.type as? KotlinType)?.isBuiltinFunctionalTypeOrSubtype == true } constraintsWithFunctionalType.extractFunctionalTypes() - }.flatten() + } } private fun extractParameterTypesFromDeclaration(atom: ResolutionAtom) = @@ -81,32 +82,42 @@ class PostponedArgumentInputTypesResolver( val parameterTypesFromDeclaration = if (argument is LambdaWithTypeVariableAsExpectedTypeAtom) argument.parameterTypesFromDeclaration else null - val parameterTypesFromConstraints = functionalTypesFromConstraints?.map { typeWithKind -> + val parameterTypesFromConstraints = functionalTypesFromConstraints?.mapTo(SmartSet.create()) { typeWithKind -> typeWithKind.type.getPureArgumentsForFunctionalTypeOrSubtype().map { // We should use opposite kind as lambda's parameters are contravariant TypeWithKind(it, typeWithKind.direction.opposite()) } - }?.toSet() + } // An extension function flag can only come from a declaration of anonymous function: `select({ this + it }, fun Int.(x: Int) = 10)` val (parameterTypesFromDeclarationOfRelatedLambdas, isThereExtensionFunctionAmongRelatedLambdas) = getDeclaredParametersFromRelatedLambdas(argument, postponedArguments, variableDependencyProvider) val annotationsFromConstraints = functionalTypesFromConstraints?.run { - Annotations.create(map { it.type.annotations }.flatten()) + Annotations.create(flatMap { it.type.annotations }) } ?: Annotations.EMPTY val annotations = if (isThereExtensionFunctionAmongRelatedLambdas) { annotationsFromConstraints.withExtensionFunctionAnnotation(expectedType.builtIns) } else annotationsFromConstraints + var isSuspend = false + var isNullable = false + if (!functionalTypesFromConstraints.isNullOrEmpty()) { + isNullable = true + for (funType in functionalTypesFromConstraints) { + if (!isSuspend && funType.type.isSuspendFunctionTypeOrSubtype) isSuspend = true + if (isNullable && !funType.type.isMarkedNullable) isNullable = false + if (isSuspend && !isNullable) break + } + } return ParameterTypesInfo( parameterTypesFromDeclaration, parameterTypesFromDeclarationOfRelatedLambdas, parameterTypesFromConstraints, annotations, - isSuspend = !functionalTypesFromConstraints.isNullOrEmpty() && functionalTypesFromConstraints.any { it.type.isSuspendFunctionTypeOrSubtype }, - isNullable = !functionalTypesFromConstraints.isNullOrEmpty() && functionalTypesFromConstraints.all { it.type.isMarkedNullable } + isSuspend = isSuspend, + isNullable = isNullable ) } @@ -116,24 +127,28 @@ class PostponedArgumentInputTypesResolver( dependencyProvider: TypeVariableDependencyInformationProvider ): Pair<Set<List<UnwrappedType?>>?, Boolean> { val parameterTypesFromDeclarationOfRelatedLambdas = postponedArguments - .filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>() - .filter { it.parameterTypesFromDeclaration != null && it != argument } .mapNotNull { anotherArgument -> - val argumentExpectedTypeConstructor = argument.expectedType?.typeConstructor() ?: return@mapNotNull null - val anotherArgumentExpectedTypeConstructor = anotherArgument.expectedType.typeConstructor() - val areTypeVariablesRelated = dependencyProvider.areVariablesDependentShallowly( - argumentExpectedTypeConstructor, anotherArgumentExpectedTypeConstructor - ) - val anotherAtom = anotherArgument.atom - val isAnonymousExtensionFunction = anotherAtom is FunctionExpression && anotherAtom.receiverType != null - val parameterTypesFromDeclarationOfRelatedLambda = anotherArgument.parameterTypesFromDeclaration - - if (areTypeVariablesRelated && parameterTypesFromDeclarationOfRelatedLambda != null) { - parameterTypesFromDeclarationOfRelatedLambda to isAnonymousExtensionFunction - } else null + when { + anotherArgument !is LambdaWithTypeVariableAsExpectedTypeAtom -> null + anotherArgument.parameterTypesFromDeclaration == null || anotherArgument == argument -> null + else -> { + val argumentExpectedTypeConstructor = argument.expectedType?.typeConstructor() ?: return@mapNotNull null + val anotherArgumentExpectedTypeConstructor = anotherArgument.expectedType.typeConstructor() + val areTypeVariablesRelated = dependencyProvider.areVariablesDependentShallowly( + argumentExpectedTypeConstructor, anotherArgumentExpectedTypeConstructor + ) + val anotherAtom = anotherArgument.atom + val isAnonymousExtensionFunction = anotherAtom is FunctionExpression && anotherAtom.receiverType != null + val parameterTypesFromDeclarationOfRelatedLambda = anotherArgument.parameterTypesFromDeclaration + + if (areTypeVariablesRelated && parameterTypesFromDeclarationOfRelatedLambda != null) { + parameterTypesFromDeclarationOfRelatedLambda to isAnonymousExtensionFunction + } else null + } + } } - return parameterTypesFromDeclarationOfRelatedLambdas.run { map { it.first }.toSet() to any { it.second } } + return parameterTypesFromDeclarationOfRelatedLambdas.run { mapTo(SmartSet.create()) { it.first } to any { it.second } } } private fun Context.createTypeVariableForReturnType(argument: PostponedAtomWithRevisableExpectedType): NewTypeVariable { @@ -186,7 +201,8 @@ class PostponedArgumentInputTypesResolver( return allGroupedParameterTypes.mapIndexed { index, types -> val parameterTypeVariable = createTypeVariableForParameterType(argument, index) - for (typeWithKind in types.filterNotNull()) { + for (typeWithKind in types) { + if (typeWithKind == null) continue when (typeWithKind.direction) { ConstraintKind.EQUALITY -> csBuilder.addEqualityConstraint( parameterTypeVariable.defaultType, typeWithKind.type, ArgumentConstraintPosition(atom) @@ -327,29 +343,23 @@ class PostponedArgumentInputTypesResolver( dependencyProvider: TypeVariableDependencyInformationProvider ): Boolean { // We can collect parameter types from declaration in any mode, they can't change during completion. - val postponedArgumentsToCollectTypesFromDeclaredParameters = postponedArguments - .filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>() - .filter { it.parameterTypesFromDeclaration == null } - - for (argument in postponedArgumentsToCollectTypesFromDeclaredParameters) { + for (argument in postponedArguments) { + if (argument !is LambdaWithTypeVariableAsExpectedTypeAtom) continue + if (argument.parameterTypesFromDeclaration != null) continue argument.parameterTypesFromDeclaration = extractParameterTypesFromDeclaration(argument.atom) } - /* - * We can build new functional expected types in partial mode only for anonymous functions, - * because more exact type can't appear from constraints in full mode (anonymous functions have fully explicit declaration). - * It can be so for lambdas: for instance, an extension function type can appear in full mode (it may not be known in partial mode). - * - * TODO: investigate why we can't do it for anonymous functions in full mode always (see `diagnostics/tests/resolve/resolveWithSpecifiedFunctionLiteralWithId.kt`) - */ - val postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType = - if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL) { - postponedArguments.filter(::isAnonymousFunction) - } else { - postponedArguments - } - - return postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument -> + return postponedArguments.any { argument -> + /* + * We can build new functional expected types in partial mode only for anonymous functions, + * because more exact type can't appear from constraints in full mode (anonymous functions have fully explicit declaration). + * It can be so for lambdas: for instance, an extension function type can appear in full mode (it may not be known in partial mode). + * + * TODO: investigate why we can't do it for anonymous functions in full mode always (see `diagnostics/tests/resolve/resolveWithSpecifiedFunctionLiteralWithId.kt`) + */ + if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL && !isAnonymousFunction(argument)) + return@any false + if (argument.revisedExpectedType != null) return@any false val parameterTypesInfo = c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false val newExpectedType = @@ -393,26 +403,28 @@ class PostponedArgumentInputTypesResolver( listOf(typeConstructor) + relatedVariables.filterIsInstance<TypeVariableTypeConstructor>() } type.arguments.isNotEmpty() -> { - type.arguments.map { getAllDeeplyRelatedTypeVariables(it.type, variableDependencyProvider) }.flatten() + type.arguments.flatMap { getAllDeeplyRelatedTypeVariables(it.type, variableDependencyProvider) } } - else -> listOf() + else -> emptyList() } } - private fun getDeclaredParametersConsideringExtensionFunctionsPresence(parameterTypesInfo: ParameterTypesInfo): List<UnwrappedType?>? { - val (parametersFromDeclaration, _, parametersFromConstraints, annotations) = parameterTypesInfo - - if (parametersFromConstraints.isNullOrEmpty() || parametersFromDeclaration.isNullOrEmpty()) - return parametersFromDeclaration + private fun getDeclaredParametersConsideringExtensionFunctionsPresence(parameterTypesInfo: ParameterTypesInfo): List<UnwrappedType?>? = + with (parameterTypesInfo) { - val oneLessParameterInDeclarationThanInConstraints = parametersFromConstraints.first().size == parametersFromDeclaration.size + 1 + if (parametersFromConstraints.isNullOrEmpty() || parametersFromDeclaration.isNullOrEmpty()) + parametersFromDeclaration + else { + val oneLessParameterInDeclarationThanInConstraints = + parametersFromConstraints.first().size == parametersFromDeclaration.size + 1 - return if (oneLessParameterInDeclarationThanInConstraints && annotations.hasExtensionFunctionAnnotation()) { - listOf(null) + parametersFromDeclaration - } else { - parametersFromDeclaration + if (oneLessParameterInDeclarationThanInConstraints && annotations.hasExtensionFunctionAnnotation()) { + listOf(null) + parametersFromDeclaration + } else { + parametersFromDeclaration + } + } } - } fun fixNextReadyVariableForParameterTypeIfNeeded( c: Context, @@ -443,7 +455,7 @@ class PostponedArgumentInputTypesResolver( dependencyProvider: TypeVariableDependencyInformationProvider ): Boolean { val relatedVariables = type.getPureArgumentsForFunctionalTypeOrSubtype() - .map { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) }.flatten() + .flatMap { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) } val variableForFixation = variableFixationFinder.findFirstVariableForFixation( this, relatedVariables, postponedArguments, KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL, topLevelType ) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt index 256324ce33e..7a0619c027a 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeVariableMarker import org.jetbrains.kotlin.types.typeUtil.unCapture +import org.jetbrains.kotlin.utils.SmartList class MutableVariableWithConstraints private constructor( @@ -36,12 +37,15 @@ class MutableVariableWithConstraints private constructor( // see @OnlyInputTypes annotation val projectedInputCallTypes: Collection<UnwrappedType> get() = mutableConstraints - .filter { it.position.from is OnlyInputTypeConstraintPosition || it.inputTypePositionBeforeIncorporation != null } - .map { (it.type as KotlinType).unCapture().unwrap() } + .mapNotNullTo(SmartList()) { + if (it.position.from is OnlyInputTypeConstraintPosition || it.inputTypePositionBeforeIncorporation != null) + (it.type as KotlinType).unCapture().unwrap() + else null + } - private val mutableConstraints = if (constraints == null) ArrayList() else ArrayList(constraints) + private val mutableConstraints = if (constraints == null) SmartList() else SmartList(constraints) - private var simplifiedConstraints: ArrayList<Constraint>? = mutableConstraints + private var simplifiedConstraints: SmartList<Constraint>? = mutableConstraints // return new actual constraint, if this constraint is new fun addConstraint(constraint: Constraint): Constraint? { @@ -110,13 +114,13 @@ class MutableVariableWithConstraints private constructor( } } - private fun ArrayList<Constraint>.simplifyConstraints(): ArrayList<Constraint> { + private fun SmartList<Constraint>.simplifyConstraints(): SmartList<Constraint> { val equalityConstraints = filter { it.kind == ConstraintKind.EQUALITY } .groupBy { it.typeHashCode } return when { equalityConstraints.isEmpty() -> this - else -> filterTo(ArrayList()) { isUsefulConstraint(it, equalityConstraints) } + else -> filterTo(SmartList()) { isUsefulConstraint(it, equalityConstraints) } } } @@ -134,10 +138,10 @@ class MutableVariableWithConstraints private constructor( internal class MutableConstraintStorage : ConstraintStorage { override val allTypeVariables: MutableMap<TypeConstructorMarker, TypeVariableMarker> = LinkedHashMap() override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap() - override val initialConstraints: MutableList<InitialConstraint> = ArrayList() + override val initialConstraints: MutableList<InitialConstraint> = SmartList() override var maxTypeDepthFromInitialConstraints: Int = 1 - override val errors: MutableList<KotlinCallDiagnostic> = ArrayList() + override val errors: MutableList<KotlinCallDiagnostic> = SmartList() override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess } override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> = LinkedHashMap() - override val postponedTypeVariables: ArrayList<TypeVariableMarker> = ArrayList() + override val postponedTypeVariables: MutableList<TypeVariableMarker> = SmartList() } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index e222993d602..103a8b129b0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -389,10 +389,4 @@ class NewConstraintSystemImpl( val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() } } - - override fun hasEqualNothingConstraint(type: KotlinTypeMarker): Boolean { - checkState(State.BUILDING, State.COMPLETION, State.FREEZED) - val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false - return constraints.any { (it.kind == ConstraintKind.EQUALITY) && it.type.isNothing() } - } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt index e32895c0cb1..41b482853d4 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt @@ -228,6 +228,7 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) { CheckArgumentsInParenthesis, CheckExternalArgument, EagerResolveOfCallableReferences, + CompatibilityOfTypeVariableAsIntersectionTypePart, PostponedVariablesInitializerResolutionPart ), INVOKE(*FUNCTION.resolutionSequence.toTypedArray()), diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt index 0957bf240ca..40c735957bc 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt @@ -16,22 +16,22 @@ package org.jetbrains.kotlin.resolve.calls.model +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.renderer.DescriptorRenderer -import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver -import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks -import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl -import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper +import org.jetbrains.kotlin.resolve.calls.components.* import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage +import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.utils.SmartList abstract class ResolutionPart { @@ -250,3 +250,12 @@ class MutableResolvedCallAtom( override fun toString(): String = "$atom, candidate = $candidateDescriptor" } +fun KotlinResolutionCandidate.markCandidateForCompatibilityResolve() { + if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return + addDiagnostic(LowerPriorityToPreserveCompatibility) +} + +fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(diagnostics: SmartList<KotlinCallDiagnostic>) { + if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return + diagnostics.add(LowerPriorityToPreserveCompatibility) +} diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt index d126929d7b0..6f5be6281fa 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt @@ -139,7 +139,7 @@ private class QualifierScopeTowerProcessor<C : Candidate>( } private class NoExplicitReceiverScopeTowerProcessor<C : Candidate>( - val context: CandidateFactory<C>, + context: CandidateFactory<C>, val collectCandidates: CandidatesCollector ) : AbstractSimpleScopeTowerProcessor<C>(context) { override fun simpleProcess(data: TowerData): Collection<C> = when (data) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 88f23c7a361..8b2ae621ada 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -90,8 +90,14 @@ internal class MemberScopeTowerLevel( private fun collectMembers( getMembers: ResolutionScope.(KotlinType?) -> Collection<CallableDescriptor> ): Collection<CandidateWithBoundDispatchReceiver> { - val result = ArrayList<CandidateWithBoundDispatchReceiver>(0) val receiverValue = dispatchReceiver.receiverValue + + if (receiverValue.type is StubType) { + return arrayListOf() + } + + val result = ArrayList<CandidateWithBoundDispatchReceiver>(0) + receiverValue.type.memberScope.getMembers(receiverValue.type).mapTo(result) { createCandidateDescriptor(it, dispatchReceiver) } diff --git a/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.args b/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.args new file mode 100644 index 00000000000..8aa4650126f --- /dev/null +++ b/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/newInferenceImpliesProgressiveModeForNI.kt +-d +$TEMP_DIR$ +-XXLanguage\:+NewInference
\ No newline at end of file diff --git a/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.kt b/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.kt new file mode 100644 index 00000000000..50c59914756 --- /dev/null +++ b/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.kt @@ -0,0 +1,11 @@ +fun bar(): Int = 0 + +object Scope { + fun <T> foo(f: () -> T): T = f() + + fun bar(x: Int = 0): String = "" + + fun test() { + val r1 = foo(::bar) + } +}
\ No newline at end of file diff --git a/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.out b/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.out new file mode 100644 index 00000000000..d656becb3ae --- /dev/null +++ b/compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.out @@ -0,0 +1,16 @@ +warning: ATTENTION! +This build uses unsafe internal compiler arguments: + +-XXLanguage:+NewInference + +This mode is not recommended for production use, +as no stability/compatibility guarantees are given on +compiler or generated code. Use it at your own risk! + +compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.kt:6:13: warning: parameter 'x' is never used + fun bar(x: Int = 0): String = "" + ^ +compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.kt:9:13: warning: variable 'r1' is never used + val r1 = foo(::bar) + ^ +OK diff --git a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt new file mode 100644 index 00000000000..16f77837185 --- /dev/null +++ b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt @@ -0,0 +1,25 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// IGNORE_BACKEND: JVM_IR +// IGNORE_BACKEND: JS_IR +// KJS_WITH_FULL_RUNTIME +// WITH_RUNTIME +// WITH_COROUTINES + +import helpers.* +import kotlin.coroutines.* + +suspend fun foo() { + val x = sequence { + yield(1) + ::`yield` + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + builder { foo() } + return "OK" +} diff --git a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt new file mode 100644 index 00000000000..b4c5fea00ff --- /dev/null +++ b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt @@ -0,0 +1,24 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +class TypeDefinition<K : Any> { + fun parse(parser: (serializedValue: String) -> K?): Unit {} + fun serialize(parser: (value: K) -> Any?): Unit {} +} + +@OptIn(ExperimentalTypeInference::class) +fun <T : Any> defineType(@BuilderInference definition: TypeDefinition<T>.() -> Unit): Unit {} + +fun test() { + defineType { + parse { it as Int } + serialize { it.toString() } + } +} + +fun box(): String { + test() + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/defaultUpperBound.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/defaultUpperBound.kt index b9cd2f99b41..42a8b3ee6e8 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/defaultUpperBound.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/defaultUpperBound.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -16,7 +16,14 @@ fun <X> test() = typeOf<Container<X>>() fun box(): String { val type = test<Any>() val x = type.arguments.single().type!!.classifier as KTypeParameter - assertEquals("kotlin.Any?", x.upperBounds.joinToString()) + + val expected = className("kotlin", "Any?") + assertEquals(expected, x.upperBounds.joinToString()) return "OK" } + +fun className(qualifier: String, name: String): String { + val isJS = 1 as Any is Double + return if (isJS) name else "$qualifier.$name" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnClassParameters.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnClassParameters.kt index cdf9fa3f787..495b9a0989b 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnClassParameters.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnClassParameters.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -36,7 +36,12 @@ fun box(): String { assertEquals(c.x1, c.x2) assertEquals(c.x1.hashCode(), c.x2.hashCode()) - assertNotEquals(c.x1, c.xFun) + + if (!isJS) { + assertNotEquals(c.x1, c.xFun) + } assertNotEquals(c.x1, c.y) return "OK" } + +val isJS = 1 as Any is Double diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnFunctionParameters.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnFunctionParameters.kt index b3b656ace42..7f6651b432b 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnFunctionParameters.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/equalsOnFunctionParameters.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -22,6 +22,10 @@ fun box(): String { assertEquals(createX<Any>(), createX<Any>()) assertEquals(createX<Any>().hashCode(), createX<Any>().hashCode()) - assertNotEquals(createX<Any>(), createOtherX<Any>()) + if (!isJS) { + assertNotEquals(createX<Any>(), createOtherX<Any>()) + } return "OK" } + +val isJS = 1 as Any is Double diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt index 1a4e21e69a8..f1f51ee83d3 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt new file mode 100644 index 00000000000..05dc2a70845 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt @@ -0,0 +1,25 @@ +// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TODO: it should target all backends, but now it's possible to have only one .fial file per test file, +// so we can't define different messages for different test suites/runners. +// TARGET_BACKEND: JS +// KJS_WITH_FULL_RUNTIME + +import kotlin.reflect.typeOf + +fun <T : Comparable<T>> foo() { + bar<List<T>>() + baz<List<T>>() +} + +inline fun <reified T> bar() { + baz<T>() +} + +inline fun <reified T> baz() { + typeOf<Set<T>>() +} + +fun box(): String { + foo<Int>() + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail new file mode 100644 index 00000000000..9803cffba2d --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail @@ -0,0 +1 @@ +An operation is not implemented: Non-reified type parameters with recursive bounds are not supported yet
\ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt new file mode 100644 index 00000000000..ea49c1e1127 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt @@ -0,0 +1,16 @@ +// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TODO: it should target all backends, but now it's possible to have only one .fial file per test file, +// so we can't define different messages for different test suites/runners. +// TARGET_BACKEND: JS +// KJS_WITH_FULL_RUNTIME + +import kotlin.reflect.typeOf + +fun <T : Comparable<T>> foo() { + typeOf<List<T>>() +} + +fun box(): String { + foo<Int>() + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail new file mode 100644 index 00000000000..9803cffba2d --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail @@ -0,0 +1 @@ +An operation is not implemented: Non-reified type parameters with recursive bounds are not supported yet
\ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt index 39100cfae8b..d535a38f1db 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -16,7 +16,13 @@ class C<X> { } fun box(): String { - assertEquals("test.Container<X>", C<Any>().notNull().toString()) - assertEquals("test.Container<X?>", C<Any>().nullable().toString()) + val fqn = className("test", "Container") + assertEquals("$fqn<X>", C<Any>().notNull().toString()) + assertEquals("$fqn<X?>", C<Any>().nullable().toString()) return "OK" } + +fun className(qualifier: String, name: String): String { + val isJS = 1 as Any is Double + return if (isJS) name else "$qualifier.$name" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleFunctionParameter.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleFunctionParameter.kt index 4d6a2756288..b55d1dc1125 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleFunctionParameter.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleFunctionParameter.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -14,7 +14,13 @@ fun <X1> notNull() = typeOf<Container<X1>>() fun <X2> nullable() = typeOf<Container<X2?>>() fun box(): String { - assertEquals("test.Container<X1>", notNull<Any>().toString()) - assertEquals("test.Container<X2?>", nullable<Any>().toString()) + val fqn = className("test", "Container") + assertEquals("$fqn<X1>", notNull<Any>().toString()) + assertEquals("$fqn<X2?>", nullable<Any>().toString()) return "OK" } + +fun className(qualifier: String, name: String): String { + val isJS = 1 as Any is Double + return if (isJS) name else "$qualifier.$name" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simplePropertyParameter.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simplePropertyParameter.kt index 8dad8f5b0aa..453372356d1 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simplePropertyParameter.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simplePropertyParameter.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -14,7 +14,13 @@ val <X1> X1.notNull get() = typeOf<Container<X1>>() val <X2> X2.nullable get() = typeOf<Container<X2?>>() fun box(): String { - assertEquals("test.Container<X1>", "".notNull.toString()) - assertEquals("test.Container<X2?>", "".nullable.toString()) + val fqn = className("test", "Container") + assertEquals("$fqn<X1>", "".notNull.toString()) + assertEquals("$fqn<X2?>", "".nullable.toString()) return "OK" } + +fun className(qualifier: String, name: String): String { + val isJS = 1 as Any is Double + return if (isJS) name else "$qualifier.$name" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/typeParameterFlags.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/typeParameterFlags.kt index ccedd962668..64bc818c4ae 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/typeParameterFlags.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/typeParameterFlags.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -25,16 +25,22 @@ fun box(): String { assertEquals(KVariance.OUT, c.getOut().variance) assertEquals(false, c.getInv().isReified) - val y = getY<Any, Any>() - assertEquals(false, y.isReified) - val x = y.upperBounds.single().classifier as KTypeParameter - assertEquals(true, x.isReified) - assertEquals(KVariance.INVARIANT, x.variance) + if (!isJS) { + val y = getY<Any, Any>() + assertEquals(false, y.isReified) + val x = y.upperBounds.single().classifier as KTypeParameter + assertEquals(true, x.isReified) + assertEquals(KVariance.INVARIANT, x.variance) + assertEquals("X", x.toString()) + } assertEquals("INV", c.getInv().toString()) - assertEquals("in IN", c.getIn().toString()) - assertEquals("out OUT", c.getOut().toString()) - assertEquals("X", x.toString()) + if (!isJS) { + assertEquals("in IN", c.getIn().toString()) + assertEquals("out OUT", c.getOut().toString()) + } return "OK" } + +val isJS = 1 as Any is Double diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBoundUsesOuterClassParameter.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBoundUsesOuterClassParameter.kt index 38dc1f76ca5..5c9fe365191 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBoundUsesOuterClassParameter.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBoundUsesOuterClassParameter.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBounds.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBounds.kt index 46cef4c6aa7..d5e75a2e458 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBounds.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/upperBounds.kt @@ -1,7 +1,7 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// IGNORE_BACKEND: JS, JS_IR, NATIVE -// IGNORE_BACKEND: JS_IR_ES6 +// IGNORE_BACKEND: NATIVE // WITH_REFLECT +// KJS_WITH_FULL_RUNTIME package test @@ -16,16 +16,25 @@ fun <X, Y, Z> test() where X : Y?, Y : List<Z>, Z : Set<String> fun box(): String { val type = test<MutableList<Set<String>>?, MutableList<Set<String>>, Set<String>>() - assertEquals("test.Container<X>", type.toString()) + val containerNmae = className("test", "Container") + assertEquals("$containerNmae<X>", type.toString()) val x = type.arguments.single().type!!.classifier as KTypeParameter assertEquals("Y?", x.upperBounds.joinToString()) val y = x.upperBounds.single().classifier as KTypeParameter - assertEquals("kotlin.collections.List<Z>", y.upperBounds.joinToString()) + val listName = className("kotlin.collections", "List") + assertEquals("$listName<Z>", y.upperBounds.joinToString()) val z = y.upperBounds.single().arguments.single().type!!.classifier as KTypeParameter - assertEquals("kotlin.collections.Set<kotlin.String>", z.upperBounds.joinToString()) + val setName = className("kotlin.collections", "Set") + val stringName = className("kotlin", "String") + assertEquals("$setName<$stringName>", z.upperBounds.joinToString()) return "OK" } + +fun className(qualifier: String, name: String): String { + val isJS = 1 as Any is Double + return if (isJS) name else "$qualifier.$name" +} diff --git a/compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt b/compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt index 9e1c64a26fe..8dcff939afe 100644 --- a/compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt +++ b/compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt @@ -16,7 +16,7 @@ inline fun <reified T> T.causeBug() { T::class Array<T>(1) { x } - // Non-reified type parameters with recursive bounds are not yet supported + // Non-reified type parameters with recursive bounds are not yet supported, see Z from class Something // typeOf<T>() } diff --git a/compiler/testData/codegen/bytecodeText/constructors/inlinePrimaryDefaults.kt b/compiler/testData/codegen/bytecodeText/constructors/inlinePrimaryDefaults.kt index e77ffe8b07f..2f1b951dac6 100644 --- a/compiler/testData/codegen/bytecodeText/constructors/inlinePrimaryDefaults.kt +++ b/compiler/testData/codegen/bytecodeText/constructors/inlinePrimaryDefaults.kt @@ -1,13 +1,10 @@ +// !LANGUAGE: +InlineClasses +// This tests both KT-37013 and KT-37015. + inline class A(val x: Int = 0) // 0 <init>\(\)V // 1 private synthetic <init>\(I\)V // 1 public final static synthetic box-impl\(I\)LA; - -// JVM_TEMPLATES // 1 public static constructor-impl\(I\)I // 1 public static synthetic constructor-impl\$default\(IILkotlin/jvm/internal/DefaultConstructorMarker;\)I - -// JVM_IR_TEMPLATES -// 1 public final static constructor-impl\(I\)I -// 1 public static synthetic constructor-impl\$default\(IILjava/lang/Object;\)I diff --git a/compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.kt b/compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.kt new file mode 100644 index 00000000000..b0f5ea3befc --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.kt @@ -0,0 +1,19 @@ +// FIR_IDENTICAL +// !LANGUAGE: +DisableCompatibilityModeForNewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +fun bar(): Int = 0 + +object Scope { + fun <T> foo(f: () -> T): T = f() + + fun bar(x: Int = 0): String = "" + + fun test() { + val r1 = foo(::bar) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>r1<!> + + val r2 = foo(Scope::bar) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>r2<!> + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.txt b/compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.txt new file mode 100644 index 00000000000..cc3c2a58722 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.txt @@ -0,0 +1,13 @@ +package + +public fun bar(): kotlin.Int + +public object Scope { + private constructor Scope() + public final fun bar(/*0*/ x: kotlin.Int = ...): kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ T> foo(/*0*/ f: () -> T): T + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.fir.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.fir.kt new file mode 100644 index 00000000000..9ec54a74492 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.fir.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER +// WITH_RUNTIME + + +fun <T> List<Option<T>>.flatten(): List<T> = <!AMBIGUITY!>flatMap<!> { <!UNRESOLVED_REFERENCE!>it<!>.<!INAPPLICABLE_CANDIDATE!>fold<!>(::emptyList, <!UNRESOLVED_REFERENCE!>::listOf<!>) } + +class Option<out T> { + fun <R> fold(ifEmpty: () -> R, ifSome: (T) -> R): R = TODO() +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.kt new file mode 100644 index 00000000000..3dcd7353331 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER +// WITH_RUNTIME + + +fun <T> List<Option<T>>.flatten(): List<T> = flatMap { it.fold(::emptyList, ::listOf) } + +class Option<out T> { + fun <R> fold(ifEmpty: () -> R, ifSome: (T) -> R): R = TODO() +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.txt b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.txt new file mode 100644 index 00000000000..c7a22a24bdb --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.txt @@ -0,0 +1,11 @@ +package + +public fun </*0*/ T> kotlin.collections.List<Option<T>>.flatten(): kotlin.collections.List<T> + +public final class Option</*0*/ out T> { + public constructor Option</*0*/ out T>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ R> fold(/*0*/ ifEmpty: () -> R, /*1*/ ifSome: (T) -> R): R + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.fir.kt b/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.fir.kt new file mode 100644 index 00000000000..e4a34b1f051 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.fir.kt @@ -0,0 +1,23 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +object Scope { + fun foo(): Int = 0 + + object Nested { + @Deprecated("err", level = DeprecationLevel.HIDDEN) + fun foo(): String = "" + + fun <T> take(f: () -> T): T = f() + + fun test() { + val r1 = take(::foo) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>r1<!> + + val r2 = ::foo + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.String>")!>r2<!> + + val r3 = foo() + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>r3<!> + } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.kt b/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.kt new file mode 100644 index 00000000000..728e6ea3330 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.kt @@ -0,0 +1,23 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +object Scope { + fun foo(): Int = 0 + + object Nested { + @Deprecated("err", level = DeprecationLevel.HIDDEN) + fun foo(): String = "" + + fun <T> take(f: () -> T): T = f() + + fun test() { + val r1 = take(::foo) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>r1<!> + + val r2 = ::foo + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.Int>")!>r2<!> + + val r3 = foo() + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>r3<!> + } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.txt b/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.txt new file mode 100644 index 00000000000..55568cb0c81 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.txt @@ -0,0 +1,19 @@ +package + +public object Scope { + private constructor Scope() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object Nested { + private constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "err") public final fun foo(): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun </*0*/ T> take(/*0*/ f: () -> T): T + public final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.fir.kt b/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.fir.kt new file mode 100644 index 00000000000..ddadd6b1256 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.fir.kt @@ -0,0 +1,26 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +package kotlin + +object Scope { + fun foo(): Int = 0 + + object Nested { + @Deprecated("err") + @DeprecatedSinceKotlin(hiddenSince = "1.0") + fun foo(): String = "" + + fun <T> take(f: () -> T): T = f() + + fun test() { + val r1 = take(::foo) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>r1<!> + + val r2 = ::foo + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.String>")!>r2<!> + + val r3 = foo() + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>r3<!> + } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.kt b/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.kt new file mode 100644 index 00000000000..4dd1e3f80fb --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.kt @@ -0,0 +1,26 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +package kotlin + +object Scope { + fun foo(): Int = 0 + + object Nested { + @Deprecated("err") + @DeprecatedSinceKotlin(hiddenSince = "1.0") + fun foo(): String = "" + + fun <T> take(f: () -> T): T = f() + + fun test() { + val r1 = take(::foo) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>r1<!> + + val r2 = ::foo + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.Int>")!>r2<!> + + val r3 = foo() + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>r3<!> + } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.txt b/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.txt new file mode 100644 index 00000000000..4c8b25d0219 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.txt @@ -0,0 +1,22 @@ +package + +package kotlin { + + public object Scope { + private constructor Scope() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object Nested { + private constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + @kotlin.Deprecated(message = "err") @kotlin.DeprecatedSinceKotlin(hiddenSince = "1.0") public final fun foo(): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun </*0*/ T> take(/*0*/ f: () -> T): T + public final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt index c86551c0788..313b0300703 100644 --- a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt @@ -3,11 +3,11 @@ fun <T : Number> materializeNumber(): T = TODO() fun a(): Unit = run { - <!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>() + <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>() } fun b(): Unit = run { run { - <!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>() + <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>() } }
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt new file mode 100644 index 00000000000..1d5333bbba1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt @@ -0,0 +1,15 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Base +class Foo : Base + +fun <T : Base> myRun(action: () -> T): T = action() + +fun foo(f: (Foo) -> Unit) {} + +fun main() { + foo { f: Foo -> + myRun { f } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.txt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.txt new file mode 100644 index 00000000000..3b39cfa6822 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.txt @@ -0,0 +1,18 @@ +package + +public fun foo(/*0*/ f: (Foo) -> kotlin.Unit): kotlin.Unit +public fun main(): kotlin.Unit +public fun </*0*/ T : Base> myRun(/*0*/ action: () -> T): T + +public interface Base { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Foo : Base { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.fir.kt b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.fir.kt new file mode 100644 index 00000000000..460d6e39714 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.fir.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo<T> + +abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>> + +object Scope { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {} + + object Nested { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {} + + fun test(b: Bar<Long>) { + <!DEBUG_INFO_CALL("fqName: Scope.Nested.greater; typeCall: function")!>greater(b, b)<!> + } + } +} + +object OnlyOne { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {} + + fun test(b: Bar<Long>) { + <!DEBUG_INFO_CALL("fqName: OnlyOne.greater; typeCall: function")!>greater(b, b)<!> + } +} + +object GoodOldCandidate { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {} + + object Nested { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {} + + fun test(b: Bar<Long>) { + <!DEBUG_INFO_CALL("fqName: GoodOldCandidate.Nested.greater; typeCall: function")!>greater(b, b)<!> + } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt new file mode 100644 index 00000000000..2e5b6620375 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo<T> + +abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>> + +object Scope { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {} + + object Nested { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {} + + fun test(b: Bar<Long>) { + <!DEBUG_INFO_CALL("fqName: Scope.greater; typeCall: function")!><!COMPATIBILITY_WARNING!>greater<!>(b, b)<!> + } + } +} + +object OnlyOne { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {} + + fun test(b: Bar<Long>) { + <!DEBUG_INFO_CALL("fqName: OnlyOne.greater; typeCall: function")!>greater(b, b)<!> + } +} + +object GoodOldCandidate { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {} + + object Nested { + fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {} + + fun test(b: Bar<Long>) { + <!DEBUG_INFO_CALL("fqName: GoodOldCandidate.Nested.greater; typeCall: function")!>greater(b, b)<!> + } + } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.txt b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.txt new file mode 100644 index 00000000000..61d17839187 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.txt @@ -0,0 +1,59 @@ +package + +public abstract class Bar</*0*/ T> : Foo<T>, kotlin.Comparable<Bar<T>> { + public constructor Bar</*0*/ T>() + public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Bar<T>): kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class Foo</*0*/ T> { + public constructor Foo</*0*/ T>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object GoodOldCandidate { + private constructor GoodOldCandidate() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object Nested { + private constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ other: Foo<T>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(/*0*/ b: Bar<kotlin.Long>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public object OnlyOne { + private constructor OnlyOne() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(/*0*/ b: Bar<kotlin.Long>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object Scope { + private constructor Scope() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ other: Foo<T>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object Nested { + private constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(/*0*/ b: Bar<kotlin.Long>): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.fir.kt new file mode 100644 index 00000000000..79cf65fbf00 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.fir.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo<T> + +abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>> + +fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T): Int = 0 +fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>): String = "" + +fun test(b: Bar<Long>) { + val result = <!AMBIGUITY!>greater<!>(b, b) + <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Ambiguity: greater, [/greater, /greater]")!>result<!> +} diff --git a/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt new file mode 100644 index 00000000000..30f4a95028c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo<T> + +abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>> + +fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T): Int = 0 +fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>): String = "" + +fun test(b: Bar<Long>) { + val result = greater(b, b) + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!> +} diff --git a/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.txt b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.txt new file mode 100644 index 00000000000..9d4cf487cfb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.txt @@ -0,0 +1,20 @@ +package + +public fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ other: Foo<T>): kotlin.String +public fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Int +public fun test(/*0*/ b: Bar<kotlin.Long>): kotlin.Unit + +public abstract class Bar</*0*/ T> : Foo<T>, kotlin.Comparable<Bar<T>> { + public constructor Bar</*0*/ T>() + public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Bar<T>): kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class Foo</*0*/ T> { + public constructor Foo</*0*/ T>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.fir.kt b/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.fir.kt new file mode 100644 index 00000000000..aa94bcbed9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.fir.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -EXPERIMENTAL_IS_NOT_ENABLED +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +@OptIn(ExperimentalTypeInference::class) +fun <T> foo(x: T, @BuilderInference builder: T.() -> Unit): Unit = TODO() + +class Bar<T> + +fun test() { + foo(1) { + <!UNRESOLVED_REFERENCE!>dsgfsdg<!> + } +} diff --git a/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt b/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt new file mode 100644 index 00000000000..2e82448e11f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -EXPERIMENTAL_IS_NOT_ENABLED +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +@OptIn(ExperimentalTypeInference::class) +fun <T> foo(x: T, @BuilderInference builder: T.() -> Unit): Unit = TODO() + +class Bar<T> + +fun test() { + foo(1) { + <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_UNRESOLVED_WITH_TARGET, UNRESOLVED_REFERENCE!>dsgfsdg<!> + } +} diff --git a/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.txt b/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.txt new file mode 100644 index 00000000000..b0b700c7316 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.txt @@ -0,0 +1,11 @@ +package + +@kotlin.OptIn(markerClass = {kotlin.experimental.ExperimentalTypeInference::class}) public fun </*0*/ T> foo(/*0*/ x: T, /*1*/ @kotlin.BuilderInference builder: T.() -> kotlin.Unit): kotlin.Unit +public fun test(): kotlin.Unit + +public final class Bar</*0*/ T> { + public constructor Bar</*0*/ T>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.kt b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.kt new file mode 100644 index 00000000000..0f5c72758cb --- /dev/null +++ b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.kt @@ -0,0 +1,12 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Either + +infix fun <A, B, C> ((A) -> B).andThen(g: (B) -> C): (A) -> C = TODO() + +fun unsafeRunAsync(cb: (Either) -> Unit) {} + +fun runAsync(cb: (Either) -> Unit) { + unsafeRunAsync(cb.andThen { }) +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.txt b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.txt new file mode 100644 index 00000000000..80543186aac --- /dev/null +++ b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.txt @@ -0,0 +1,12 @@ +package + +public fun runAsync(/*0*/ cb: (Either) -> kotlin.Unit): kotlin.Unit +public fun unsafeRunAsync(/*0*/ cb: (Either) -> kotlin.Unit): kotlin.Unit +public infix fun </*0*/ A, /*1*/ B, /*2*/ C> ((A) -> B).andThen(/*0*/ g: (B) -> C): (A) -> C + +public final class Either { + public constructor Either() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.kt b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.kt new file mode 100644 index 00000000000..7be24ab4c6b --- /dev/null +++ b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.kt @@ -0,0 +1,10 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun <T> foo(f: () -> T) {} +fun bar(g: () -> Unit) {} +fun <K> baz(): () -> K = TODO() + +fun test() { + foo { bar(baz()) } +}
\ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.txt b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.txt new file mode 100644 index 00000000000..bed9c2f5107 --- /dev/null +++ b/compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.txt @@ -0,0 +1,6 @@ +package + +public fun bar(/*0*/ g: () -> kotlin.Unit): kotlin.Unit +public fun </*0*/ K> baz(): () -> K +public fun </*0*/ T> foo(/*0*/ f: () -> T): kotlin.Unit +public fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.kt b/compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.kt deleted file mode 100644 index 2bd33843377..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.kt +++ /dev/null @@ -1,35 +0,0 @@ -// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi -// !LANGUAGE: +ProhibitNonReifiedArraysAsReifiedTypeArguments - -import kotlin.reflect.typeOf - -inline fun <X, reified Y, Z : Y> test1() { - <!UNSUPPORTED!>typeOf<!><<!TYPE_PARAMETER_AS_REIFIED!>X<!>>() - <!UNSUPPORTED!>typeOf<!><List<X>>() - <!UNSUPPORTED!>typeOf<!><<!TYPE_PARAMETER_AS_REIFIED_ARRAY!>Array<X?><!>>() - - typeOf<Y>() - - <!UNSUPPORTED!>typeOf<!><<!TYPE_PARAMETER_AS_REIFIED!>Z<!>>() - <!UNSUPPORTED!>typeOf<!><List<Z>?>() - <!UNSUPPORTED!>typeOf<!><<!TYPE_PARAMETER_AS_REIFIED_ARRAY!>Array<Z><!>>() -} - - -class Test2<W> { - fun test2() { - <!UNSUPPORTED!>typeOf<!><<!TYPE_PARAMETER_AS_REIFIED!>W<!>>() - <!UNSUPPORTED!>typeOf<!><List<W?>>() - <!UNSUPPORTED!>typeOf<!><<!TYPE_PARAMETER_AS_REIFIED_ARRAY!>Array<W><!>>() - } -} - - -inline fun <reified U> f() { - typeOf<U>() -} - -fun <T> test3() { - // We don't report anything here because we can't know in frontend how the corresponding type parameter is used in f - f<List<T>>() -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.txt b/compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.txt deleted file mode 100644 index 1fd20e67728..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.txt +++ /dev/null @@ -1,13 +0,0 @@ -package - -public inline fun </*0*/ reified U> f(): kotlin.Unit -public inline fun </*0*/ X, /*1*/ reified Y, /*2*/ Z : Y> test1(): kotlin.Unit -public fun </*0*/ T> test3(): kotlin.Unit - -public final class Test2</*0*/ W> { - public constructor Test2</*0*/ W>() - public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - public final fun test2(): kotlin.Unit - public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.kt index 17490c59289..c8ed5d607a5 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.kt @@ -15,6 +15,6 @@ fun <KotlinType : Any> defineType(@BuilderInference definition: TypeDefinition<K fun main() { <!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>defineType<!> { parse { it.toInt() } - serialize { <!OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>toString<!>() } + serialize { <!OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!>.<!OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>toString<!>() } } }
\ No newline at end of file diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/InTextDirectivesUtils.java b/compiler/tests-common/tests/org/jetbrains/kotlin/test/InTextDirectivesUtils.java index 32e266d1b02..e54bc1a80fa 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/InTextDirectivesUtils.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/InTextDirectivesUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -231,7 +231,12 @@ public final class InTextDirectivesUtils { return false; List<String> backends = findLinesWithPrefixesRemoved(textWithDirectives(file), "// TARGET_BACKEND: "); - return backends.isEmpty() || backends.contains(targetBackend.name()) || backends.contains(targetBackend.getCompatibleWith().name()); + return isCompatibleTargetExceptAny(targetBackend, backends); + } + + private static boolean isCompatibleTargetExceptAny(TargetBackend targetBackend, List<String> backends) { + if (targetBackend == TargetBackend.ANY) return false; + return backends.isEmpty() || backends.contains(targetBackend.name()) || isCompatibleTargetExceptAny(targetBackend.getCompatibleWith(), backends); } public static boolean isIgnoredTarget(TargetBackend targetBackend, File file, String ignoreBackendDirectivePrefix) { diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 883762945a5..abef5325a89 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1931,6 +1931,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/callableReference/noAmbiguityWhenAllReferencesAreInapplicable.kt"); } + @TestMetadata("noCompatibilityResolveWithProressiveModeForNI.kt") + public void testNoCompatibilityResolveWithProressiveModeForNI() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.kt"); + } + @TestMetadata("noExceptionOnRedCodeWithArrayLikeCall.kt") public void testNoExceptionOnRedCodeWithArrayLikeCall() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/noExceptionOnRedCodeWithArrayLikeCall.kt"); @@ -2805,6 +2810,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveReferenceAgainstKFunctionAndKPrpoerty.kt"); } + @TestMetadata("resolveTwoReferencesAgainstGenerics.kt") + public void testResolveTwoReferencesAgainstGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.kt"); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt"); @@ -6532,6 +6542,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedHidden.kt"); } + @TestMetadata("deprecatedHiddenOnCallableReferenceArgument.kt") + public void testDeprecatedHiddenOnCallableReferenceArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.kt"); + } + @TestMetadata("deprecatedInheritance.kt") public void testDeprecatedInheritance() throws Exception { runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedInheritance.kt"); @@ -6674,6 +6689,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinDeclaration.kt"); } + @TestMetadata("deprecatedSinceKotlinHiddenOnReferenceArgument.kt") + public void testDeprecatedSinceKotlinHiddenOnReferenceArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.kt"); + } + @TestMetadata("deprecatedSinceKotlinOutsideKotlinPackage.kt") public void testDeprecatedSinceKotlinOutsideKotlinPackage() throws Exception { runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinOutsideKotlinPackage.kt"); @@ -10056,6 +10076,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/commonSuperTypeOfErrorTypes.kt"); } + @TestMetadata("compatibilityResolveWhenVariableHasComplexIntersectionType.kt") + public void testCompatibilityResolveWhenVariableHasComplexIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt"); + } + @TestMetadata("completeInferenceIfManyFailed.kt") public void testCompleteInferenceIfManyFailed() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt"); @@ -10206,6 +10231,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/intersectionTypeMultipleBoundsAsReceiver.kt"); } + @TestMetadata("intersectionTypesWithContravariantTypes.kt") + public void testIntersectionTypesWithContravariantTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt"); + } + @TestMetadata("intersectionWithEnum.kt") public void testIntersectionWithEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/intersectionWithEnum.kt"); @@ -10396,6 +10426,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt"); } + @TestMetadata("skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt") + public void testSkipedUnresolvedInBuilderInferenceWithStubReceiverType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt"); + } + @TestMetadata("starApproximation.kt") public void testStarApproximation() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/starApproximation.kt"); @@ -10651,6 +10686,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coerctionToUnitForATypeWithUpperBound.kt") + public void testCoerctionToUnitForATypeWithUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt"); + } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); @@ -24691,6 +24731,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/unitConversion/chainedUnitSuspendConversion.kt"); } + @TestMetadata("noUnitConversionForGenericTypeFromArrow.kt") + public void testNoUnitConversionForGenericTypeFromArrow() throws Exception { + runTest("compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.kt"); + } + + @TestMetadata("noUnitConversionOnReturningGenericFunctionalType.kt") + public void testNoUnitConversionOnReturningGenericFunctionalType() throws Exception { + runTest("compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.kt"); + } + @TestMetadata("unitConversionCompatibility.kt") public void testUnitConversionCompatibility() throws Exception { runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index ffae5cf73d2..a9836316b29 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -1122,10 +1122,5 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes public void testReflectionApi() throws Exception { runTest("compiler/testData/diagnostics/testsWithJsStdLib/reflection/reflectionApi.kt"); } - - @TestMetadata("typeOfWithNonReifiedParameter.kt") - public void testTypeOfWithNonReifiedParameter() throws Exception { - runTest("compiler/testData/diagnostics/testsWithJsStdLib/reflection/typeOfWithNonReifiedParameter.kt"); - } } } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index c4545b45a17..7a69bc88a5b 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -1926,6 +1926,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/callableReference/noAmbiguityWhenAllReferencesAreInapplicable.kt"); } + @TestMetadata("noCompatibilityResolveWithProressiveModeForNI.kt") + public void testNoCompatibilityResolveWithProressiveModeForNI() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/noCompatibilityResolveWithProressiveModeForNI.kt"); + } + @TestMetadata("noExceptionOnRedCodeWithArrayLikeCall.kt") public void testNoExceptionOnRedCodeWithArrayLikeCall() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/noExceptionOnRedCodeWithArrayLikeCall.kt"); @@ -2800,6 +2805,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveReferenceAgainstKFunctionAndKPrpoerty.kt"); } + @TestMetadata("resolveTwoReferencesAgainstGenerics.kt") + public void testResolveTwoReferencesAgainstGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveTwoReferencesAgainstGenerics.kt"); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt"); @@ -6527,6 +6537,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedHidden.kt"); } + @TestMetadata("deprecatedHiddenOnCallableReferenceArgument.kt") + public void testDeprecatedHiddenOnCallableReferenceArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedHiddenOnCallableReferenceArgument.kt"); + } + @TestMetadata("deprecatedInheritance.kt") public void testDeprecatedInheritance() throws Exception { runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedInheritance.kt"); @@ -6669,6 +6684,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinDeclaration.kt"); } + @TestMetadata("deprecatedSinceKotlinHiddenOnReferenceArgument.kt") + public void testDeprecatedSinceKotlinHiddenOnReferenceArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinHiddenOnReferenceArgument.kt"); + } + @TestMetadata("deprecatedSinceKotlinOutsideKotlinPackage.kt") public void testDeprecatedSinceKotlinOutsideKotlinPackage() throws Exception { runTest("compiler/testData/diagnostics/tests/deprecated/deprecatedSinceKotlin/deprecatedSinceKotlinOutsideKotlinPackage.kt"); @@ -10051,6 +10071,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/commonSuperTypeOfErrorTypes.kt"); } + @TestMetadata("compatibilityResolveWhenVariableHasComplexIntersectionType.kt") + public void testCompatibilityResolveWhenVariableHasComplexIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt"); + } + @TestMetadata("completeInferenceIfManyFailed.kt") public void testCompleteInferenceIfManyFailed() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt"); @@ -10201,6 +10226,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/intersectionTypeMultipleBoundsAsReceiver.kt"); } + @TestMetadata("intersectionTypesWithContravariantTypes.kt") + public void testIntersectionTypesWithContravariantTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt"); + } + @TestMetadata("intersectionWithEnum.kt") public void testIntersectionWithEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/intersectionWithEnum.kt"); @@ -10391,6 +10421,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt"); } + @TestMetadata("skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt") + public void testSkipedUnresolvedInBuilderInferenceWithStubReceiverType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/skipedUnresolvedInBuilderInferenceWithStubReceiverType.kt"); + } + @TestMetadata("starApproximation.kt") public void testStarApproximation() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/starApproximation.kt"); @@ -10646,6 +10681,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coerctionToUnitForATypeWithUpperBound.kt") + public void testCoerctionToUnitForATypeWithUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt"); + } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); @@ -24611,6 +24651,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/unitConversion/chainedUnitSuspendConversion.kt"); } + @TestMetadata("noUnitConversionForGenericTypeFromArrow.kt") + public void testNoUnitConversionForGenericTypeFromArrow() throws Exception { + runTest("compiler/testData/diagnostics/tests/unitConversion/noUnitConversionForGenericTypeFromArrow.kt"); + } + + @TestMetadata("noUnitConversionOnReturningGenericFunctionalType.kt") + public void testNoUnitConversionOnReturningGenericFunctionalType() throws Exception { + runTest("compiler/testData/diagnostics/tests/unitConversion/noUnitConversionOnReturningGenericFunctionalType.kt"); + } + @TestMetadata("unitConversionCompatibility.kt") public void testUnitConversionCompatibility() throws Exception { runTest("compiler/testData/diagnostics/tests/unitConversion/unitConversionCompatibility.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index 40cf8ebb0bf..91679f77bf9 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -540,6 +540,11 @@ public class CliTestGenerated extends AbstractCliTest { runTest("compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.args"); } + @TestMetadata("newInferenceImpliesProgressiveModeForNI.args") + public void testNewInferenceImpliesProgressiveModeForNI() throws Exception { + runTest("compiler/testData/cli/jvm/newInferenceImpliesProgressiveModeForNI.args"); + } + @TestMetadata("newInferenceImpliesSamConversions.args") public void testNewInferenceImpliesSamConversions() throws Exception { runTest("compiler/testData/cli/jvm/newInferenceImpliesSamConversions.args"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 93b5c3a0a56..7ca941d651e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -1727,6 +1727,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 6fc1f78b0eb..4005ab27c69 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -1727,6 +1727,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 6fce14f44d5..27262ed50c8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -1707,6 +1707,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 84763cf7832..4f2a80e946e 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -132,6 +132,7 @@ enum class LanguageFeature( ProhibitVarargAsArrayAfterSamArgument(KOTLIN_1_5, kind = BUG_FIX), CorrectSourceMappingSyntax(KOTLIN_1_5, kind = UNSTABLE_FEATURE), ProperArrayConventionSetterWithDefaultCalls(KOTLIN_1_5, kind = OTHER), + DisableCompatibilityModeForNewInference(KOTLIN_1_5, defaultState = LanguageFeature.State.DISABLED), // Temporarily disabled, see KT-27084/KT-22379 SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX), diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/VariableDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/VariableDescriptorImpl.java index fcb022f7c1c..7db3c6fc9f9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/VariableDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/VariableDescriptorImpl.java @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.types.KotlinType; +import org.jetbrains.kotlin.types.StubType; import java.util.Collection; import java.util.Collections; @@ -49,7 +50,7 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorNonRoo } public void setOutType(KotlinType outType) { - assert this.outType == null; + assert this.outType == null || this.outType instanceof StubType; this.outType = outType; } diff --git a/gradle.properties b/gradle.properties index a110920adca..7807117f33b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,3 +22,7 @@ bootstrap.kotlin.default.version=1.4.0-rc-87 #kotlin.build.postprocessing=false #kotlin.build.java9=false #kotlin.build.useBootstrapStdlib=true + +# Don't add the Kotlin standard library dependencies by default +# TODO: add this flag in a granular way to the modules that don't need stdlib? +kotlin.stdlib.default.dependency=false
\ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt index 45b081285e7..b64adce93f7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.idea.configuration.getBuildSystemType import org.jetbrains.kotlin.idea.core.isInTestSourceContentKotlinAware import org.jetbrains.kotlin.idea.framework.effectiveKind import org.jetbrains.kotlin.idea.framework.platform +import org.jetbrains.kotlin.idea.klib.AbstractKlibLibraryInfo import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.findAnalyzerServices import org.jetbrains.kotlin.idea.project.getStableName @@ -47,6 +48,7 @@ import org.jetbrains.kotlin.idea.project.isHMPPEnabled import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected import org.jetbrains.kotlin.idea.util.rootManager +import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider import org.jetbrains.kotlin.platform.TargetPlatform @@ -152,22 +154,25 @@ private fun ideaModelDependencies( } true } - return result.filterNot { it is LibraryInfo && !platform.canDependOn(it.platform, module.isHMPPEnabled) } + return result.filterNot { it is LibraryInfo && !platform.canDependOn(it, module.isHMPPEnabled) } } -private fun TargetPlatform.canDependOn(other: TargetPlatform, isHmppEnabled: Boolean): Boolean { +private fun TargetPlatform.canDependOn(other: IdeaModuleInfo, isHmppEnabled: Boolean): Boolean { if (isHmppEnabled) { - val platformsWhichAreNotContainedInOther = this.componentPlatforms - other.componentPlatforms + // HACK: allow depending on stdlib even if platforms do not match + if (isNative() && other is AbstractKlibLibraryInfo && other.libraryRoot.endsWith(KONAN_STDLIB_NAME)) return true + + val platformsWhichAreNotContainedInOther = this.componentPlatforms - other.platform.componentPlatforms if (platformsWhichAreNotContainedInOther.isEmpty()) return true // unspecifiedNativePlatform is effectively a wildcard for NativePlatform return platformsWhichAreNotContainedInOther.all { it is NativePlatform } && - NativePlatforms.unspecifiedNativePlatform.componentPlatforms.single() in other.componentPlatforms + NativePlatforms.unspecifiedNativePlatform.componentPlatforms.single() in other.platform.componentPlatforms } else { - return this.isJvm() && other.isJvm() || - this.isJs() && other.isJs() || - this.isNative() && other.isNative() || - this.isCommon() && other.isCommon() + return this.isJvm() && other.platform.isJvm() || + this.isJs() && other.platform.isJs() || + this.isNative() && other.platform.isNative() || + this.isCommon() && other.platform.isCommon() } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index ca7638622be..03e28a64d73 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.project +import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.psi.util.CachedValue @@ -12,6 +13,7 @@ import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.SLRUCache +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.cfg.ControlFlowInformationProvider import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.context.SimpleGlobalContext @@ -25,6 +27,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.util.analyzeControlFlow import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListenerCompat import org.jetbrains.kotlin.idea.caches.trackers.inBlockModificationCount +import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.* @@ -151,6 +154,22 @@ class ResolveElementCache( assert(bodyResolveMode == BodyResolveMode.FULL) } + // KT-38687: There are lots of editor specific items like inlays, line markers, injected items etc + // those require analysis: it is called with BodyResolveMode.PARTIAL or BodyResolveMode.PARTIAL_WITH_CFA almost simultaneously. + // In the same time Kotlin Annotator (e.g. KotlinPsiChecker) requires BodyResolveMode.FULL analysis. + // + // While results of FULL could be reused by any of PARTIAL or PARTIAL_WITH_CFA analysis, + // neither result of PARTIAL nor result of PARTIAL_WITH_CFA analyses could be reused by FULL analysis. + // + // Force perform FULL analysis to avoid redundant analysis for the current selected files. + if (bodyResolveMode != BodyResolveMode.FULL && bodyResolveMode != BodyResolveMode.PARTIAL_FOR_COMPLETION && (!isUnitTestMode() || forceFullAnalysisModeInTests)) { + val virtualFile = resolveElement.containingFile.virtualFile + // applicable for real (physical) files only + if (virtualFile != null && FileEditorManager.getInstance(resolveElement.project).selectedFiles.any { it == virtualFile }) { + return getElementsAdditionalResolve(resolveElement, contextElements, BodyResolveMode.FULL) + } + } + // check if full additional resolve already performed and is up-to-date val fullResolveMap = fullResolveCache.value val cachedFullResolve = fullResolveMap[resolveElement] @@ -793,5 +812,10 @@ class ResolveElementCache( override fun getTopDownAnalysisMode() = topDownAnalysisMode } + + companion object { + @set:TestOnly + var forceFullAnalysisModeInTests: Boolean = false + } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/CompletionFUSCollector.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/CompletionFUSCollector.kt index 23ae4c9ee7d..92b120a3b51 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/CompletionFUSCollector.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/CompletionFUSCollector.kt @@ -66,8 +66,7 @@ object CompletionFUSCollector { data[CompletionEventAttribute] = NotChosen } - // sending the data was turned of for 1.3.71+ as we sent enough in 1.3.70 - // KotlinFUSLogger.log(FUSEventGroups.Editor, EventName, data) + KotlinFUSLogger.log(FUSEventGroups.Editor, EventName, data) } } diff --git a/idea/idea-gradle/res/messages/KotlinIdeaGradleBundle.properties b/idea/idea-gradle/res/messages/KotlinIdeaGradleBundle.properties index d5725b6c359..08bfd414a74 100644 --- a/idea/idea-gradle/res/messages/KotlinIdeaGradleBundle.properties +++ b/idea/idea-gradle/res/messages/KotlinIdeaGradleBundle.properties @@ -1,40 +1,56 @@ -notification.oldGradle.firstLoad=Code insight is disabled to avoid Gradle build configuration -notification.oldGradle.firstLoad.info=<div width=400>\ - <p>The Gradle configuration phase is required to be run to get the Script Configuration \ - It is disabled by default since it can be expensive for large Gradle projects.</p>\ - <br/>\ - <p>Click "Load Configuration" to evaluate Gradle build scripts.</p>\ +gradle.script.configurations.importing.feature=Load Gradle Kotlin DSL script configurations during Gradle project import +notification.gradle.legacy.firstLoad=Code insight is disabled to avoid the Gradle build configuration. +notification.gradle.legacy.firstLoad.info=<div width=400><p>The Gradle configuration phase needs to be run to get the Script Configuration. \ +Loading the script configuration is disabled by default, since it can be resource-intensive for large Gradle projects.</p>\ +<p>Click "Load Configuration" to evaluate the Gradle Kotlin DSL script.</p>\ +<p>Alternatively, to automatically load the configuration when the script first opens \ +and reload it each time build script configuration blocks are changed, you can enable "auto-reload" for all scripts. \ +This option is not recommended for large Gradle projects with long configuration times.</p>\ +</div> +notification.gradle.legacy.outsideProject=Code insight unavailable (related Gradle project not linked). +notification.gradle.legacy.outsideProject.addToStandaloneHelp=<div width=400>\ + <p>The Gradle project that evaluates this script needs to be imported to have it analyzed by the IDE. \ + Try re-importing the linked Gradle project or link a new Gradle project that evaluates this script.</p>\ + <p>Alternatively, you can add it to standalone scripts, and its configuration will be loaded automatically.</p>\ + <p><b>NOTE:</b> Each standalone script requires a separate Gradle configuration phase to be executed on update. \ + This can be resource intensive for large Gradle projects.</p>\ + </div> +notification.gradle.legacy.standalone.info=<div width=400>\ + <p>The Gradle project that evaluates this script isn't imported in IDE. \ <br/>\ - <p>Alternatively, you can "Enable auto-reload" for all files to automatically load \ - configuration on the first opening and reload it on each change of build script configuration blocks. \ - This option is not recommended for a big Gradle project with a long configuration time.</p>\ + <p><b>NOTE:</b> Each standalone script requires a separate Gradle configuration phase to be executed on update. \ + This can be resource intensive for large Gradle projects.</p>\ </div> -gradle.script.configurations.importing.feature=Load gradle kotlin scripts configuration from project importing -notification.outsideAnything.text=Code insight unavailable (related Gradle project not linked) +notification.outsideAnything.text=Code insight unavailable (related Gradle project not linked). notification.outsideAnything.linkAction=Link Gradle project -notification.wasNotImportedAfterCreation.text=Code insight unavailable (Gradle project not imported) +notification.wasNotImportedAfterCreation.193.text=Code insight unavailable (Gradle project not imported). +notification.wasNotImportedAfterCreation.text=Code insight unavailable (Script Configurations not loaded). +notification.wasNotImportedAfterCreation.help=<div width=400>\ + <p>The Gradle Kotlin DSL script configurations are missing. \ + Import the external Gradle project or load the configurations \ + to get script code insight.</p>\ + </div> action.label.import.project=Import Project action.text.load.script.configurations=Load Script Configurations -action.description.load.script.configurations=Gradle Kotlin DSL script configuration has been changed. Load changes to get script code insight without loading the external Gradle project. +action.description.load.script.configurations=The Gradle Kotlin DSL script configuration has been changed. Load the changes to get code insight without importing the external Gradle project. action.label.enable.auto.import=Enable Auto-Import -notification.notEvaluatedInLastImport.text=Code insight unavailable (configuration for this script wasn't received during last import) -notification.notEvaluatedInLastImport.addAsStandaloneAction=Add as standalone script +notification.notEvaluatedInLastImport.text=Code insight unavailable (configuration for this script wasn't received during the last Gradle project import). +notification.notEvaluatedInLastImport.addAsStandaloneAction=Add to standalone scripts notification.notEvaluatedInLastImport.info=<div width=400>\ -<p>The Gradle project that evaluates this script needs to be imported to get it analyzed by the IDE.\ -Try reimport linked Gradle project or link a new Gradle project that evaluates this script.</p>\ -<br/>\ -<p>Alternatively, you can mark this script as standalone and its configuration will be loaded separately.</p>\ -<br/> \ -<p><b>NOTE:</b> Each standalone script requires separate Gradle configuration phase to be executed on update. \ -This can be expensive for large Gradle projects.</p>\ -</div> + <p>The Gradle project that evaluates this script needs to be imported to have it analyzed by the IDE. \ + Try re-importing the linked Gradle project or link a new Gradle project that evaluates this script.</p>\ + <p>Alternatively, you can add it to standalone scripts, and its configuration will be loaded separately.</p>\ + <p><b>NOTE:</b> Each standalone script requires a separate Gradle configuration phase to be executed on update. \ + This can be resource intensive for large Gradle projects.</p>\ + </div> notification.standalone.text=Standalone script -notification.standalone.disableScriptAction=Disable script +notification.standalone.disableScriptAction=Remove from standalone scripts notification.standalone.info=<div width=400>\ -<p>Configuration for this script will be loaded separately from Gradle project Sync. \ -<br/>\ -<p>This can be expensive for large Gradle projects.</p>\ -</div> + <p>The configuration for this script will be loaded separately from Gradle project sync.\ + <br/>\ + <p><b>NOTE:</b> Each standalone script requires a separate Gradle configuration phase to be executed on update. \ + This can be resource intensive for large Gradle projects.</p>\ + </div> action.text.install=Install action.text.show.kotlin.gradle.dsl.logs.in=Show Kotlin Gradle DSL Logs in {0} build.0.project=Build {0} diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt index 472e342dfef..ed399de8d81 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt @@ -49,7 +49,9 @@ fun runPartialGradleImport(project: Project, root: GradleBuildRoot) { ) } +fun getMissingConfigurationsDescription() = KotlinIdeaGradleBundle.message("notification.wasNotImportedAfterCreation.193.text") fun getMissingConfigurationActionText() = KotlinIdeaGradleBundle.message("action.label.import.project") +fun getMissingConfigurationsHelp(): String? = null fun autoReloadScriptConfigurations(project: Project, root: GradleBuildRoot): Boolean { return ExternalSystemApiUtil diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt.201 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt.201 index a26d34d684d..bd51507705f 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt.201 +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleImportHelper.kt.201 @@ -52,7 +52,9 @@ fun runPartialGradleImport(project: Project, root: GradleBuildRoot) { ) } +fun getMissingConfigurationsDescription() = KotlinIdeaGradleBundle.message("notification.wasNotImportedAfterCreation.text") fun getMissingConfigurationActionText() = KotlinIdeaGradleBundle.message("action.text.load.script.configurations") +fun getMissingConfigurationsHelp(): String? = KotlinIdeaGradleBundle.message("notification.wasNotImportedAfterCreation.help") fun autoReloadScriptConfigurations(project: Project, file: VirtualFile): Boolean { val definition = file.findScriptDefinition(project) ?: return false diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptDefinitionsProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptDefinitionsProvider.kt index e3a0ac4ed18..6235683fbe8 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptDefinitionsProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptDefinitionsProvider.kt @@ -46,7 +46,7 @@ import kotlin.script.templates.standard.ScriptTemplateWithArgs class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionSourceAsContributor { companion object { - fun getDefinitions(project: Project, workingDir: String, gradleHome: String?): List<ScriptDefinition>? { + fun getDefinitions(project: Project, workingDir: String, gradleHome: String?, javaHome: String?): List<ScriptDefinition>? { val contributor = ScriptDefinitionContributor.EP_NAME.getExtensions(project) .filterIsInstance<GradleScriptDefinitionsContributor>() .singleOrNull() @@ -63,7 +63,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD return null } - val root = LightGradleBuildRoot(workingDir, gradleHome) + val root = LightGradleBuildRoot(workingDir, gradleHome, javaHome) val definitions = contributor.definitionsByRoots[root] if (definitions == null) { scriptingInfoLog( @@ -128,7 +128,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD override val id: String = "Gradle Kotlin DSL" - private data class LightGradleBuildRoot(val workingDir: String, val gradleHome: String?) + private data class LightGradleBuildRoot(val workingDir: String, val gradleHome: String?, val javaHome: String?) private val definitionsByRoots = ConcurrentHashMap<LightGradleBuildRoot, List<ScriptDefinition>>() @@ -148,8 +148,8 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD } // TODO: remove old roots - fun reloadIfNeeded(workingDir: String, gradleHome: String?) { - val root = LightGradleBuildRoot(workingDir, gradleHome) + fun reloadIfNeeded(workingDir: String, gradleHome: String?, javaHome: String?) { + val root = LightGradleBuildRoot(workingDir, gradleHome, javaHome) val value = definitionsByRoots[root] if (value != null) { if (root.isError()) { @@ -177,15 +177,17 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD loadGradleTemplates( projectPath, templateClass = "org.gradle.kotlin.dsl.KotlinInitScript", - root.gradleHome, - templateClasspath, - additionalClassPath + gradleHome = root.gradleHome, + javaHome = root.javaHome, + templateClasspath = templateClasspath, + additionalClassPath = additionalClassPath ).let { kotlinDslTemplates.addAll(it) } loadGradleTemplates( projectPath, templateClass = "org.gradle.kotlin.dsl.KotlinSettingsScript", gradleHome = root.gradleHome, + javaHome = root.javaHome, templateClasspath = templateClasspath, additionalClassPath = additionalClassPath ).let { kotlinDslTemplates.addAll(it) } @@ -195,6 +197,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD projectPath, templateClass = "org.gradle.kotlin.dsl.KotlinBuildScript", gradleHome = root.gradleHome, + javaHome = root.javaHome, templateClasspath = templateClasspath, additionalClassPath = additionalClassPath ).let { kotlinDslTemplates.addAll(it) } @@ -223,6 +226,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD projectPath: String, templateClass: String, gradleHome: String?, + javaHome: String?, templateClasspath: List<File>, additionalClassPath: List<File> ): List<ScriptDefinition> { @@ -231,7 +235,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD projectPath, GradleConstants.SYSTEM_ID ) - val hostConfiguration = createHostConfiguration(projectPath, gradleHome, gradleExeSettings) + val hostConfiguration = createHostConfiguration(projectPath, gradleHome, javaHome, gradleExeSettings) return loadDefinitionsFromTemplates( listOf(templateClass), templateClasspath, @@ -253,6 +257,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD private fun createHostConfiguration( projectPath: String, gradleHome: String?, + javaHome: String?, gradleExeSettings: GradleExecutionSettings ): ScriptingHostConfiguration { val gradleJvmOptions = gradleExeSettings.daemonVmOptions?.let { vmOptions -> @@ -264,7 +269,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD val environment = mapOf( "gradleHome" to gradleHome?.let(::File), - "gradleJavaHome" to gradleExeSettings.javaHome, // TODO: should be taken from information from gradle sync + "gradleJavaHome" to javaHome, "projectRoot" to projectPath.let(::File), @@ -317,19 +322,20 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD // otherwise KotlinDslSyncListener should run reloadIfNeeded for valid roots GradleBuildRootsManager.getInstance(project).getAllRoots().forEach { val workingDir = it.pathPrefix - val gradleHome = when (it) { + val (gradleHome, javaHome) = when (it) { is Imported -> { - it.data.gradleHome + it.data.gradleHome to it.data.javaHome } is WithoutScriptModels -> { - ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>( + val settings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>( project, workingDir, GradleConstants.SYSTEM_ID - ).gradleHome + ) + settings.gradleHome to settings.javaHome } } - val root = LightGradleBuildRoot(workingDir, gradleHome) + val root = LightGradleBuildRoot(workingDir, gradleHome, javaHome) definitionsByRoots[root] = loadGradleDefinitions(root) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt index a617bd471b7..1adb48e4bac 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/GradleScriptNotificationProvider.kt @@ -66,11 +66,11 @@ class GradleScriptNotificationProvider(private val project: Project) : if (actions == null) null else { object : EditorNotificationPanel() { - val contextHelp = KotlinIdeaGradleBundle.message("notification.oldGradle.firstLoad.info") + val contextHelp = KotlinIdeaGradleBundle.message("notification.gradle.legacy.firstLoad.info") init { if (actions.isFirstLoad) { - text(KotlinIdeaGradleBundle.message("notification.oldGradle.firstLoad")) + text(KotlinIdeaGradleBundle.message("notification.gradle.legacy.firstLoad")) toolTipText = contextHelp } else { text(KotlinIdeaCoreBundle.message("notification.text.script.configuration.has.been.changed")) @@ -92,12 +92,13 @@ class GradleScriptNotificationProvider(private val project: Project) : } } legacyOutside -> EditorNotificationPanel().apply { - text("Out of project script") + text(KotlinIdeaGradleBundle.message("notification.gradle.legacy.outsideProject")) createActionLabel(KotlinIdeaGradleBundle.message("notification.notEvaluatedInLastImport.addAsStandaloneAction")) { rootsManager.updateStandaloneScripts { addStandaloneScript(file.path) } } + contextHelp(KotlinIdeaGradleBundle.message("notification.gradle.legacy.outsideProject.addToStandaloneHelp")) } outsideAnything -> EditorNotificationPanel().apply { text(KotlinIdeaGradleBundle.message("notification.outsideAnything.text")) @@ -106,13 +107,17 @@ class GradleScriptNotificationProvider(private val project: Project) : } } wasNotImportedAfterCreation -> EditorNotificationPanel().apply { - text(KotlinIdeaGradleBundle.message("notification.wasNotImportedAfterCreation.text")) + text(getMissingConfigurationsDescription()) createActionLabel(getMissingConfigurationActionText()) { val root = scriptUnderRoot.nearest if (root != null) { runPartialGradleImport(project, root) } } + val help = getMissingConfigurationsHelp() + if (help != null) { + contextHelp(help) + } } notEvaluatedInLastImport -> EditorNotificationPanel().apply { text(KotlinIdeaGradleBundle.message("notification.notEvaluatedInLastImport.text")) @@ -128,7 +133,7 @@ class GradleScriptNotificationProvider(private val project: Project) : contextHelp(KotlinIdeaGradleBundle.message("notification.notEvaluatedInLastImport.info")) } - standalone -> EditorNotificationPanel().apply { + standalone, standaloneLegacy -> EditorNotificationPanel().apply { val actions = standaloneScriptActions[file] if (actions != null) { text( @@ -153,7 +158,12 @@ class GradleScriptNotificationProvider(private val project: Project) : removeStandaloneScript(file.path) } } - contextHelp(KotlinIdeaGradleBundle.message("notification.standalone.info")) + + if (scriptUnderRoot.notificationKind == standaloneLegacy) { + contextHelp(KotlinIdeaGradleBundle.message("notification.gradle.legacy.standalone.info")) + } else { + contextHelp(KotlinIdeaGradleBundle.message("notification.standalone.info")) + } } } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelProcessor.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelProcessor.kt index aeb32267c15..0bfd0a14d6d 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelProcessor.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelProcessor.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel +import org.jetbrains.plugins.gradle.service.project.DefaultProjectResolverContext import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext import java.io.File @@ -28,6 +29,10 @@ fun saveGradleBuildEnvironment(resolverCtx: ProjectResolverContext) { ?: resolverCtx.settings?.gradleHome synchronized(sync) { sync.gradleVersion = resolverCtx.projectGradleVersion + sync.javaHome = (resolverCtx as? DefaultProjectResolverContext) + ?.buildEnvironment + ?.java?.javaHome?.canonicalPath + ?.let { toSystemIndependentName(it) } if (gradleHome != null) { sync.gradleHome = toSystemIndependentName(gradleHome) @@ -125,6 +130,7 @@ class KotlinDslGradleBuildSync(val workingDir: String, val taskId: ExternalSyste var project: Project? = null var gradleVersion: String? = null var gradleHome: String? = null + var javaHome: String? = null val projectRoots = mutableSetOf<String>() val models = mutableListOf<KotlinDslScriptModel>() var failed = false diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslSyncListener.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslSyncListener.kt index b3e2daef63d..7e304c834df 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslSyncListener.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslSyncListener.kt @@ -10,11 +10,15 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager import org.jetbrains.plugins.gradle.service.GradleInstallationManager +import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings +import org.jetbrains.plugins.gradle.util.GradleConstants +import java.io.File import java.util.* class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() { @@ -54,8 +58,16 @@ class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() { ?.canonicalPath } + if (sync.javaHome == null) { + sync.javaHome = ExternalSystemApiUtil + .getExecutionSettings<GradleExecutionSettings>(project, sync.workingDir, GradleConstants.SYSTEM_ID) + .javaHome + } + @Suppress("DEPRECATION") - ScriptDefinitionContributor.find<GradleScriptDefinitionsContributor>(project)?.reloadIfNeeded(sync.workingDir, sync.gradleHome) + ScriptDefinitionContributor.find<GradleScriptDefinitionsContributor>(project)?.reloadIfNeeded( + sync.workingDir, sync.gradleHome, sync.javaHome + ) saveScriptModels(project, sync) } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt index 05b2b75c94a..8058f1d5cb5 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt @@ -88,19 +88,20 @@ class New( */ class Imported( override val pathPrefix: String, - val javaHome: File?, val data: GradleBuildRootData, lastModifiedFiles: LastModifiedFiles ) : GradleBuildRoot(lastModifiedFiles) { override val projectRoots: Collection<String> get() = data.projectRoots + val javaHome = data.javaHome?.takeIf { it.isNotBlank() }?.let { File(it) } + fun collectConfigurations(builder: ScriptClassRootsBuilder) { if (javaHome != null) { builder.sdks.addSdk(javaHome) } - val definitions = GradleScriptDefinitionsContributor.getDefinitions(builder.project, pathPrefix, data.gradleHome) + val definitions = GradleScriptDefinitionsContributor.getDefinitions(builder.project, pathPrefix, data.gradleHome, data.javaHome) if (definitions == null) { // needed to recreate classRoots if correct script definitions weren't loaded at this moment // in this case classRoots will be recreated after script definitions update diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootData.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootData.kt index 6704da8b41d..899aab6f84e 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootData.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootData.kt @@ -11,5 +11,6 @@ data class GradleBuildRootData( val importTs: Long, val projectRoots: Collection<String>, val gradleHome: String, + val javaHome: String?, val models: Collection<KotlinDslScriptModel> )
\ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootDataSerializer.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootDataSerializer.kt index 8f5789ab500..1de257bc5c2 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootDataSerializer.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootDataSerializer.kt @@ -19,7 +19,7 @@ import java.io.DataInputStream import java.io.DataOutput internal object GradleBuildRootDataSerializer { - private val attribute = FileAttribute("kotlin-dsl-script-models", 7, false) + private val attribute = FileAttribute("kotlin-dsl-script-models", 8, false) fun read(buildRoot: VirtualFile): GradleBuildRootData? { return attribute.readAttribute(buildRoot)?.use { @@ -47,6 +47,7 @@ internal fun writeKotlinDslScriptModels(output: DataOutput, data: GradleBuildRoo val strings = StringsPool.writer(output) strings.addStrings(data.projectRoots) strings.addString(data.gradleHome) + strings.addString(data.javaHome) data.models.forEach { strings.addString(it.file) strings.addStrings(it.classPath) @@ -57,6 +58,7 @@ internal fun writeKotlinDslScriptModels(output: DataOutput, data: GradleBuildRoo output.writeLong(data.importTs) strings.writeStringIds(data.projectRoots) strings.writeStringId(data.gradleHome) + strings.writeStringId(data.javaHome) output.writeList(data.models) { strings.writeStringId(it.file) output.writeString(it.inputs.sections) @@ -73,6 +75,7 @@ internal fun readKotlinDslScriptModels(input: DataInputStream, buildRoot: String val importTs = input.readLong() val projectRoots = strings.readStrings() val gradleHome = strings.readString() + val javaHome = strings.readNullableString() val models = input.readList { KotlinDslScriptModel( strings.readString(), @@ -84,7 +87,7 @@ internal fun readKotlinDslScriptModels(input: DataInputStream, buildRoot: String ) } - return GradleBuildRootData(importTs, projectRoots, gradleHome, models) + return GradleBuildRootData(importTs, projectRoots, gradleHome, javaHome, models) } private object StringsPool { @@ -99,8 +102,8 @@ private object StringsPool { ids.size } - fun addString(string: String) { - getStringId(string) + fun addString(string: String?) { + getStringId(string ?: "null") } fun addStrings(list: Collection<String>) { @@ -119,8 +122,8 @@ private object StringsPool { } } - fun writeStringId(it: String) { - output.writeInt(getStringId(it)) + fun writeStringId(it: String?) { + output.writeInt(getStringId(it ?: "null")) } fun writeStringIds(strings: Collection<String>) { @@ -140,6 +143,11 @@ private object StringsPool { fun getString(id: Int) = strings[id] fun readString() = getString(input.readInt()) + fun readNullableString(): String? { + val string = getString(input.readInt()) + if (string == "null") return null + return string + } fun readStrings(): List<String> = input.readList { readString() } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt index 6561bfa55d9..5c67eb2f3c3 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt @@ -69,7 +69,8 @@ abstract class GradleBuildRootsLocator { outsideAnything, // suggest link related gradle build or just say that there is no one wasNotImportedAfterCreation, // project not yet imported after this file was created notEvaluatedInLastImport, // all other scripts, suggest to sync or mark as standalone - standalone + standalone, + standaloneLegacy } /** @@ -88,7 +89,10 @@ abstract class GradleBuildRootsLocator { val notificationKind: NotificationKind get() = when { isImported -> NotificationKind.dontCare - standalone -> NotificationKind.standalone + standalone -> when (nearest) { + is Legacy -> NotificationKind.standaloneLegacy + else -> NotificationKind.standalone + } nearest == null -> NotificationKind.outsideAnything importing -> NotificationKind.dontCare else -> when (nearest) { diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt index 0be78159dac..6e2890178ae 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt @@ -161,7 +161,10 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), return } - val newData = GradleBuildRootData(sync.ts, sync.projectRoots, gradleHome, sync.models) + + val newData = GradleBuildRootData( + sync.ts, sync.projectRoots, gradleHome, sync.javaHome, sync.models + ) val mergedData = if (sync.failed && oldRoot is Imported) merge(oldRoot.data, newData) else newData val lastModifiedFilesReset = LastModifiedFiles() @@ -183,7 +186,7 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), val models = old.models.associateByTo(mutableMapOf()) { it.file } new.models.associateByTo(models) { it.file } - return GradleBuildRootData(new.importTs, roots, new.gradleHome, models.values) + return GradleBuildRootData(new.importTs, roots, new.gradleHome, new.javaHome, models.values) } private val modifiedFilesCheckScheduled = AtomicBoolean() @@ -345,12 +348,8 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), ): Imported? { val buildRoot = VfsUtil.findFile(Paths.get(externalProjectPath), true) ?: return null val data = dataProvider(buildRoot) ?: return null - // TODO: can be outdated, should be taken from sync - val javaHome = ExternalSystemApiUtil - .getExecutionSettings<GradleExecutionSettings>(project, externalProjectPath, GradleConstants.SYSTEM_ID) - .javaHome?.let { File(it) } - return Imported(externalProjectPath, javaHome, data, lastModifiedFiles) + return Imported(externalProjectPath, data, lastModifiedFiles) } private fun add(newRoot: GradleBuildRoot) { diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/statistics/KotlinGradleFUSLogger.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/statistics/KotlinGradleFUSLogger.kt index 36bf1e6b8b5..ed29b2ad772 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/statistics/KotlinGradleFUSLogger.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/statistics/KotlinGradleFUSLogger.kt @@ -94,7 +94,9 @@ class KotlinGradleFUSLogger : StartupActivity, DumbAware, Runnable { BooleanMetrics.ENABLED_COMPILER_PLUGIN_ALL_OPEN, BooleanMetrics.ENABLED_COMPILER_PLUGIN_NO_ARG, BooleanMetrics.ENABLED_COMPILER_PLUGIN_JPA_SUPPORT, - BooleanMetrics.ENABLED_COMPILER_PLUGIN_SAM_WITH_RECEIVER + BooleanMetrics.ENABLED_COMPILER_PLUGIN_SAM_WITH_RECEIVER, + BooleanMetrics.JVM_COMPILER_IR_MODE, + StringMetrics.JVM_DEFAULTS ) container.log( @@ -153,7 +155,8 @@ class KotlinGradleFUSLogger : StartupActivity, DumbAware, Runnable { NumericalMetrics.GRADLE_BUILD_DURATION, NumericalMetrics.GRADLE_EXECUTION_DURATION, NumericalMetrics.NUMBER_OF_SUBPROJECTS, - NumericalMetrics.STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD + NumericalMetrics.STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD, + NumericalMetrics.STATISTICS_COLLECT_METRICS_OVERHEAD ) val finishTime = container.getMetric(NumericalMetrics.BUILD_FINISH_TIME)?.getValue() diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleBuildRootDataSerializerTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleBuildRootDataSerializerTest.kt index a59a5f2ef2b..951bad18de0 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleBuildRootDataSerializerTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/GradleBuildRootDataSerializerTest.kt @@ -22,10 +22,11 @@ class GradleBuildRootDataSerializerTest { val data = GradleBuildRootData( 123, listOf("a", "b", "c"), - "a", + "gradleHome", + "javaHome", listOf( KotlinDslScriptModel( - "a", + "gradleHome", GradleKotlinScriptConfigurationInputs("b", 1, "a"), listOf("c", "a", "b"), listOf("b", "c", "a"), @@ -33,7 +34,7 @@ class GradleBuildRootDataSerializerTest { listOf() ), KotlinDslScriptModel( - "a", + "gradleHome", GradleKotlinScriptConfigurationInputs("b", 1, "a"), listOf("c", "a", "b"), listOf("b", "c", "a"), @@ -50,4 +51,22 @@ class GradleBuildRootDataSerializerTest { assertEquals(data.toString(), restored.toString()) } + + @Test + fun writeNullable() { + val data = GradleBuildRootData( + 0, + listOf(), + "null", + null, + listOf() + ) + + val buffer = ByteArrayOutputStream() + writeKotlinDslScriptModels(DataOutputStream(buffer), data) + + val restored = readKotlinDslScriptModels(DataInputStream(ByteArrayInputStream(buffer.toByteArray())), "a") + + assertEquals(data.toString(), restored.toString()) + } }
\ No newline at end of file diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/roots/AbstractGradleBuildRootsLocatorTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/roots/AbstractGradleBuildRootsLocatorTest.kt index 4654809daac..c328966846d 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/roots/AbstractGradleBuildRootsLocatorTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/scripting/gradle/roots/AbstractGradleBuildRootsLocatorTest.kt @@ -35,11 +35,11 @@ open class AbstractGradleBuildRootsLocatorTest { val pathPrefix = "$dir/" val root = Imported( dir, - null, GradleBuildRootData( ts, relativeProjectRoots.map { (pathPrefix + it).removeSuffix("/") }, - "", + "gradleHome", + "javaHome", listOf() ), LastModifiedFiles() diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt index 4a701566fb6..1f640cd260c 100644 --- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativePlatformKindResolution.kt @@ -153,6 +153,7 @@ class NativePlatformKindResolution : IdePlatformKindResolution { class NativeKlibLibraryInfo(project: Project, library: Library, libraryRoot: String) : AbstractKlibLibraryInfo(project, library, libraryRoot) { + // If you're changing this, please take a look at ideaModelDependencies as well val isStdlib: Boolean get() = libraryRoot.endsWith(KONAN_STDLIB_NAME) override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt index 1b158bb286a..dde90958b19 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep +import com.intellij.ui.JBColor import com.intellij.ui.ScrollPaneFactory import com.intellij.ui.SeparatorWithText import com.intellij.util.ui.JBUI @@ -15,6 +16,7 @@ import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.* import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator import java.awt.Dimension +import javax.swing.BorderFactory import javax.swing.Icon import javax.swing.JComponent @@ -43,12 +45,10 @@ class ProjectTemplateSettingComponent( onValueSelected = { value = it } ) - private val scrollPane = ScrollPaneFactory.createScrollPane(list).apply { - preferredSize = Dimension(minimumSize.width, HEIGHT) - } + private val borderedPanel = list.addBorder(BorderFactory.createLineBorder(JBColor.border())) override val component: JComponent = borderPanel { - addToCenter(borderPanel { addToCenter(scrollPane) }.addBorder(JBUI.Borders.empty(0,/*left*/ 3, 0, /*right*/ 3))) + addToCenter(borderPanel { addToCenter(list) }.addBorder(JBUI.Borders.empty(0,/*left*/ 3, 0, /*right*/ 3))) addToBottom(templateDescriptionComponent.component.addBorder(JBUI.Borders.empty(/*top*/8,/*left*/ 3, 0, 0))) } @@ -74,10 +74,6 @@ class ProjectTemplateSettingComponent( value = setting.type.values.firstOrNull() } } - - companion object { - private const val HEIGHT = 310 - } } private val ProjectTemplate.icon: Icon diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 index d69db4cc07d..515b85274e8 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 @@ -51,7 +51,16 @@ class SuspendCoroutineStackFrameItem( val stackTraceElement: StackTraceElement, location: Location, spilledVariables: List<XNamedValue> = emptyList() -) : CoroutineStackFrameItem(location, spilledVariables) +) : CoroutineStackFrameItem(location, spilledVariables) { + override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? { + return debugProcess.invokeInManagerThread { + val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null + val locationFrame = LocationStackFrameProxyImpl(location, frame) + val position = location.findPosition(debugProcess.project) + CoroutineStackFrame(locationFrame, position, spilledVariables, includeFrameVariables = false) + } + } +} /** diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt index 173ac5380ae..fb39ff7a3ac 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.xdebugger.frame.XNamedValue +import com.sun.jdi.ObjectReference import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineNameIdState import org.jetbrains.kotlin.idea.debugger.coroutine.data.CreationCoroutineStackFrameItem @@ -32,11 +33,7 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution private fun mapToCoroutineInfoData(mirror: MirrorOfCoroutineInfo): CoroutineInfoData? { val coroutineNameIdState = CoroutineNameIdState.instance(mirror) val stackTrace = mirror.enhancedStackTrace?.mapNotNull { it.stackTraceElement() } ?: emptyList() - val variables: List<XNamedValue> = mirror.lastObservedFrame?.let { - val spilledVariables = debugMetadata?.baseContinuationImpl?.mirror(it, executionContext) - spilledVariables?.spilledValues(executionContext) - } ?: emptyList() - val stackFrames = findStackFrames(stackTrace, variables) + val stackFrames = findStackFrames(stackTrace, mirror.lastObservedFrame) return CoroutineInfoData( coroutineNameIdState, stackFrames.restoredStackFrames, @@ -57,14 +54,24 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution private fun findStackFrames( frames: List<StackTraceElement>, - variables: List<XNamedValue> + lastObservedFrame: ObjectReference? ): CoroutineStackFrames { val index = frames.indexOfFirst { it.isCreationSeparatorFrame() } val restoredStackTraceElements = if (index >= 0) frames.take(index) else frames + + var observedFrame = lastObservedFrame val restoredStackFrames = restoredStackTraceElements.map { + val variables: List<XNamedValue> = observedFrame?.let { + val spilledVariables = debugMetadata?.baseContinuationImpl?.mirror(it, executionContext) + if (spilledVariables != null) { + observedFrame = spilledVariables.nextContinuation + spilledVariables.spilledValues(executionContext) + } else + null + } ?: emptyList() SuspendCoroutineStackFrameItem(it, locationCache.createLocation(it), variables) } val creationStackFrames = frames.subList(index + 1, frames.size).mapIndexed { ix, it -> diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt index b2176ec315e..1391ab4eef8 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt @@ -141,7 +141,7 @@ class CoroutineInfo private constructor( debugProbesImplMirror.enhanceStackTraceWithThreadDump(context, value, lastObservedStackTrace) else emptyList() val lastObservedThread = threadValue(value, lastObservedThreadField) - val lastObservedFrame = threadValue(value, lastObservedFrameField) + val lastObservedFrame = objectValue(value, lastObservedFrameField) return MirrorOfCoroutineInfo( value, coroutineContext, diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt index f3dc51bc940..19c8f6aed8e 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt @@ -20,6 +20,8 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.Exec import org.gradle.api.tasks.TaskProvider import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel.Companion.NO_KOTLIN_NATIVE_HOME +import org.jetbrains.kotlin.gradle.KotlinSourceSet.Companion.COMMON_MAIN_SOURCE_SET_NAME +import org.jetbrains.kotlin.gradle.KotlinSourceSet.Companion.COMMON_TEST_SOURCE_SET_NAME import org.jetbrains.plugins.gradle.DefaultExternalDependencyId import org.jetbrains.plugins.gradle.model.* import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder @@ -58,7 +60,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { val sourceSets = buildSourceSets(dependencyResolver, project, dependencyMapper) ?: return null val sourceSetMap = sourceSets.map { it.name to it }.toMap() val targets = buildTargets(projectTargets, sourceSetMap, dependencyResolver, project, dependencyMapper) ?: return null - computeSourceSetsDeferredInfo(sourceSetMap, targets, isHMPPEnabled(project)) + computeSourceSetsDeferredInfo(sourceSetMap, targets, isHMPPEnabled(project), shouldCoerceRootSourceSetToCommon(project)) val coroutinesState = getCoroutinesState(project) reportUnresolvedDependencies(targets) val kotlinNativeHome = KotlinNativeHomeEvaluator.getKotlinNativeHome(project) ?: NO_KOTLIN_NATIVE_HOME @@ -94,6 +96,10 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { return (project.findProperty("kotlin.mpp.enableGranularSourceSetsMetadata") as? String)?.toBoolean() ?: false } + private fun shouldCoerceRootSourceSetToCommon(project: Project): Boolean { + return (project.findProperty("kotlin.mpp.coerceRootSourceSetsToCommon") as? String)?.toBoolean() ?: true + } + private fun isNativeDependencyPropagationEnabled(project: Project): Boolean { return (project.findProperty("kotlin.native.enableDependencyPropagation") as? String)?.toBoolean() ?: true } @@ -771,7 +777,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { private fun computeSourceSetsDeferredInfo( sourceSets: Map<String, KotlinSourceSetImpl>, targets: Collection<KotlinTarget>, - isHMPPEnabled: Boolean + isHMPPEnabled: Boolean, + coerceRootSourceSetsToCommon: Boolean ) { // includes only compilations where source set is listed val compiledSourceSetToCompilations = LinkedHashMap<KotlinSourceSet, MutableSet<KotlinCompilation>>() @@ -810,12 +817,32 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { val platforms = compilations.map { it.platform } sourceSet.actualPlatforms.addSimplePlatforms(platforms) } - if ((!isHMPPEnabled) && sourceSet.actualPlatforms.platforms.size != 1) { + + if (sourceSet.shouldCoerceToCommon(isHMPPEnabled, coerceRootSourceSetsToCommon)) { sourceSet.actualPlatforms.addSimplePlatforms(listOf(KotlinPlatform.COMMON)) } } } + private fun KotlinSourceSetImpl.shouldCoerceToCommon(isHMPPEnabled: Boolean, coerceRootSourceSetsToCommon: Boolean): Boolean { + val isRoot = name == COMMON_MAIN_SOURCE_SET_NAME || name == COMMON_TEST_SOURCE_SET_NAME + + // never makes sense to coerce single-targeted source-sets + if (actualPlatforms.platforms.size == 1) return false + + return when { + // pre-HMPP has only single-targeted source sets and COMMON + !isHMPPEnabled -> true + + // in HMPP, we might want to coerce source sets to common, but only root ones, and only + // when the corresponding setting is turned on + isHMPPEnabled && isRoot && coerceRootSourceSetsToCommon -> true + + // in all other cases, in HMPP we shouldn't coerce anything + else -> false + } + } + private class DependencyAdjuster( private val configuration: Configuration, private val scope: String, diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/testFramework/ProjectOpenAction.kt b/idea/performanceTests/test/org/jetbrains/kotlin/idea/testFramework/ProjectOpenAction.kt index 2d2cdb69777..bf1a742c0a1 100644 --- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/testFramework/ProjectOpenAction.kt +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/testFramework/ProjectOpenAction.kt @@ -26,11 +26,11 @@ import com.intellij.util.io.exists import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure import org.jetbrains.kotlin.idea.perf.util.logMessage +import org.jetbrains.kotlin.idea.project.ResolveElementCache import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import java.io.File import java.nio.file.Paths -import kotlin.test.assertNotNull import kotlin.test.assertTrue data class OpenProject(val projectPath: String, val projectName: String, val jdk: Sdk, val projectOpenAction: ProjectOpenAction) @@ -64,7 +64,7 @@ enum class ProjectOpenAction { val projectManagerEx = ProjectManagerEx.getInstanceEx() val project = loadProjectWithName(projectPath, projectName) - assertNotNull(project, "project $projectName at $projectPath is not loaded") + ?: error("project $projectName at $projectPath is not loaded") runWriteAction { ProjectRootManager.getInstance(project).projectSdk = jdk @@ -123,6 +123,7 @@ enum class ProjectOpenAction { open fun postOpenProject(project: Project, openProject: OpenProject) { ApplicationManager.getApplication().executeOnPooledThread { + ResolveElementCache.forceFullAnalysisModeInTests = true DumbService.getInstance(project).waitForSmartMode() for (module in getModulesWithKotlinFiles(project)) { diff --git a/idea/resources-en/inspectionDescriptions/ObsoleteKotlinJsPackages.html b/idea/resources-en/inspectionDescriptions/ObsoleteKotlinJsPackages.html new file mode 100644 index 00000000000..04ebed2fd4b --- /dev/null +++ b/idea/resources-en/inspectionDescriptions/ObsoleteKotlinJsPackages.html @@ -0,0 +1,6 @@ +<html> +<body> +This inspection reports usages of 'kotlin.dom' and 'kotlin.browser' packages which were moved to 'kotlinx.dom' and 'kotlinx.browser' +respectively in Kotlin 1.4+. +</body> +</html>
\ No newline at end of file diff --git a/idea/resources-en/messages/KotlinBundle.properties b/idea/resources-en/messages/KotlinBundle.properties index fb41c349bc6..675cca55c97 100644 --- a/idea/resources-en/messages/KotlinBundle.properties +++ b/idea/resources-en/messages/KotlinBundle.properties @@ -1310,11 +1310,14 @@ missing.documentation=Missing documentation library.should.be.updated.to.be.compatible.with.kotlin.1.3=Library should be updated to be compatible with Kotlin 1.3 it.s.prohibited.to.call.0.with.min.value.step.since.1.3=It''s prohibited to call {0} with MIN_VALUE step since 1.3 obsolete.coroutine.usage.in.whole.fix.family.name=Fix experimental coroutines usages in the project +obsolete.kotlin.js.packages.usage.in.whole.fix.family.name=Fix 'kotlin.dom' and 'kotlin.browser' packages usages in the project apply.in.the.project.0=Apply in the project: {0} obsolete.coroutine.usage.fix.family.name=Fix experimental coroutines usage +obsolete.package.usage.fix.family.name=Fix ''{0}'' package usage 0.is.expected.to.be.used.since.kotlin.1.3=`{0}` is expected to be used since Kotlin 1.3 methods.are.absent.in.coroutines.class.since.1.3=Methods are absent in coroutines class since 1.3 experimental.coroutines.usages.are.obsolete.since.1.3=Experimental coroutines usages are obsolete since 1.3 +package.usages.are.obsolete.since.1.4=''{0}'' package usages are obsolete since 1.4 replace.substring.call.with.droplast.call=Replace 'substring' call with 'dropLast' call replace.substring.call.with.indexing.operation.call=Replace 'substring' call with indexing operation call replace.substring.call.with.substringbefore.call=Replace 'substring' call with 'substringBefore' call @@ -2021,6 +2024,7 @@ inspection.suspicious.as.dynamic.display.name=Suspicious 'asDynamic' member invo inspection.convert.call.chain.into.sequence.display.name=Call chain on collection could be converted into 'Sequence' to improve performance inspection.redundant.with.display.name=Redundant 'with' call inspection.obsolete.experimental.coroutines.display.name=Experimental coroutines usages are deprecated since 1.3 +inspection.obsolete.kotlin.js.packages.display.name='kotlin.browser' and 'kotlin.dom' packages are deprecated since 1.4 inspection.warning.on.main.unused.parameter.migration.display.name=Unused `args` on `main` since 1.4 inspection.prohibit.repeated.use.site.target.annotations.migration.display.name=Repeatable annotation without `@Repeatable` are not allowed since 1.4 inspection.prohibit.use.site.target.annotations.on.super.types.migration.display.name=Annotations on superclass are meaningless since 1.4 diff --git a/idea/resources/META-INF/kotlinx-serialization.xml b/idea/resources/META-INF/kotlinx-serialization.xml index 4ad16af7a6a..3e2a22229ab 100644 --- a/idea/resources/META-INF/kotlinx-serialization.xml +++ b/idea/resources/META-INF/kotlinx-serialization.xml @@ -5,5 +5,6 @@ <jsSyntheticTranslateExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEJsExtension"/> <irGenerationExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEIrExtension"/> <storageComponentContainerContributor implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEContainerContributor"/> + <quickFixContributor implementation="org.jetbrains.kotlinx.serialization.idea.quickfixes.SerializationQuickFixContributor"/> </extensions> </idea-plugin> diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index b66ce3553aa..bbc463bd129 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -2981,6 +2981,15 @@ language="kotlin" key="inspection.obsolete.experimental.coroutines.display.name" bundle="messages.KotlinBundle"/> + <localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.migration.ObsoleteKotlinJsPackagesInspection" + groupPath="Kotlin" + groupName="Migration" + enabledByDefault="true" + cleanupTool="true" + level="ERROR" + language="kotlin" + key="inspection.obsolete.kotlin.js.packages.display.name" bundle="messages.KotlinBundle"/> + <localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.RedundantWithInspection" groupPath="Kotlin" groupName="Redundant constructs" diff --git a/idea/resources/META-INF/plugin.xml.as36 b/idea/resources/META-INF/plugin.xml.as36 index 51d6b78069a..68bc12922e3 100644 --- a/idea/resources/META-INF/plugin.xml.as36 +++ b/idea/resources/META-INF/plugin.xml.as36 @@ -13,7 +13,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. <version>@snapshot@</version> <vendor url="http://www.jetbrains.com">JetBrains</vendor> - <idea-version since-build="192.7142.36.36.6071332" until-build="192.*"/> + <idea-version since-build="192.7142.36" until-build="192.*"/> <depends>com.intellij.modules.platform</depends> <depends>com.intellij.modules.androidstudio</depends> diff --git a/idea/resources/META-INF/plugin.xml.as40 b/idea/resources/META-INF/plugin.xml.as40 index aaf86185a64..a6a2a8cc2d7 100644 --- a/idea/resources/META-INF/plugin.xml.as40 +++ b/idea/resources/META-INF/plugin.xml.as40 @@ -13,7 +13,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. <version>@snapshot@</version> <vendor url="http://www.jetbrains.com">JetBrains</vendor> - <idea-version since-build="193.5233.102.40.6085562" until-build="193.*"/> + <idea-version since-build="193.5233.102" until-build="193.*"/> <depends>com.intellij.modules.platform</depends> <depends>com.intellij.modules.androidstudio</depends> diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteCodeMigrationInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteCodeMigrationInspection.kt new file mode 100644 index 00000000000..a39f8a4074d --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteCodeMigrationInspection.kt @@ -0,0 +1,197 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.inspections.migration + +import com.intellij.analysis.AnalysisScope +import com.intellij.codeInspection.* +import com.intellij.codeInspection.actions.RunInspectionIntention +import com.intellij.codeInspection.ex.InspectionManagerEx +import com.intellij.codeInspection.ex.InspectionProfileImpl +import com.intellij.codeInspection.ex.InspectionToolWrapper +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.project.Project +import com.intellij.profile.codeInspection.InspectionProjectProfileManager +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.configuration.MigrationInfo +import org.jetbrains.kotlin.idea.configuration.isLanguageVersionUpdate +import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection +import org.jetbrains.kotlin.idea.project.languageVersionSettings +import org.jetbrains.kotlin.idea.quickfix.migration.MigrationFix +import org.jetbrains.kotlin.idea.references.KtSimpleNameReference +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.parents + +internal abstract class ObsoleteCodeMigrationInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool, MigrationFix { + protected abstract val fromVersion: LanguageVersion + protected abstract val toVersion: LanguageVersion + protected abstract val problemReporters: List<ObsoleteCodeProblemReporter> + + final override fun isApplicable(migrationInfo: MigrationInfo): Boolean { + return migrationInfo.isLanguageVersionUpdate(fromVersion, toVersion) + } + + final override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): KtVisitorVoid { + return simpleNameExpressionVisitor(fun(simpleNameExpression) { + val versionIsSatisfied = simpleNameExpression.languageVersionSettings.languageVersion >= toVersion + if (!versionIsSatisfied && !ApplicationManager.getApplication().isUnitTestMode) { + return + } + + for (reporter in problemReporters) { + if (reporter.report(holder, isOnTheFly, simpleNameExpression)) { + return + } + } + }) + } +} + +internal interface ObsoleteCodeProblemReporter { + fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean +} + +internal interface ObsoleteCodeFix { + fun applyFix(project: Project, descriptor: ProblemDescriptor) +} + +// Shortcut quick fix for running inspection in the project scope. +// Should work like RunInspectionAction.runInspection. +internal abstract class ObsoleteCodeInWholeProjectFix : LocalQuickFix { + protected abstract val inspectionName: String + + final override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val toolWrapper = InspectionProjectProfileManager.getInstance(project).currentProfile.getInspectionTool(inspectionName, project)!! + runToolInProject(project, toolWrapper) + } + + final override fun startInWriteAction(): Boolean = false + + private fun runToolInProject(project: Project, toolWrapper: InspectionToolWrapper<*, *>) { + val managerEx = InspectionManager.getInstance(project) as InspectionManagerEx + val kotlinSourcesScope: GlobalSearchScope = KotlinSourceFilterScope.projectSources(GlobalSearchScope.allScope(project), project) + val cleanupScope = AnalysisScope(kotlinSourcesScope, project) + + val cleanupToolProfile = runInInspectionProfileInitMode { RunInspectionIntention.createProfile(toolWrapper, managerEx, null) } + managerEx.createNewGlobalContext(false) + .codeCleanup( + cleanupScope, + cleanupToolProfile, + KotlinBundle.message("apply.in.the.project.0", toolWrapper.displayName), + null, + false + ) + } + + // Overcome failure during profile creating because of absent tools in tests + private inline fun <T> runInInspectionProfileInitMode(runnable: () -> T): T { + return if (!ApplicationManager.getApplication().isUnitTestMode) { + runnable() + } else { + val old = InspectionProfileImpl.INIT_INSPECTIONS + try { + InspectionProfileImpl.INIT_INSPECTIONS = true + runnable() + } finally { + InspectionProfileImpl.INIT_INSPECTIONS = old + } + } + } +} + +/** + * There should be a single fix class with the same family name, this way it can be executed for all found problems from UI. + */ +internal abstract class ObsoleteCodeFixDelegateQuickFix(private val delegate: ObsoleteCodeFix) : LocalQuickFix { + final override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + delegate.applyFix(project, descriptor) + } +} + +internal abstract class ObsoleteImportsUsageReporter : ObsoleteCodeProblemReporter { + /** + * Required to report the problem only on one psi element instead of the every single qualifier + * in the import statement. + */ + protected abstract val textMarker: String + + protected abstract val packageBindings: Map<String, String> + protected open val importsToRemove: Set<String> = emptySet() + + protected abstract val wholeProjectFix: LocalQuickFix + protected abstract fun problemMessage(): String + + protected abstract fun wrapFix(fix: ObsoleteCodeFix): LocalQuickFix + + final override fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean { + if (simpleNameExpression.text != textMarker) return false + + val parent = simpleNameExpression.parent as? KtExpression ?: return false + val reportExpression = parent as? KtDotQualifiedExpression ?: simpleNameExpression + + findBinding(simpleNameExpression) ?: return false + + holder.registerProblem( + reportExpression, + problemMessage(), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + *fixesWithWholeProject(isOnTheFly, wrapFix(ObsoleteImportFix()), wholeProjectFix) + ) + + return true + } + + private fun findBinding(simpleNameExpression: KtSimpleNameExpression): Binding? { + if (simpleNameExpression.text != textMarker) return null + + val importDirective = simpleNameExpression.parents + .takeWhile { it is KtDotQualifiedExpression || it is KtImportDirective } + .lastOrNull() as? KtImportDirective ?: return null + + val fqNameStr = importDirective.importedFqName?.asString() ?: return null + + val bindEntry = packageBindings.entries.find { (affectedImportPrefix, _) -> + fqNameStr.startsWith(affectedImportPrefix) + } ?: return null + + return Binding( + FqName(bindEntry.value), + fqNameStr in importsToRemove, + importDirective + ) + } + + private inner class ObsoleteImportFix : ObsoleteCodeFix { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val simpleNameExpression = when (val element = descriptor.psiElement) { + is KtSimpleNameExpression -> element + is KtDotQualifiedExpression -> element.selectorExpression as? KtSimpleNameExpression + else -> null + } ?: return + + val binding = findBinding(simpleNameExpression) ?: return + + if (binding.shouldRemove) { + binding.importDirective.delete() + } else { + simpleNameExpression.mainReference.bindToFqName( + binding.bindTo, shorteningMode = KtSimpleNameReference.ShorteningMode.NO_SHORTENING + ) + } + } + } + + private class Binding( + val bindTo: FqName, + val shouldRemove: Boolean, + val importDirective: KtImportDirective + ) +} + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt index 089c7a0c27e..b3305c05f45 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteExperimentalCoroutinesInspection.kt @@ -5,158 +5,63 @@ package org.jetbrains.kotlin.idea.inspections.migration -import com.intellij.analysis.AnalysisScope -import com.intellij.codeInspection.* -import com.intellij.codeInspection.actions.RunInspectionIntention -import com.intellij.codeInspection.ex.InspectionManagerEx -import com.intellij.codeInspection.ex.InspectionProfileImpl -import com.intellij.codeInspection.ex.InspectionToolWrapper -import com.intellij.openapi.application.ApplicationManager +import com.intellij.codeInspection.LocalQuickFix +import com.intellij.codeInspection.ProblemDescriptor +import com.intellij.codeInspection.ProblemHighlightType +import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.project.Project -import com.intellij.profile.codeInspection.InspectionProjectProfileManager import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedRefactoringRequests -import org.jetbrains.kotlin.idea.configuration.MigrationInfo -import org.jetbrains.kotlin.idea.configuration.isLanguageVersionUpdate import org.jetbrains.kotlin.idea.imports.importableFqName -import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection -import org.jetbrains.kotlin.idea.project.languageVersionSettings -import org.jetbrains.kotlin.idea.quickfix.migration.MigrationFix import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors -import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.parents +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull -class ObsoleteExperimentalCoroutinesInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool, MigrationFix { - override fun isApplicable(migrationInfo: MigrationInfo): Boolean { - return migrationInfo.isLanguageVersionUpdate(LanguageVersion.KOTLIN_1_2, LanguageVersion.KOTLIN_1_3) - } - - override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): KtVisitorVoid { - return simpleNameExpressionVisitor(fun(simpleNameExpression) { - run { - val versionAtLeast13 = simpleNameExpression.languageVersionSettings.languageVersion >= LanguageVersion.KOTLIN_1_3 - if (!versionAtLeast13 && !ApplicationManager.getApplication().isUnitTestMode) { - return - } - } +internal class ObsoleteExperimentalCoroutinesInspection : ObsoleteCodeMigrationInspection() { + override val fromVersion: LanguageVersion = LanguageVersion.KOTLIN_1_2 + override val toVersion: LanguageVersion = LanguageVersion.KOTLIN_1_3 - for (registeredProblem in PROBLEMS) { - if (registeredProblem.report(holder, isOnTheFly, simpleNameExpression)) { - return - } - } - }) - } - - companion object { - private val PROBLEMS = listOf( - ObsoleteTopLevelFunctionUsage( - "buildSequence", - "kotlin.coroutines.experimental.buildSequence", - "kotlin.sequences.sequence" - ), - ObsoleteTopLevelFunctionUsage( - "buildIterator", - "kotlin.coroutines.experimental.buildIterator", - "kotlin.sequences.iterator" - ), - ObsoleteExtensionFunctionUsage( - "resume", - "kotlin.coroutines.experimental.Continuation.resume", - "kotlin.coroutines.resume" - ), - ObsoleteExtensionFunctionUsage( - "resumeWithException", - "kotlin.coroutines.experimental.Continuation.resumeWithException", - "kotlin.coroutines.resumeWithException" - ), - ExperimentalImportUsage() - ) - } -} - -private interface CoroutineMigrationProblem { - fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean + override val problemReporters = listOf( + ObsoleteTopLevelFunctionUsageReporter( + "buildSequence", + "kotlin.coroutines.experimental.buildSequence", + "kotlin.sequences.sequence" + ), + ObsoleteTopLevelFunctionUsageReporter( + "buildIterator", + "kotlin.coroutines.experimental.buildIterator", + "kotlin.sequences.iterator" + ), + ObsoleteExtensionFunctionUsageReporter( + "resume", + "kotlin.coroutines.experimental.Continuation.resume", + "kotlin.coroutines.resume" + ), + ObsoleteExtensionFunctionUsageReporter( + "resumeWithException", + "kotlin.coroutines.experimental.Continuation.resumeWithException", + "kotlin.coroutines.resumeWithException" + ), + ObsoleteCoroutinesImportsUsageReporter + ) } -// Shortcut quick fix for running inspection in the project scope. -// Should work like RunInspectionAction.runInspection. -private class ObsoleteCoroutineUsageInWholeFix : LocalQuickFix { +private object ObsoleteCoroutinesUsageInWholeProjectFix : ObsoleteCodeInWholeProjectFix() { + override val inspectionName = ObsoleteExperimentalCoroutinesInspection().shortName override fun getFamilyName(): String = KotlinBundle.message("obsolete.coroutine.usage.in.whole.fix.family.name") - - override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - val toolWrapper = InspectionProjectProfileManager.getInstance(project).currentProfile.getInspectionTool( - ObsoleteExperimentalCoroutinesInspection().shortName, - project - )!! - - runToolInProject(project, toolWrapper) - } - - override fun startInWriteAction(): Boolean = false - - companion object { - val INSTANCE = ObsoleteCoroutineUsageInWholeFix() - - private fun runToolInProject(project: Project, toolWrapper: InspectionToolWrapper<*, *>) { - val managerEx = InspectionManager.getInstance(project) as InspectionManagerEx - val kotlinSourcesScope: GlobalSearchScope = KotlinSourceFilterScope.projectSources(GlobalSearchScope.allScope(project), project) - val cleanupScope = AnalysisScope(kotlinSourcesScope, project) - - val cleanupToolProfile = runInInspectionProfileInitMode { RunInspectionIntention.createProfile(toolWrapper, managerEx, null) } - managerEx.createNewGlobalContext(false) - .codeCleanup( - cleanupScope, - cleanupToolProfile, - KotlinBundle.message("apply.in.the.project.0", toolWrapper.displayName), - null, - false - ) - } - - // Overcome failure during profile creating because of absent tools in tests - inline fun <T> runInInspectionProfileInitMode(runnable: () -> T): T { - return if (!ApplicationManager.getApplication().isUnitTestMode) { - runnable() - } else { - val old = InspectionProfileImpl.INIT_INSPECTIONS - try { - InspectionProfileImpl.INIT_INSPECTIONS = true - runnable() - } finally { - InspectionProfileImpl.INIT_INSPECTIONS = old - } - } - } - } } -/** - * There should be a single fix class with the same family name, this way it can be executed for all found coroutines problems from UI. - */ -private class ObsoleteCoroutineUsageFix(val delegate: CoroutineFix) : LocalQuickFix { +private class ObsoleteCoroutinesDelegateQuickFix(delegate: ObsoleteCodeFix) : ObsoleteCodeFixDelegateQuickFix(delegate) { override fun getFamilyName(): String = KotlinBundle.message("obsolete.coroutine.usage.fix.family.name") - - override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - delegate.applyFix(project, descriptor) - } - - companion object { - interface CoroutineFix { - fun applyFix(project: Project, descriptor: ProblemDescriptor) - } - } } private fun isTopLevelCallForReplace(simpleNameExpression: KtSimpleNameExpression, oldFqName: String, newFqName: String): Boolean { @@ -177,17 +82,17 @@ private fun isTopLevelCallForReplace(simpleNameExpression: KtSimpleNameExpressio return !isInIndex } -private fun fixesWithWholeProject(isOnTheFly: Boolean, fix: LocalQuickFix): Array<LocalQuickFix> { +internal fun fixesWithWholeProject(isOnTheFly: Boolean, fix: LocalQuickFix, wholeProjectFix: LocalQuickFix): Array<LocalQuickFix> { if (!isOnTheFly) { return arrayOf(fix) } - return arrayOf(fix, ObsoleteCoroutineUsageInWholeFix.INSTANCE) + return arrayOf(fix, wholeProjectFix) } -private class ObsoleteTopLevelFunctionUsage( +private class ObsoleteTopLevelFunctionUsageReporter( val textMarker: String, val oldFqName: String, val newFqName: String -) : CoroutineMigrationProblem { +) : ObsoleteCodeProblemReporter { override fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean { if (simpleNameExpression.text != textMarker) return false @@ -199,7 +104,7 @@ private class ObsoleteTopLevelFunctionUsage( simpleNameExpression, KotlinBundle.message("0.is.expected.to.be.used.since.kotlin.1.3", newFqName), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - *fixesWithWholeProject(isOnTheFly, ObsoleteCoroutineUsageFix(fix)) + *fixesWithWholeProject(isOnTheFly, ObsoleteCoroutinesDelegateQuickFix(fix), ObsoleteCoroutinesUsageInWholeProjectFix) ) return true @@ -208,22 +113,20 @@ private class ObsoleteTopLevelFunctionUsage( private val fix = RebindReferenceFix(newFqName) companion object { - private class RebindReferenceFix(val fqName: String) : ObsoleteCoroutineUsageFix.Companion.CoroutineFix { + private class RebindReferenceFix(val fqName: String) : ObsoleteCodeFix { override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val element = descriptor.psiElement if (element !is KtSimpleNameExpression) return - element.mainReference.bindToFqName(FqName(fqName), KtSimpleNameReference.ShorteningMode.DELAYED_SHORTENING) - - performDelayedRefactoringRequests(project) + element.mainReference.bindToFqName(FqName(fqName), KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING) } } } } -private class ObsoleteExtensionFunctionUsage( +private class ObsoleteExtensionFunctionUsageReporter( val textMarker: String, val oldFqName: String, val newFqName: String -) : CoroutineMigrationProblem { +) : ObsoleteCodeProblemReporter { override fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean { if (simpleNameExpression.text != textMarker) return false @@ -235,7 +138,7 @@ private class ObsoleteExtensionFunctionUsage( simpleNameExpression, KotlinBundle.message("methods.are.absent.in.coroutines.class.since.1.3"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - *fixesWithWholeProject(isOnTheFly, ObsoleteCoroutineUsageFix(fix)) + *fixesWithWholeProject(isOnTheFly, ObsoleteCoroutinesDelegateQuickFix(fix), ObsoleteCoroutinesUsageInWholeProjectFix) ) return true @@ -244,7 +147,7 @@ private class ObsoleteExtensionFunctionUsage( private val fix = ImportExtensionFunctionFix(newFqName) companion object { - private class ImportExtensionFunctionFix(val fqName: String) : ObsoleteCoroutineUsageFix.Companion.CoroutineFix { + private class ImportExtensionFunctionFix(val fqName: String) : ObsoleteCodeFix { override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val element = descriptor.psiElement if (element !is KtSimpleNameExpression) return @@ -256,91 +159,30 @@ private class ObsoleteExtensionFunctionUsage( .map { it.resolveToDescriptorIfAny() } .find { it != null && it.importableFqName?.asString() == fqName } ?: return - ImportInsertHelper.getInstance(element.project) - .importDescriptor(element.containingKtFile, importFun, forceAllUnderImport = false) + ImportInsertHelper.getInstance(element.project).importDescriptor( + element.containingKtFile, + importFun, + forceAllUnderImport = false + ) } } } } -private class ExperimentalImportUsage : CoroutineMigrationProblem { - override fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean { - if (simpleNameExpression.text != EXPERIMENTAL_COROUTINES_MARKER) return false - - val parent = simpleNameExpression.parent as? KtExpression ?: return false - val reportExpression = parent as? KtDotQualifiedExpression ?: simpleNameExpression - - findBinding(simpleNameExpression) ?: return false - - holder.registerProblem( - reportExpression, - KotlinBundle.message("experimental.coroutines.usages.are.obsolete.since.1.3"), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - *fixesWithWholeProject(isOnTheFly, ObsoleteCoroutineUsageFix(ObsoleteCoroutineImportFix)) - ) - - return true - } - - companion object { - private class Binding( - val bindTo: FqName, - val shouldRemove: Boolean, - val importDirective: KtImportDirective - ) - - @Suppress("SpellCheckingInspection") - private val PACKAGE_BINDING = mapOf( - "kotlinx.coroutines.experimental" to "kotlinx.coroutines", - "kotlin.coroutines.experimental" to "kotlin.coroutines" - ) - - private val IMPORTS_TO_REMOVE = setOf( - "kotlin.coroutines.experimental.buildSequence", - "kotlin.coroutines.experimental.buildIterator" - ) - - private const val EXPERIMENTAL_COROUTINES_MARKER = "experimental" - - private fun findBinding(simpleNameExpression: KtSimpleNameExpression): Binding? { - if (simpleNameExpression.text != EXPERIMENTAL_COROUTINES_MARKER) return null - - val importDirective = simpleNameExpression.parents - .takeWhile { it is KtDotQualifiedExpression || it is KtImportDirective } - .lastOrNull() as? KtImportDirective ?: return null - - val fqNameStr = importDirective.importedFqName?.asString() ?: return null - - val bindEntry = PACKAGE_BINDING.entries.find { (affectedImportPrefix, _) -> - fqNameStr.startsWith(affectedImportPrefix) - } ?: return null - - return Binding( - FqName(bindEntry.value), - fqNameStr in IMPORTS_TO_REMOVE, - importDirective - ) - } - - private object ObsoleteCoroutineImportFix : ObsoleteCoroutineUsageFix.Companion.CoroutineFix { - override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - val element = descriptor.psiElement - val simpleNameExpression = when (element) { - is KtSimpleNameExpression -> element - is KtDotQualifiedExpression -> element.selectorExpression as? KtSimpleNameExpression - else -> null - } ?: return - - val binding = findBinding(simpleNameExpression) ?: return - - if (binding.shouldRemove) { - binding.importDirective.delete() - } else { - simpleNameExpression.mainReference.bindToFqName( - binding.bindTo, shorteningMode = KtSimpleNameReference.ShorteningMode.NO_SHORTENING - ) - } - } - } - } +private object ObsoleteCoroutinesImportsUsageReporter : ObsoleteImportsUsageReporter() { + override val textMarker: String = "experimental" + + override val packageBindings: Map<String, String> = mapOf( + "kotlinx.coroutines.experimental" to "kotlinx.coroutines", + "kotlin.coroutines.experimental" to "kotlin.coroutines" + ) + override val importsToRemove: Set<String> = setOf( + "kotlin.coroutines.experimental.buildSequence", + "kotlin.coroutines.experimental.buildIterator" + ) + + override val wholeProjectFix: LocalQuickFix = ObsoleteCoroutinesUsageInWholeProjectFix + override fun problemMessage(): String = KotlinBundle.message("experimental.coroutines.usages.are.obsolete.since.1.3") + override fun wrapFix(fix: ObsoleteCodeFix): LocalQuickFix = ObsoleteCoroutinesDelegateQuickFix(fix) } + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteKotlinJsPackagesInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteKotlinJsPackagesInspection.kt new file mode 100644 index 00000000000..177f9db6052 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/ObsoleteKotlinJsPackagesInspection.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.inspections.migration + +import com.intellij.codeInspection.* +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.backend.common.serialization.findPackage +import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.KtSimpleNameExpression + +internal class ObsoleteKotlinJsPackagesInspection : ObsoleteCodeMigrationInspection() { + override val fromVersion: LanguageVersion = LanguageVersion.KOTLIN_1_3 + override val toVersion: LanguageVersion = LanguageVersion.KOTLIN_1_4 + + override val problemReporters: List<ObsoleteCodeProblemReporter> = listOf( + KotlinBrowserFullyQualifiedUsageReporter, + KotlinBrowserImportUsageReporter, + KotlinDomImportUsageReporter + ) +} + +private object ObsoleteKotlinJsPackagesUsagesInWholeProjectFix : ObsoleteCodeInWholeProjectFix() { + override val inspectionName: String = ObsoleteKotlinJsPackagesInspection().shortName + override fun getFamilyName(): String = KotlinBundle.message("obsolete.kotlin.js.packages.usage.in.whole.fix.family.name") +} + +private const val KOTLIN_BROWSER_PACKAGE = "kotlin.browser" +private const val KOTLINX_BROWSER_PACKAGE = "kotlinx.browser" +private const val KOTLIN_DOM_PACKAGE = "kotlin.dom" + +private class ObsoleteKotlinBrowserUsageFix(delegate: ObsoleteCodeFix) : ObsoleteCodeFixDelegateQuickFix(delegate) { + override fun getFamilyName(): String = KotlinBundle.message("obsolete.package.usage.fix.family.name", KOTLIN_BROWSER_PACKAGE) +} + +private class ObsoleteKotlinDomUsageFix(delegate: ObsoleteCodeFix) : ObsoleteCodeFixDelegateQuickFix(delegate) { + override fun getFamilyName(): String = KotlinBundle.message("obsolete.package.usage.fix.family.name", KOTLIN_DOM_PACKAGE) +} + +/** + * We have such inspection only for 'kotlin.browser' package; it is because 'kotlin.dom' package has only extension functions. Such + * functions cannot be used with fully qualified name. + */ +private object KotlinBrowserFullyQualifiedUsageReporter : ObsoleteCodeProblemReporter { + override fun report(holder: ProblemsHolder, isOnTheFly: Boolean, simpleNameExpression: KtSimpleNameExpression): Boolean { + val fullyQualifiedExpression = simpleNameExpression.parent as? KtDotQualifiedExpression ?: return false + + val kotlinBrowserQualifier = fullyQualifiedExpression.receiverExpression as? KtDotQualifiedExpression ?: return false + if (kotlinBrowserQualifier.text != KOTLIN_BROWSER_PACKAGE) return false + + if (!resolvesToKotlinBrowserPackage(simpleNameExpression)) return false + + holder.registerProblem( + kotlinBrowserQualifier, + KotlinBundle.message("package.usages.are.obsolete.since.1.4", KOTLIN_DOM_PACKAGE), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + *fixesWithWholeProject( + isOnTheFly, + fix = ObsoleteKotlinBrowserUsageFix(KotlinBrowserFullyQualifiedUsageFix), + wholeProjectFix = ObsoleteKotlinJsPackagesUsagesInWholeProjectFix + ) + ) + + return true + } + + private fun resolvesToKotlinBrowserPackage(simpleNameExpression: KtSimpleNameExpression): Boolean { + val referencedDescriptor = + simpleNameExpression.resolveMainReferenceToDescriptors().singleOrNull() as? CallableDescriptor ?: return false + + return referencedDescriptor.findPackage().fqName.asString() == KOTLIN_BROWSER_PACKAGE + } + + object KotlinBrowserFullyQualifiedUsageFix : ObsoleteCodeFix { + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val oldQualifier = descriptor.psiElement as? KtDotQualifiedExpression ?: return + + val newQualifier = KtPsiFactory(oldQualifier).createExpression(KOTLINX_BROWSER_PACKAGE) + oldQualifier.replace(newQualifier) + } + } +} + +private object KotlinBrowserImportUsageReporter : ObsoleteImportsUsageReporter() { + override val textMarker: String = "browser" + override val packageBindings: Map<String, String> = mapOf(KOTLIN_BROWSER_PACKAGE to KOTLINX_BROWSER_PACKAGE) + + override val wholeProjectFix: LocalQuickFix = ObsoleteKotlinJsPackagesUsagesInWholeProjectFix + override fun problemMessage(): String = KotlinBundle.message("package.usages.are.obsolete.since.1.4", KOTLIN_BROWSER_PACKAGE) + + override fun wrapFix(fix: ObsoleteCodeFix): LocalQuickFix = ObsoleteKotlinBrowserUsageFix(fix) +} + +private object KotlinDomImportUsageReporter : ObsoleteImportsUsageReporter() { + override val textMarker: String = "dom" + override val packageBindings: Map<String, String> = mapOf(KOTLIN_DOM_PACKAGE to "kotlinx.dom") + + override val wholeProjectFix: LocalQuickFix = ObsoleteKotlinJsPackagesUsagesInWholeProjectFix + override fun problemMessage(): String = KotlinBundle.message("package.usages.are.obsolete.since.1.4", KOTLIN_DOM_PACKAGE) + + override fun wrapFix(fix: ObsoleteCodeFix): LocalQuickFix = ObsoleteKotlinDomUsageFix(fix) +} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/KotlinAddOrderEntryActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/KotlinAddOrderEntryActionFactory.kt index 3ad1ef87d36..79671cedd25 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/KotlinAddOrderEntryActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/KotlinAddOrderEntryActionFactory.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset object KotlinAddOrderEntryActionFactory : KotlinIntentionActionsFactory() { override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> { val simpleExpression = diagnostic.psiElement as? KtSimpleNameExpression ?: return emptyList() - if (ProjectRootsUtil.isInProjectSource(simpleExpression, includeScriptsOutsideSourceRoots = false)) return emptyList() + if (!ProjectRootsUtil.isInProjectSource(simpleExpression, includeScriptsOutsideSourceRoots = false)) return emptyList() val refElement = simpleExpression.getQualifiedElement() diff --git a/idea/testData/quickfix/allowResolveInWriteAction.txt b/idea/testData/quickfix/allowResolveInWriteAction.txt index b45ac13dc33..84b22caac0f 100644 --- a/idea/testData/quickfix/allowResolveInWriteAction.txt +++ b/idea/testData/quickfix/allowResolveInWriteAction.txt @@ -6,7 +6,7 @@ org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection$DeleteRedundantExtensionAction org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection$HighPriorityIntentionBasedQuickFix org.jetbrains.kotlin.idea.inspections.KotlinUnusedImportInspection$OptimizeImportsQuickFix -org.jetbrains.kotlin.idea.inspections.migration.ObsoleteCoroutineUsageFix +org.jetbrains.kotlin.idea.inspections.migration.ObsoleteCoroutinesDelegateQuickFix org.jetbrains.kotlin.idea.inspections.SafeDeleteFix org.jetbrains.kotlin.idea.inspections.SuspiciousCollectionReassignmentInspection$ChangeTypeToMutableFix org.jetbrains.kotlin.idea.inspections.SuspiciousCollectionReassignmentInspection$JoinWithInitializerFix diff --git a/idea/testData/quickfix/libraries/junit.kt b/idea/testData/quickfix/libraries/junit.kt index 32da6a0a1ae..f759362c5af 100644 --- a/idea/testData/quickfix/libraries/junit.kt +++ b/idea/testData/quickfix/libraries/junit.kt @@ -1,8 +1,11 @@ // "Add 'JUnit4' to classpath" "true" // ERROR: Unresolved reference: Before // ERROR: Unresolved reference: junit -// UNCONFIGURE_LIBRARY: JUnit4 // WITH_RUNTIME + +// Do not apply quickfix as platform can't handle open maven download dialog in unit test mode +// APPLY_QUICKFIX: false + package some import org.<caret>junit.Before diff --git a/idea/testData/quickfix/libraries/junit.kt.after b/idea/testData/quickfix/libraries/junit.kt.after index 08f9ce656e7..07efd055357 100644 --- a/idea/testData/quickfix/libraries/junit.kt.after +++ b/idea/testData/quickfix/libraries/junit.kt.after @@ -1,8 +1,11 @@ // "Add 'JUnit4' to classpath" "true" // ERROR: Unresolved reference: Before // ERROR: Unresolved reference: junit -// UNCONFIGURE_LIBRARY: JUnit4 // WITH_RUNTIME + +// Do not apply quickfix as platform can't handle open maven download dialog in unit test mode +// APPLY_QUICKFIX: false + package some import org.junit.Before diff --git a/idea/testData/quickfix/libraries/testNG.kt b/idea/testData/quickfix/libraries/testNG.kt index aadc6dde890..9147b4186cf 100644 --- a/idea/testData/quickfix/libraries/testNG.kt +++ b/idea/testData/quickfix/libraries/testNG.kt @@ -1,8 +1,10 @@ // "Add 'testng' to classpath" "true" // ERROR: Unresolved reference: BeforeMethod -// ERROR: Unresolved reference: testng -// UNCONFIGURE_LIBRARY: testng // WITH_RUNTIME + +// Do not apply quickfix as platform can't handle open maven download dialog in unit test mode +// APPLY_QUICKFIX: false + package some abstract class KBase { diff --git a/idea/testData/quickfix/libraries/testNG.kt.after b/idea/testData/quickfix/libraries/testNG.kt.after index d6ae595a8b4..0ca0d92350d 100644 --- a/idea/testData/quickfix/libraries/testNG.kt.after +++ b/idea/testData/quickfix/libraries/testNG.kt.after @@ -1,11 +1,11 @@ // "Add 'testng' to classpath" "true" // ERROR: Unresolved reference: BeforeMethod -// ERROR: Unresolved reference: testng -// UNCONFIGURE_LIBRARY: testng // WITH_RUNTIME -package some -import org.testng.annotations.BeforeMethod +// Do not apply quickfix as platform can't handle open maven download dialog in unit test mode +// APPLY_QUICKFIX: false + +package some abstract class KBase { @BeforeMethod diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/.inspection b/idea/testData/quickfix/obsoleteKotlinJsPackages/.inspection new file mode 100644 index 00000000000..46e5ecbbaf1 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.migration.ObsoleteKotlinJsPackagesInspection
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt new file mode 100644 index 00000000000..a79c822736b --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt @@ -0,0 +1,10 @@ +// "Fix 'kotlin.browser' package usage" "true" +// JS + +package test + +fun use(a: Any) {} + +fun usage() { + use(kotlin.<caret>browser.localStorage.toString()) +} diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt.after b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt.after new file mode 100644 index 00000000000..1d43e869337 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt.after @@ -0,0 +1,10 @@ +// "Fix 'kotlin.browser' package usage" "true" +// JS + +package test + +fun use(a: Any) {} + +fun usage() { + use(kotlinx.browser.localStorage.toString()) +} diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt new file mode 100644 index 00000000000..29c044018d3 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt @@ -0,0 +1,7 @@ +// "Fix 'kotlin.browser' package usage" "true" +// JS + +package test + +import kotlin.<caret>browser.localStorage +import kotlin.dom.addClass
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt.after b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt.after new file mode 100644 index 00000000000..39788ab1df4 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt.after @@ -0,0 +1,7 @@ +// "Fix 'kotlin.browser' package usage" "true" +// JS + +package test + +import kotlinx.browser.localStorage +import kotlin.dom.addClass
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt new file mode 100644 index 00000000000..0925108565e --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt @@ -0,0 +1,7 @@ +// "Fix 'kotlin.browser' package usage" "true" +// JS + +package test + +import kotlin.<caret>browser.* +import kotlin.dom.* diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt.after b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt.after new file mode 100644 index 00000000000..be16f7a41ba --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt.after @@ -0,0 +1,7 @@ +// "Fix 'kotlin.browser' package usage" "true" +// JS + +package test + +import kotlinx.browser.* +import kotlin.dom.* diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt new file mode 100644 index 00000000000..81918b6e5f1 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt @@ -0,0 +1,11 @@ +// "Fix 'kotlin.dom' and 'kotlin.browser' packages usages in the project" "true" +// JS + +package test + +import kotlin.<caret>browser.localStorage +import kotlin.dom.addClass + +fun usage() { + kotlin.browser.document.toString() +}
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt.after b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt.after new file mode 100644 index 00000000000..d72b1376956 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt.after @@ -0,0 +1,11 @@ +// "Fix 'kotlin.dom' and 'kotlin.browser' packages usages in the project" "true" +// JS + +package test + +import kotlinx.browser.localStorage +import kotlinx.dom.addClass + +fun usage() { + kotlinx.browser.document.toString() +}
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt new file mode 100644 index 00000000000..48bc1a22ff6 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt @@ -0,0 +1,7 @@ +// "Fix 'kotlin.dom' package usage" "true" +// JS + +package test + +import kotlin.browser.localStorage +import kotlin.<caret>dom.addClass
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt.after b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt.after new file mode 100644 index 00000000000..03ae880f49b --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt.after @@ -0,0 +1,7 @@ +// "Fix 'kotlin.dom' package usage" "true" +// JS + +package test + +import kotlin.browser.localStorage +import kotlinx.dom.addClass
\ No newline at end of file diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt new file mode 100644 index 00000000000..272dd8dfbc5 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt @@ -0,0 +1,7 @@ +// "Fix 'kotlin.dom' package usage" "true" +// JS + +package test + +import kotlin.browser.* +import kotlin.<caret>dom.* diff --git a/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt.after b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt.after new file mode 100644 index 00000000000..d3f95448d41 --- /dev/null +++ b/idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt.after @@ -0,0 +1,7 @@ +// "Fix 'kotlin.dom' package usage" "true" +// JS + +package test + +import kotlin.browser.* +import kotlinx.dom.* diff --git a/idea/tests/org/jetbrains/kotlin/idea/AbstractResolveElementCacheTest.kt b/idea/tests/org/jetbrains/kotlin/idea/AbstractResolveElementCacheTest.kt index 88ee80c2589..935562184cd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/AbstractResolveElementCacheTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/AbstractResolveElementCacheTest.kt @@ -5,8 +5,12 @@ package org.jetbrains.kotlin.idea +import com.intellij.util.ThrowableRunnable +import org.intellij.lang.annotations.Language +import org.jetbrains.kotlin.idea.project.ResolveElementCache import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.runAll import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.psi.* @@ -43,6 +47,16 @@ class C(param1: String = "", param2: Int = 0) { val factory: KtPsiFactory ) + override fun tearDown() { + runAll( + ThrowableRunnable { ResolveElementCache.forceFullAnalysisModeInTests = false }, + ThrowableRunnable { super.tearDown() }, + ) + } + + protected fun configureWithKotlin(@Language("kotlin") text: String): KtFile = + myFixture.configureByText("Test.kt", text.trimIndent()) as KtFile + protected fun doTest(handler: Data.() -> Unit) { val file = myFixture.configureByText("Test.kt", FILE_TEXT) as KtFile val data = extractData(file) diff --git a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt index d79edb7214a..d76a6ecaf43 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea import com.intellij.psi.PsiDocumentManager import junit.framework.TestCase -import org.intellij.lang.annotations.Language import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks @@ -15,6 +14,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.project.ResolveElementCache import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* @@ -291,12 +291,12 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } fun testIncompleteFileAnnotationList() { - val file = myFixture.configureByText( - "Test.kt", """ + val file = configureWithKotlin( + """ @file import some.hello """ - ) as KtFile + ) val fileAnnotationList = file.fileAnnotationList!! fileAnnotationList.analyze(BodyResolveMode.PARTIAL) @@ -336,16 +336,12 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { assertEmpty(context.diagnostics.all()) } - private fun configureWithKotlin(@Language("kotlin") text: String): KtFile { - return myFixture.configureByText("Test.kt", text.trimIndent()) as KtFile - } - fun testPrimaryConstructorParameterFullAnalysis() { - myFixture.configureByText( - "Test.kt", """ + configureWithKotlin( + """ class My(param: Int = <caret>0) """ - ) as KtFile + ) val defaultValue = myFixture.elementByOffset.getParentOfType<KtExpression>(true)!! // Kept to preserve correct behaviour of analyzeFully() on class internal elements @@ -355,11 +351,11 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } fun testPrimaryConstructorAnnotationFullAnalysis() { - myFixture.configureByText( - "Test.kt", """ + configureWithKotlin( + """ class My @Deprecated("<caret>xyz") protected constructor(param: Int) """ - ) as KtFile + ) val annotationArguments = myFixture.elementByOffset.getParentOfType<KtValueArgumentList>(true)!! @@ -368,14 +364,14 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } fun testFunctionParameterAnnotation() { - val file = myFixture.configureByText( - "Test.kt", """ + val file = configureWithKotlin( + """ annotation class Ann fun foo(@<caret>Ann p: Int) { bar() } """ - ) as KtFile + ) val function = (file.declarations[1]) as KtFunction val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!! @@ -391,12 +387,12 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } fun testPrimaryConstructorParameterAnnotation() { - myFixture.configureByText( - "Test.kt", """ + configureWithKotlin( + """ annotation class Ann class X(@set:<caret>Ann var p: Int) """ - ) as KtFile + ) val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!! @@ -408,8 +404,8 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } fun testSecondaryConstructorParameterAnnotation() { - val file = myFixture.configureByText( - "Test.kt", """ + val file = configureWithKotlin( + """ annotation class Ann class X { constructor(@<caret>Ann p: Int) { @@ -417,7 +413,7 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } } """ - ) as KtFile + ) val constructor = ((file.declarations[1]) as KtClass).secondaryConstructors[0] val typeRef = myFixture.elementByOffset.getParentOfType<KtTypeReference>(true)!! @@ -475,16 +471,28 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { } } + fun testPartialResolveIsAFullResolveForOpenedFile() { + ResolveElementCache.forceFullAnalysisModeInTests = true + doTest { + val function = members[0] as KtFunction + val bindingContextPartial = function.analyze(BodyResolveMode.PARTIAL) + val bindingContextFull = function.analyze(BodyResolveMode.FULL) + assert(bindingContextPartial === bindingContextFull) { + "Partial resolve is forced to FULL resolve for a file currently opened in editor" + } + } + } + fun testKT14376() { - val file = myFixture.configureByText("Test.kt", "object Obj(val x: Int)") as KtFile + val file = configureWithKotlin("object Obj(val x: Int)") val nameRef = file.findDescendantOfType<KtNameReferenceExpression>()!! val bindingContext = nameRef.analyze(BodyResolveMode.PARTIAL) assert(bindingContext[BindingContext.REFERENCE_TARGET, nameRef]?.fqNameSafe?.asString() == "kotlin.Int") } fun testResolveDefaultValueInPrimaryConstructor() { - myFixture.configureByText( - "Test.kt", """ + configureWithKotlin( + """ class ClassA<N> ( messenger: ClassB<N> = object : ClassB<N> { override fun methodOne<caret>(param: List<N>) { @@ -496,7 +504,7 @@ class ResolveElementCacheTest : AbstractResolveElementCacheTest() { fun methodOne(param: List<N>) } """ - ) as KtFile + ) val methodOne = myFixture.elementByOffset.getParentOfType<KtFunction>(true)!! diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.kt b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.kt index 5f8662d3d05..14423da9852 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.kt @@ -33,6 +33,13 @@ import java.io.IOException abstract class AbstractQuickFixTest : KotlinLightCodeInsightFixtureTestCase(), QuickFixTest { companion object { + const val APPLY_QUICKFIX_DIRECTIVE = "APPLY_QUICKFIX" + const val ACTION_DIRECTIVE = "ACTION" + const val SHOULD_BE_AVAILABLE_AFTER_EXECUTION_DIRECTIVE = "SHOULD_BE_AVAILABLE_AFTER_EXECUTION" + const val FIXTURE_CLASS_DIRECTIVE = "FIXTURE_CLASS" + const val SHOULD_FAIL_WITH_DIRECTIVE = "SHOULD_FAIL_WITH" + const val FORCE_PACKAGE_FOLDER_DIRECTIVE = "FORCE_PACKAGE_FOLDER" + private val quickFixesAllowedToResolveInWriteAction = AllowedToResolveUnderWriteActionData( "idea/testData/quickfix/allowResolveInWriteAction.txt", """ @@ -77,7 +84,7 @@ abstract class AbstractQuickFixTest : KotlinLightCodeInsightFixtureTestCase(), Q private fun shouldBeAvailableAfterExecution(): Boolean = InTextDirectivesUtils.isDirectiveDefined( myFixture.file.text, - "// SHOULD_BE_AVAILABLE_AFTER_EXECUTION" + "// $SHOULD_BE_AVAILABLE_AFTER_EXECUTION_DIRECTIVE" ) protected open fun configExtra(options: String) { @@ -101,15 +108,15 @@ abstract class AbstractQuickFixTest : KotlinLightCodeInsightFixtureTestCase(), Q fileText = FileUtil.loadFile(testFile, CharsetToolkit.UTF8_CHARSET) TestCase.assertTrue("\"<caret>\" is missing in file \"${testFile.path}\"", fileText.contains("<caret>")) - fixtureClasses = InTextDirectivesUtils.findListWithPrefixes(fileText, "// FIXTURE_CLASS: ") + fixtureClasses = InTextDirectivesUtils.findListWithPrefixes(fileText, "// $FIXTURE_CLASS_DIRECTIVE: ") for (fixtureClass in fixtureClasses) { TestFixtureExtension.loadFixture(fixtureClass, module) } - expectedErrorMessage = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// SHOULD_FAIL_WITH: ") + expectedErrorMessage = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// $SHOULD_FAIL_WITH_DIRECTIVE: ") val contents = StringUtil.convertLineSeparators(fileText) var fileName = testFile.canonicalFile.name - val putIntoPackageFolder = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// FORCE_PACKAGE_FOLDER") != null + val putIntoPackageFolder = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// $FORCE_PACKAGE_FOLDER_DIRECTIVE") != null if (putIntoPackageFolder) { fileName = getPathAccordingToPackage(fileName, contents) myFixture.addFileToProject(fileName, contents) @@ -171,30 +178,36 @@ abstract class AbstractQuickFixTest : KotlinLightCodeInsightFixtureTestCase(), Q } } - val stubComparisonFailure: ComparisonFailure? = try { - forceCheckForResolveInDispatchThreadInTests(writeActionResolveHandler) { - myFixture.launchAction(intention) + val applyQuickFix = (InTextDirectivesUtils.findStringWithPrefixes(myFixture.file.text, "// $APPLY_QUICKFIX_DIRECTIVE: ") + ?: "true").toBoolean() + val stubComparisonFailure: ComparisonFailure? + if (applyQuickFix) { + stubComparisonFailure = try { + forceCheckForResolveInDispatchThreadInTests(writeActionResolveHandler) { + myFixture.launchAction(intention) + } + null + } + catch (comparisonFailure: ComparisonFailure) { + comparisonFailure } - null - } catch (comparisonFailure: ComparisonFailure) { - comparisonFailure - } - UIUtil.dispatchAllInvocationEvents() - UIUtil.dispatchAllInvocationEvents() + UIUtil.dispatchAllInvocationEvents() + UIUtil.dispatchAllInvocationEvents() - if (!shouldBeAvailableAfterExecution()) { - assertNull( - "Action '${actionHint.expectedText}' is still available after its invocation in test " + fileName, - findActionWithText(actionHint.expectedText) - ) + if (!shouldBeAvailableAfterExecution()) { + assertNull( + "Action '${actionHint.expectedText}' is still available after its invocation in test " + fileName, + findActionWithText(actionHint.expectedText) + ) + } + } else { + stubComparisonFailure = null } myFixture.checkResultByFile(File(fileName).name + ".after") - if (stubComparisonFailure != null) { - throw stubComparisonFailure - } + stubComparisonFailure?.let { throw it } } else { assertNull("Action with text ${actionHint.expectedText} is present, but should not", intention) } @@ -213,7 +226,7 @@ abstract class AbstractQuickFixTest : KotlinLightCodeInsightFixtureTestCase(), Q val aClass = Class.forName(className) assert(IntentionAction::class.java.isAssignableFrom(aClass)) { "$className should be inheritor of IntentionAction" } - val validActions = HashSet(InTextDirectivesUtils.findLinesWithPrefixesRemoved(text, "// ACTION:")) + val validActions = setOf(InTextDirectivesUtils.findLinesWithPrefixesRemoved(text, "// $ACTION_DIRECTIVE:")) actions.removeAll { action -> !aClass.isAssignableFrom(action.javaClass) || validActions.contains(action.text) } diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 091eb3ddf94..255b02040d3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -3518,6 +3518,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/obsoleteKotlinJsPackages") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ObsoleteKotlinJsPackages extends AbstractQuickFixMultiFileTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath); + } + + public void testAllFilesPresentInObsoleteKotlinJsPackages() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/obsoleteKotlinJsPackages"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), null, true); + } + } + @TestMetadata("idea/testData/quickfix/optimizeImports") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index d8b10c6eaa9..08932762f3b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -9873,6 +9873,49 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/obsoleteKotlinJsPackages") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ObsoleteKotlinJsPackages extends AbstractQuickFixTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInObsoleteKotlinJsPackages() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/obsoleteKotlinJsPackages"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true); + } + + @TestMetadata("kotlinBrowserFullyQualifiedProperty.kt") + public void testKotlinBrowserFullyQualifiedProperty() throws Exception { + runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserFullyQualifiedProperty.kt"); + } + + @TestMetadata("kotlinBrowserPropertyImport.kt") + public void testKotlinBrowserPropertyImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserPropertyImport.kt"); + } + + @TestMetadata("kotlinBrowserStarImport.kt") + public void testKotlinBrowserStarImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinBrowserStarImport.kt"); + } + + @TestMetadata("kotlinDomAndBrowserImport.kt") + public void testKotlinDomAndBrowserImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomAndBrowserImport.kt"); + } + + @TestMetadata("kotlinDomPropertyImport.kt") + public void testKotlinDomPropertyImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomPropertyImport.kt"); + } + + @TestMetadata("kotlinDomStarImport.kt") + public void testKotlinDomStarImport() throws Exception { + runTest("idea/testData/quickfix/obsoleteKotlinJsPackages/kotlinDomStarImport.kt"); + } + } + @TestMetadata("idea/testData/quickfix/optimizeImports") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt index b1be72cb9d3..0aec0c1693c 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:JvmName("MetadataProperties") @@ -129,6 +118,8 @@ var JsExpression.primitiveKClass: JsExpression? by MetadataProperty(default = nu var JsExpression.kType: JsExpression? by MetadataProperty(default = null) +var JsExpression.kTypeWithRecursion: Boolean by MetadataProperty(default = false) + data class CoroutineMetadata( val doResumeName: JsName, val stateName: JsName, diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index 050122ad9be..f7097f5a3c3 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.js.resolve @@ -23,7 +12,6 @@ import org.jetbrains.kotlin.js.analyze.JsNativeDiagnosticSuppressor import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.js.resolve.diagnostics.* import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase -import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport import org.jetbrains.kotlin.types.DynamicTypesAllowed @@ -43,7 +31,6 @@ object JsPlatformConfigurator : PlatformConfiguratorBase( JsModuleCallChecker, JsDynamicCallChecker, JsDefinedExternallyCallChecker, - TypeOfChecker, ), identifierChecker = JsIdentifierChecker ) { diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt index f8a28b05362..d7dfc75ae3d 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt @@ -1,24 +1,27 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.js.inline.clean import org.jetbrains.kotlin.js.backend.ast.* -import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction -import org.jetbrains.kotlin.js.backend.ast.metadata.kType -import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction -import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef +import org.jetbrains.kotlin.js.backend.ast.metadata.* // Replaces getReifiedTypeParameterKType(<Class Constructor>) with its KType fun substituteKTypes(root: JsNode) { val visitor = object : JsVisitorWithContextImpl() { override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) { + // for invocations from non-inline contexts + invocation.checkDoesNotCreateRecursiveKType() + val qualifier = invocation.qualifier as? JsNameRef ?: return if (qualifier.name?.specialFunction != SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE) return + val firstArg = invocation.arguments.first() getTransitiveKType(firstArg)?.let { + // for invocations from inline contexts + it.checkNoInvocationsWithRecursiveKType() ctx.replaceMe(it) } } @@ -30,7 +33,7 @@ fun substituteKTypes(root: JsNode) { // kType metadata is set on jsClass expressions. // There can be a chain of local variables from jsClass to its usage. // This methods uses staticRef to find the original expression with kType metadata. -fun getTransitiveKType(e: JsExpression): JsExpression? { +private fun getTransitiveKType(e: JsExpression): JsExpression? { return when { e.kType != null -> e.kType @@ -43,3 +46,17 @@ fun getTransitiveKType(e: JsExpression): JsExpression? { else -> null } } + +private fun JsExpression.checkNoInvocationsWithRecursiveKType() { + val visitor = object : JsVisitorWithContextImpl() { + override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) { + invocation.checkDoesNotCreateRecursiveKType() + } + } + visitor.accept(this) +} + +private fun JsInvocation.checkDoesNotCreateRecursiveKType() { + // See KT-40173 + if (kTypeWithRecursion) TODO("Non-reified type parameters with recursive bounds are not supported yet") +} diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index 63a4f25daeb..9070a27c6e1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -1173,6 +1173,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/delegation/delegationExtensionPropertyDelegated.kt"); } + @TestMetadata("delegationToExternaInterface.kt") + public void testDelegationToExternaInterface() throws Exception { + runTest("js/js.translator/testData/box/delegation/delegationToExternaInterface.kt"); + } + @TestMetadata("jsNamePropertyDelegation.kt") public void testJsNamePropertyDelegation() throws Exception { runTest("js/js.translator/testData/box/delegation/jsNamePropertyDelegation.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 3dc278ecb83..5dc406443fc 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -1077,6 +1077,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/bridges/genericProperty.kt"); } + @TestMetadata("jsName.kt") + public void testJsName() throws Exception { + runTest("compiler/testData/codegen/box/bridges/jsName.kt"); + } + + @TestMetadata("jsNative.kt") + public void testJsNative() throws Exception { + runTest("compiler/testData/codegen/box/bridges/jsNative.kt"); + } + @TestMetadata("kt12416.kt") public void testKt12416() throws Exception { runTest("compiler/testData/codegen/box/bridges/kt12416.kt"); @@ -1322,6 +1332,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") @@ -15685,6 +15705,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/primitiveTypes/conversions.kt"); } + @TestMetadata("crossTypeEquals.kt") + public void testCrossTypeEquals() throws Exception { + runTest("compiler/testData/codegen/box/primitiveTypes/crossTypeEquals.kt"); + } + @TestMetadata("ea35963.kt") public void testEa35963() throws Exception { runTest("compiler/testData/codegen/box/primitiveTypes/ea35963.kt"); @@ -22243,6 +22268,46 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testAllFilesPresentInJs() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf/js"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } + + @TestMetadata("classes.kt") + public void testClasses() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/classes.kt"); + } + + @TestMetadata("inlineClasses.kt") + public void testInlineClasses() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/inlineClasses.kt"); + } + + @TestMetadata("kType.kt") + public void testKType() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/kType.kt"); + } + + @TestMetadata("manyTypeArguments.kt") + public void testManyTypeArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/manyTypeArguments.kt"); + } + + @TestMetadata("multipleLayers.kt") + public void testMultipleLayers() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/multipleLayers.kt"); + } + + @TestMetadata("multipleModules.kt") + public void testMultipleModules() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt"); + } + + @TestMetadata("typeOfCapturedStar.kt") + public void testTypeOfCapturedStar() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/typeOfCapturedStar.kt"); + } + + @TestMetadata("typeOfReifiedUnit.kt") + public void testTypeOfReifiedUnit() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/js/typeOfReifiedUnit.kt"); + } } @TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect") @@ -22303,6 +22368,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt"); } + @TestMetadata("recursiveBoundWithInline.kt") + public void testRecursiveBoundWithInline() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt"); + } + + @TestMetadata("recursiveBoundWithoutInline.kt") + public void testRecursiveBoundWithoutInline() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt"); + } + @TestMetadata("simpleClassParameter.kt") public void testSimpleClassParameter() throws Exception { runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 047e9eaf67f..2d527b2a950 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -1173,6 +1173,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/delegation/delegationExtensionPropertyDelegated.kt"); } + @TestMetadata("delegationToExternaInterface.kt") + public void testDelegationToExternaInterface() throws Exception { + runTest("js/js.translator/testData/box/delegation/delegationToExternaInterface.kt"); + } + @TestMetadata("jsNamePropertyDelegation.kt") public void testJsNamePropertyDelegation() throws Exception { runTest("js/js.translator/testData/box/delegation/jsNamePropertyDelegation.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index f09e1128174..1076cde05ce 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -1332,6 +1332,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") @@ -22358,6 +22368,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt"); } + @TestMetadata("recursiveBoundWithInline.kt") + public void testRecursiveBoundWithInline() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt"); + } + + @TestMetadata("recursiveBoundWithoutInline.kt") + public void testRecursiveBoundWithoutInline() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt"); + } + @TestMetadata("simpleClassParameter.kt") public void testSimpleClassParameter() throws Exception { runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 12f017e1dbe..728974efebe 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1173,6 +1173,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/delegation/delegationExtensionPropertyDelegated.kt"); } + @TestMetadata("delegationToExternaInterface.kt") + public void testDelegationToExternaInterface() throws Exception { + runTest("js/js.translator/testData/box/delegation/delegationToExternaInterface.kt"); + } + @TestMetadata("jsNamePropertyDelegation.kt") public void testJsNamePropertyDelegation() throws Exception { runTest("js/js.translator/testData/box/delegation/jsNamePropertyDelegation.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index e14bdcbb6fb..5c95e5b4649 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -1332,6 +1332,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testLackOfNullCheckOnNullableInsideBuild() throws Exception { runTest("compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + + @TestMetadata("substituteStubTypeIntoCR.kt") + public void testSubstituteStubTypeIntoCR() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt"); + } + + @TestMetadata("substituteStubTypeIntolambdaParameterDescriptor.kt") + public void testSubstituteStubTypeIntolambdaParameterDescriptor() throws Exception { + runTest("compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/builtinStubMethods") @@ -22373,6 +22383,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt"); } + @TestMetadata("recursiveBoundWithInline.kt") + public void testRecursiveBoundWithInline() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt"); + } + + @TestMetadata("recursiveBoundWithoutInline.kt") + public void testRecursiveBoundWithoutInline() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt"); + } + @TestMetadata("simpleClassParameter.kt") public void testSimpleClassParameter() throws Exception { runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt index 578ab341033..803a5597fd2 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction +import org.jetbrains.kotlin.js.backend.ast.metadata.kTypeWithRecursion import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo import org.jetbrains.kotlin.js.translate.context.Namer @@ -146,7 +147,11 @@ private class KTypeConstructor(private val context: TranslationContext) { ) } - if (typeParameter in visitedTypeParams) return callHelperFunction(Namer.GET_START_KTYPE_PROJECTION) + if (typeParameter in visitedTypeParams) { + return callHelperFunction(Namer.GET_START_KTYPE_PROJECTION).also { + it.kTypeWithRecursion = true + } + } visitedTypeParams.add(typeParameter) diff --git a/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt b/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt new file mode 100644 index 00000000000..05909b67207 --- /dev/null +++ b/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt @@ -0,0 +1,15 @@ +// EXPECTED_REACHABLE_NODES: 1236 +// KJS_WITH_FULL_RUNTIME +// KT-40126 +@file:Suppress("EXTERNAL_DELEGATION") + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +external interface MySymbol { + companion object : MySymbolConstructor by definedExternally +} +external interface MySymbolConstructor { + @nativeInvoke + operator fun invoke(description: String = definedExternally): Any +} + +fun box() = "OK"
\ No newline at end of file diff --git a/js/js.translator/testData/lineNumbers/coroutine.kt b/js/js.translator/testData/lineNumbers/coroutine.kt index 41b8a593698..c4562c1c16d 100644 --- a/js/js.translator/testData/lineNumbers/coroutine.kt +++ b/js/js.translator/testData/lineNumbers/coroutine.kt @@ -14,4 +14,4 @@ suspend fun bar(): Unit { println(a + b) } -// LINES: 38 4 4 4 7 5 5 44 44 5 92 44 5 5 6 4 4 4 9 15 9 9 9 * 9 15 10 10 11 11 11 11 11 * 11 12 12 13 13 13 13 13 13 13 14 14 * 9 15 9 9 9 9
\ No newline at end of file +// LINES: 39 4 4 4 7 5 5 45 45 5 92 45 5 5 6 4 4 4 9 15 9 9 9 * 9 15 10 10 11 11 11 11 11 * 11 12 12 13 13 13 13 13 13 13 14 14 * 9 15 9 9 9 9
\ No newline at end of file diff --git a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt index 850d994ff12..dac22928c8c 100644 --- a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt +++ b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt @@ -29,7 +29,10 @@ val asserter: Asserter internal var _asserter: Asserter? = null /** Asserts that the given [block] returns `true`. */ -fun assertTrue(message: String? = null, block: () -> Boolean): Unit = assertTrue(block(), message) +fun assertTrue(message: String? = null, block: () -> Boolean) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + assertTrue(block(), message) +} /** Asserts that the expression is `true` with an optional [message]. */ fun assertTrue(actual: Boolean, message: String? = null) { @@ -38,7 +41,10 @@ fun assertTrue(actual: Boolean, message: String? = null) { } /** Asserts that the given [block] returns `false`. */ -fun assertFalse(message: String? = null, block: () -> Boolean): Unit = assertFalse(block(), message) +fun assertFalse(message: String? = null, block: () -> Boolean) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + assertFalse(block(), message) +} /** Asserts that the expression is `false` with an optional [message]. */ fun assertFalse(actual: Boolean, message: String? = null) { @@ -105,11 +111,13 @@ fun fail(message: String? = null, cause: Throwable? = null): Nothing { /** Asserts that given function [block] returns the given [expected] value. */ fun <@OnlyInputTypes T> expect(expected: T, block: () -> T) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } assertEquals(expected, block()) } /** Asserts that given function [block] returns the given [expected] value and use the given [message] if it fails. */ fun <@OnlyInputTypes T> expect(expected: T, message: String?, block: () -> T) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } assertEquals(expected, block(), message) } diff --git a/libraries/stdlib/api/js-v1/kotlin.text.kt b/libraries/stdlib/api/js-v1/kotlin.text.kt index 607a2a72950..3510921a03f 100644 --- a/libraries/stdlib/api/js-v1/kotlin.text.kt +++ b/libraries/stdlib/api/js-v1/kotlin.text.kt @@ -1275,8 +1275,8 @@ public final class StringBuilder : kotlin.text.Appendable, kotlin.CharSequence { @kotlin.WasExperimental(markerClass = {kotlin.ExperimentalStdlibApi::class}) public final fun appendRange(value: kotlin.CharSequence, startIndex: kotlin.Int, endIndex: kotlin.Int): kotlin.text.StringBuilder - @kotlin.SinceKotlin(version = "1.4") - @kotlin.WasExperimental(markerClass = {kotlin.ExperimentalStdlibApi::class}) + @kotlin.SinceKotlin(version = "1.3") + @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Obtaining StringBuilder capacity is not supported in JS and common code.") public final fun capacity(): kotlin.Int @kotlin.SinceKotlin(version = "1.3") diff --git a/libraries/stdlib/api/js/kotlin.kt b/libraries/stdlib/api/js/kotlin.kt index 2dc8a14fa1e..3c0cc877ba5 100644 --- a/libraries/stdlib/api/js/kotlin.kt +++ b/libraries/stdlib/api/js/kotlin.kt @@ -1038,6 +1038,19 @@ public final annotation class Deprecated : kotlin.Annotation { public final val replaceWith: kotlin.ReplaceWith { get; } } +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.TYPEALIAS}) +@kotlin.annotation.MustBeDocumented +@kotlin.SinceKotlin(version = "1.4") +public final annotation class DeprecatedSinceKotlin : kotlin.Annotation { + public constructor DeprecatedSinceKotlin(warningSince: kotlin.String = ..., errorSince: kotlin.String = ..., hiddenSince: kotlin.String = ...) + + public final val errorSince: kotlin.String { get; } + + public final val hiddenSince: kotlin.String { get; } + + public final val warningSince: kotlin.String { get; } +} + public final enum class DeprecationLevel : kotlin.Enum<kotlin.DeprecationLevel> { enum entry WARNING diff --git a/libraries/stdlib/api/js/kotlin.text.kt b/libraries/stdlib/api/js/kotlin.text.kt index 607a2a72950..3510921a03f 100644 --- a/libraries/stdlib/api/js/kotlin.text.kt +++ b/libraries/stdlib/api/js/kotlin.text.kt @@ -1275,8 +1275,8 @@ public final class StringBuilder : kotlin.text.Appendable, kotlin.CharSequence { @kotlin.WasExperimental(markerClass = {kotlin.ExperimentalStdlibApi::class}) public final fun appendRange(value: kotlin.CharSequence, startIndex: kotlin.Int, endIndex: kotlin.Int): kotlin.text.StringBuilder - @kotlin.SinceKotlin(version = "1.4") - @kotlin.WasExperimental(markerClass = {kotlin.ExperimentalStdlibApi::class}) + @kotlin.SinceKotlin(version = "1.3") + @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Obtaining StringBuilder capacity is not supported in JS and common code.") public final fun capacity(): kotlin.Int @kotlin.SinceKotlin(version = "1.3") diff --git a/libraries/stdlib/js/src/kotlin/dom/Builders.kt b/libraries/stdlib/js/src/kotlin/dom/Builders.kt index 20944865cb3..04487f47928 100644 --- a/libraries/stdlib/js/src/kotlin/dom/Builders.kt +++ b/libraries/stdlib/js/src/kotlin/dom/Builders.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -14,7 +14,7 @@ import kotlinx.dom.createElement as newCreateElement /** * Creates a new element with the specified [name]. * - * The element is initialized with the speicifed [init] function. + * The element is initialized with the specified [init] function. */ @LowPriorityInOverloadResolution @Deprecated( @@ -26,7 +26,7 @@ public inline fun Document.createElement(name: String, noinline init: Element.() /** * Appends a newly created element with the specified [name] to this element. * - * The element is initialized with the speicifed [init] function. + * The element is initialized with the specified [init] function. */ @LowPriorityInOverloadResolution @Deprecated( diff --git a/libraries/stdlib/js/src/kotlin/text/StringBuilderJs.kt b/libraries/stdlib/js/src/kotlin/text/StringBuilderJs.kt index 28e72acd311..f8e6d95dfbf 100644 --- a/libraries/stdlib/js/src/kotlin/text/StringBuilderJs.kt +++ b/libraries/stdlib/js/src/kotlin/text/StringBuilderJs.kt @@ -17,7 +17,6 @@ public actual class StringBuilder actual constructor(content: String) : Appendab * In Kotlin/JS implementation of StringBuilder the initial capacity has no effect on the further performance of operations. */ actual constructor(capacity: Int) : this() { - this.asDynamic()._capacity = capacity } /** Constructs a string builder that contains the same characters as the specified [content] char sequence. */ @@ -135,9 +134,10 @@ public actual class StringBuilder actual constructor(content: String) : Appendab * * In Kotlin/JS implementation of StringBuilder the value returned from this method may not indicate the actual size of the backing storage. */ - @SinceKotlin("1.4") - @WasExperimental(ExperimentalStdlibApi::class) - actual fun capacity(): Int = if (this.asDynamic()._capacity !== undefined) maxOf(this.asDynamic()._capacity, length) else length + @SinceKotlin("1.3") +// @ExperimentalStdlibApi + @Deprecated("Obtaining StringBuilder capacity is not supported in JS and common code.", level = DeprecationLevel.ERROR) + actual fun capacity(): Int = length /** * Ensures that the capacity of this string builder is at least equal to the specified [minimumCapacity]. @@ -151,9 +151,6 @@ public actual class StringBuilder actual constructor(content: String) : Appendab @SinceKotlin("1.4") @WasExperimental(ExperimentalStdlibApi::class) actual fun ensureCapacity(minimumCapacity: Int) { - if (minimumCapacity > capacity()) { - this.asDynamic()._capacity = minimumCapacity - } } /** @@ -367,9 +364,6 @@ public actual class StringBuilder actual constructor(content: String) : Appendab @SinceKotlin("1.4") @WasExperimental(ExperimentalStdlibApi::class) actual fun trimToSize() { - if (this.asDynamic()._capacity !== undefined) { - this.asDynamic()._capacity = length - } } override fun toString(): String = string diff --git a/libraries/stdlib/js/src/kotlinx/dom/Builders.kt b/libraries/stdlib/js/src/kotlinx/dom/Builders.kt index 24a75f02b43..95ac70a1604 100644 --- a/libraries/stdlib/js/src/kotlinx/dom/Builders.kt +++ b/libraries/stdlib/js/src/kotlinx/dom/Builders.kt @@ -1,24 +1,30 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package kotlinx.dom import org.w3c.dom.* +import kotlin.contracts.* /** * Creates a new element with the specified [name]. * - * The element is initialized with the speicifed [init] function. + * The element is initialized with the specified [init] function. */ -public fun Document.createElement(name: String, init: Element.() -> Unit): Element = createElement(name).apply(init) +public fun Document.createElement(name: String, init: Element.() -> Unit): Element { + contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) } + return createElement(name).apply(init) +} /** * Appends a newly created element with the specified [name] to this element. * - * The element is initialized with the speicifed [init] function. + * The element is initialized with the specified [init] function. */ -public fun Element.appendElement(name: String, init: Element.() -> Unit): Element = - ownerDocument!!.createElement(name, init).also { appendChild(it) } +public fun Element.appendElement(name: String, init: Element.() -> Unit): Element { + contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) } + return ownerDocument!!.createElement(name, init).also { appendChild(it) } +} diff --git a/libraries/stdlib/jvm/src/kotlin/concurrent/Locks.kt b/libraries/stdlib/jvm/src/kotlin/concurrent/Locks.kt index 969bc8bd3b7..da6728ec88c 100644 --- a/libraries/stdlib/jvm/src/kotlin/concurrent/Locks.kt +++ b/libraries/stdlib/jvm/src/kotlin/concurrent/Locks.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -8,7 +8,7 @@ package kotlin.concurrent import java.util.concurrent.locks.Lock import java.util.concurrent.locks.ReentrantReadWriteLock -import java.util.concurrent.CountDownLatch +import kotlin.contracts.* /** * Executes the given [action] under this lock. @@ -16,6 +16,7 @@ import java.util.concurrent.CountDownLatch */ @kotlin.internal.InlineOnly public inline fun <T> Lock.withLock(action: () -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } lock() try { return action() @@ -30,6 +31,7 @@ public inline fun <T> Lock.withLock(action: () -> T): T { */ @kotlin.internal.InlineOnly public inline fun <T> ReentrantReadWriteLock.read(action: () -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } val rl = readLock() rl.lock() try { @@ -54,6 +56,7 @@ public inline fun <T> ReentrantReadWriteLock.read(action: () -> T): T { */ @kotlin.internal.InlineOnly public inline fun <T> ReentrantReadWriteLock.write(action: () -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } val rl = readLock() val readCount = if (writeHoldCount == 0) readHoldCount else 0 diff --git a/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt b/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt index 99b79a4b77f..a4b6b48da42 100644 --- a/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt +++ b/libraries/stdlib/jvm/test/coroutines/CoroutinesTest.kt @@ -39,11 +39,17 @@ class DispatcherSwitcher( private val contextDispatcher: TestDispatcher, private val resumeDispatcher: TestDispatcher ) { - suspend fun run(): Int = suspendCoroutine { cont -> - contextDispatcher.assertThread() - resumeDispatcher.executor.execute { - resumeDispatcher.assertThread() - cont.resume(42) + suspend fun run(): Int { + val sideEffect: Int + val runResult = suspendCoroutine<Int> { cont -> + contextDispatcher.assertThread() + resumeDispatcher.executor.execute { + resumeDispatcher.assertThread() + cont.resume(42) + } + sideEffect = 21 } + assertEquals(21, sideEffect) + return runResult } } diff --git a/libraries/stdlib/src/kotlin/coroutines/Continuation.kt b/libraries/stdlib/src/kotlin/coroutines/Continuation.kt index a4f06cf2c6d..375cec539a5 100644 --- a/libraries/stdlib/src/kotlin/coroutines/Continuation.kt +++ b/libraries/stdlib/src/kotlin/coroutines/Continuation.kt @@ -1,10 +1,11 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package kotlin.coroutines +import kotlin.contracts.* import kotlin.coroutines.intrinsics.* import kotlin.internal.InlineOnly @@ -138,12 +139,14 @@ public fun <R, T> (suspend R.() -> T).startCoroutine( */ @SinceKotlin("1.3") @InlineOnly -public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T = - suspendCoroutineUninterceptedOrReturn { c: Continuation<T> -> +public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return suspendCoroutineUninterceptedOrReturn { c: Continuation<T> -> val safe = SafeContinuation(c.intercepted()) block(safe) safe.getOrThrow() } +} /** * Returns the context of the current coroutine. diff --git a/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt b/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt index ba08334d69a..3b3dd23e4dd 100644 --- a/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt +++ b/libraries/stdlib/src/kotlin/coroutines/intrinsics/Intrinsics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -8,6 +8,7 @@ package kotlin.coroutines.intrinsics +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.internal.InlineOnly @@ -37,8 +38,10 @@ import kotlin.internal.InlineOnly @SinceKotlin("1.3") @InlineOnly @Suppress("UNUSED_PARAMETER", "RedundantSuspendModifier") -public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T = +public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic") +} /** * This value is used as a return value of [suspendCoroutineUninterceptedOrReturn] `block` argument to state that diff --git a/libraries/stdlib/src/kotlin/reflect/KClass.kt b/libraries/stdlib/src/kotlin/reflect/KClass.kt index 2d8ee2ed2d7..f675514cffd 100644 --- a/libraries/stdlib/src/kotlin/reflect/KClass.kt +++ b/libraries/stdlib/src/kotlin/reflect/KClass.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -13,7 +13,7 @@ package kotlin.reflect * * @param T the type of the class. */ -public expect interface KClass<T : Any> { +public expect interface KClass<T : Any> : KClassifier { /** * The simple name of the class as it was declared in the source code, * or `null` if the class has no name (if, for example, it is a class of an anonymous object). diff --git a/libraries/stdlib/src/kotlin/text/StringBuilder.kt b/libraries/stdlib/src/kotlin/text/StringBuilder.kt index faef1ff6aaa..49a6c2b0332 100644 --- a/libraries/stdlib/src/kotlin/text/StringBuilder.kt +++ b/libraries/stdlib/src/kotlin/text/StringBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -8,6 +8,8 @@ package kotlin.text +import kotlin.contracts.* + /** * A mutable sequence of characters. * @@ -88,8 +90,9 @@ expect class StringBuilder : Appendable, CharSequence { * * The capacity is the maximum length this string builder can have before an allocation occurs. */ - @SinceKotlin("1.4") - @WasExperimental(ExperimentalStdlibApi::class) + @SinceKotlin("1.3") +// @ExperimentalStdlibApi + @Deprecated("Obtaining StringBuilder capacity is not supported in JS and common code.", level = DeprecationLevel.ERROR) fun capacity(): Int /** @@ -399,8 +402,10 @@ public inline fun StringBuilder.append(obj: Any?): StringBuilder = this.append(o * and then converting it to [String]. */ @kotlin.internal.InlineOnly -public inline fun buildString(builderAction: StringBuilder.() -> Unit): String = - StringBuilder().apply(builderAction).toString() +public inline fun buildString(builderAction: StringBuilder.() -> Unit): String { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return StringBuilder().apply(builderAction).toString() +} /** * Builds new string by populating newly created [StringBuilder] initialized with the given [capacity] @@ -408,8 +413,10 @@ public inline fun buildString(builderAction: StringBuilder.() -> Unit): String = */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun buildString(capacity: Int, builderAction: StringBuilder.() -> Unit): String = - StringBuilder(capacity).apply(builderAction).toString() +public inline fun buildString(capacity: Int, builderAction: StringBuilder.() -> Unit): String { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return StringBuilder(capacity).apply(builderAction).toString() +} /** * Appends all arguments to the given StringBuilder. diff --git a/libraries/stdlib/src/kotlin/time/Duration.kt b/libraries/stdlib/src/kotlin/time/Duration.kt index 517c1a8c623..a1aef5ac8dc 100644 --- a/libraries/stdlib/src/kotlin/time/Duration.kt +++ b/libraries/stdlib/src/kotlin/time/Duration.kt @@ -1,10 +1,11 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package kotlin.time +import kotlin.contracts.* import kotlin.math.abs @OptIn(ExperimentalTime::class) @@ -104,8 +105,10 @@ public inline class Duration internal constructor(internal val value: Double) : * If the value doesn't fit in [Int] range, i.e. it's greater than [Int.MAX_VALUE] or less than [Int.MIN_VALUE], * it is coerced into that range. */ - public inline fun <T> toComponents(action: (days: Int, hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T = - action(inDays.toInt(), hoursComponent, minutesComponent, secondsComponent, nanosecondsComponent) + public inline fun <T> toComponents(action: (days: Int, hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return action(inDays.toInt(), hoursComponent, minutesComponent, secondsComponent, nanosecondsComponent) + } /** * Splits this duration into hours, minutes, seconds, and nanoseconds and executes the given [action] with these components. @@ -118,8 +121,10 @@ public inline class Duration internal constructor(internal val value: Double) : * If the value doesn't fit in [Int] range, i.e. it's greater than [Int.MAX_VALUE] or less than [Int.MIN_VALUE], * it is coerced into that range. */ - public inline fun <T> toComponents(action: (hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T = - action(inHours.toInt(), minutesComponent, secondsComponent, nanosecondsComponent) + public inline fun <T> toComponents(action: (hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return action(inHours.toInt(), minutesComponent, secondsComponent, nanosecondsComponent) + } /** * Splits this duration into minutes, seconds, and nanoseconds and executes the given [action] with these components. @@ -131,8 +136,10 @@ public inline class Duration internal constructor(internal val value: Double) : * If the value doesn't fit in [Int] range, i.e. it's greater than [Int.MAX_VALUE] or less than [Int.MIN_VALUE], * it is coerced into that range. */ - public inline fun <T> toComponents(action: (minutes: Int, seconds: Int, nanoseconds: Int) -> T): T = - action(inMinutes.toInt(), secondsComponent, nanosecondsComponent) + public inline fun <T> toComponents(action: (minutes: Int, seconds: Int, nanoseconds: Int) -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return action(inMinutes.toInt(), secondsComponent, nanosecondsComponent) + } /** * Splits this duration into seconds, and nanoseconds and executes the given [action] with these components. @@ -143,8 +150,10 @@ public inline class Duration internal constructor(internal val value: Double) : * If the value doesn't fit in [Long] range, i.e. it's greater than [Long.MAX_VALUE] or less than [Long.MIN_VALUE], * it is coerced into that range. */ - public inline fun <T> toComponents(action: (seconds: Long, nanoseconds: Int) -> T): T = - action(inSeconds.toLong(), nanosecondsComponent) + public inline fun <T> toComponents(action: (seconds: Long, nanoseconds: Int) -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return action(inSeconds.toLong(), nanosecondsComponent) + } @PublishedApi internal val hoursComponent: Int get() = (inHours % 24).toInt() diff --git a/libraries/stdlib/test/reflection/KClassTest.kt b/libraries/stdlib/test/reflection/KClassTest.kt new file mode 100644 index 00000000000..f99338bd273 --- /dev/null +++ b/libraries/stdlib/test/reflection/KClassTest.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package test.reflection + +import test.* +import kotlin.reflect.* +import kotlin.test.* + +class KClassTest { + + @Test + fun className() { + assertEquals("KClassTest", KClassTest::class.simpleName) +// assertEquals(null, object {}::class.simpleName) // doesn't work as documented in JDK < 9, see KT-23072 + } + + @Test + fun extendsKClassifier() { + assertStaticAndRuntimeTypeIs<KClassifier>(KClassTest::class) + } + + @Test + fun isInstanceCastSafeCast() { + fun <T : Any> checkIsInstance(kclass: KClass<T>, value: Any?, expectedResult: Boolean) { + if (expectedResult) { + assertTrue(kclass.isInstance(value)) + assertSame(value, kclass.safeCast(value)) + assertSame(value, kclass.cast(value)) + } else { + assertFalse(kclass.isInstance(value)) + assertNull(kclass.safeCast(value)) + assertFailsWith<ClassCastException> { kclass.cast(value) } + } + } + + val numberClass = Number::class + checkIsInstance(numberClass, 1, true) + checkIsInstance(numberClass, 1.0, true) + checkIsInstance(numberClass, null, false) + checkIsInstance(numberClass, "42", false) + } +} diff --git a/libraries/stdlib/test/text/StringBuilderTest.kt b/libraries/stdlib/test/text/StringBuilderTest.kt index 408689fe085..991b7875de8 100644 --- a/libraries/stdlib/test/text/StringBuilderTest.kt +++ b/libraries/stdlib/test/text/StringBuilderTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -236,8 +236,9 @@ class StringBuilderTest { } @Test + @Suppress("DEPRECATION_ERROR") fun capacityTest() { - assertEquals(100, StringBuilder(100).capacity()) +// assertEquals(100, StringBuilder(100).capacity()) // not implemented in JS StringBuilder("string builder from string capacity test").let { sb -> assertTrue(sb.capacity() >= sb.length) @@ -251,7 +252,7 @@ class StringBuilderTest { sb.ensureCapacity(1) assertTrue(sb.capacity() >= sb.length) sb.ensureCapacity(sb.length * 10) - assertTrue(sb.capacity() >= sb.length * 10) +// assertTrue(sb.capacity() >= sb.length * 10) // not implemented in JS } } @@ -423,11 +424,11 @@ class StringBuilderTest { fun trimToSize() { StringBuilder("my trimToSize test").let { sb -> assertEquals(18, sb.length) - assertTrue(sb.capacity() >= sb.length) +// assertTrue(sb.capacity() >= sb.length) sb.append('1') sb.trimToSize() assertEquals(19, sb.length) - assertTrue(sb.capacity() >= sb.length) +// assertTrue(sb.capacity() >= sb.length) } } diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt index ab6bae3d678..0bfb56dd2bd 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt @@ -32,10 +32,12 @@ enum class KotlinPlatformType: Named, Serializable { if (candidateValues == setOf(androidJvm, jvm)) closestMatch(androidJvm) - if (common in candidateValues) + if (common in candidateValues && jvm !in candidateValues && androidJvm !in candidateValues) { // then the consumer requests common or requests no platform-specific artifacts, - // so common is the best match, KT-26834 + // so common is the best match, KT-26834; apply this rule only when no JVM variant is available, + // as doing otherwise would conflict with Gradle java's disambiguation rules and lead to KT-32239 closestMatch(common) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index b1352578220..c0c19fdd7c3 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -28,7 +28,7 @@ abstract class BaseGradleIT { protected var workingDir = File(".") - protected open fun defaultBuildOptions(): BuildOptions = BuildOptions(withDaemon = true) + internal open fun defaultBuildOptions(): BuildOptions = BuildOptions(withDaemon = true) open val defaultGradleVersion: GradleVersionRequired get() = GradleVersionRequired.None diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt index 6c815a6807c..8f1cf5614ac 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt @@ -524,6 +524,17 @@ class HierarchicalMppIT : BaseGradleIT() { } } + @Test + fun testTransitiveDependencyOnSelf() = with(Project("transitive-dep-on-self-hmpp")) { + testDependencyTransformations(subproject = "lib") { reports -> + reports.single { + it.sourceSetName == "commonTest" && it.scope == "implementation" && "libtests" in it.groupAndModule + }.let { + assertEquals(setOf("commonMain", "jvmAndJsMain"), it.allVisibleSourceSets) + } + } + } + private fun Project.testDependencyTransformations( subproject: String? = null, check: CompiledProject.(reports: Iterable<DependencyTransformationReport>) -> Unit diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt new file mode 100644 index 00000000000..7c916a87290 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt @@ -0,0 +1,307 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle + +import org.jetbrains.kotlin.gradle.internals.KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME +import org.jetbrains.kotlin.gradle.util.AGPVersion +import org.jetbrains.kotlin.gradle.util.modify +import org.jetbrains.kotlin.test.KotlinTestUtils +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class KotlinSpecificDependenciesIT : BaseGradleIT() { + + override val defaultGradleVersion: GradleVersionRequired + get() = GradleVersionRequired.FOR_MPP_SUPPORT + + override fun defaultBuildOptions(): BuildOptions = + super.defaultBuildOptions().copy(androidGradlePluginVersion = AGPVersion.v3_6_0, androidHome = KotlinTestUtils.findAndroidSdk()) + + private var testBuildRunId = 0 + + private fun Project.prepare() { // call this when reusing a project after a test, too, in order to remove any added dependencies + setupWorkingDir() + gradleSettingsScript().takeIf { it.exists() }?.modify(::transformBuildScriptWithPluginsDsl) + gradleBuildScript().modify { + transformBuildScriptWithPluginsDsl(it).lines().filter { line -> + "stdlib" !in line && "kotlin(\"test" !in line && "kotlin-test" !in line + }.joinToString("\n") + } + } + + private fun jsProject() = Project("kotlin-js-plugin-project").apply { + setupWorkingDir() + gradleBuildScript().modify { it.lines().filter { "html" !in it }.joinToString("\n") } + projectFile("Main.kt").modify { "fun f() = listOf(1, 2, 3).joinToString()" } + prepare() + } + + private fun androidProject() = Project("AndroidLibraryKotlinProject").apply { prepare() } + + private fun mppProject() = Project("jvm-and-js-hmpp").apply { + setupWorkingDir() + prepare() + } + + private fun jvmProject() = Project("simpleProject").apply { + prepare() + gradleBuildScript().modify { it.lines().filter { "testng" !in it }.joinToString("\n") } + } + + @Test + fun testStdlibByDefault() { + listOf( // projects and tasks: + androidProject() to listOf("compileDebugKotlin"), + jvmProject() to listOf("compileKotlin"), + jsProject() to listOf("compileKotlinJs"), + mppProject() to listOf( + "compileKotlinJvm", + "compileKotlinJs", + "compileCommonMainKotlinMetadata", + "compileJvmAndJsMainKotlinMetadata" + ) + ).forEach { (project, tasks) -> + with(project) { + prepare() + tasks.forEach { task -> + project.checkTaskCompileClasspath(task, listOf("kotlin-stdlib" /*any of them*/)) + } + projectDir.resolve("gradle.properties").appendText( + "\nkotlin.stdlib.default.dependency=false" + ) + tasks.forEach { task -> + project.checkTaskCompileClasspath(task, listOf(), checkModulesNotInClasspath = listOf("kotlin-stdlib" /*any of them*/)) + } + } + } + } + + @Test + fun testStdlibBasedOnJdk() = with(jvmProject()) { + prepare() + gradleBuildScript().modify { "$it\nkotlin.target.compilations[\"main\"].kotlinOptions { jvmTarget = \"1.6\" }" } + val version = defaultBuildOptions().kotlinVersion + checkTaskCompileClasspath( + "compileKotlin", + listOf("kotlin-stdlib-$version"), + listOf("kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8") + ) + gradleBuildScript().modify { "$it\nkotlin.target.compilations[\"main\"].kotlinOptions { jvmTarget = \"11\" }" } + checkTaskCompileClasspath( + "compileKotlin", + listOf("kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8"), + ) + } + + @Test + fun testOverrideStdlib() = with(jvmProject().apply { prepare() }) { + gradleBuildScript().appendText( + "\n" + """ + kotlin.target.compilations["main"].kotlinOptions.jvmTarget = "1.8" + dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib") } + """.trimIndent() + ) + // Check that the explicit stdlib overrides the plugin's choice of stdlib-jdk8 + checkTaskCompileClasspath( + "compileKotlin", + listOf("kotlin-stdlib-${defaultBuildOptions().kotlinVersion}"), + listOf("kotlin-stdlib-jdk8") + ) + } + + private val kotlinTestMultiplatformDependency = "org.jetbrains.kotlin:$KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME" + + @Test + fun testKotlinTestSingleDependency() { + data class TestCase( + val project: Project, + val configurationsToAddDependency: List<String>, + val classpathElementsExpectedByTask: Map<String, List<String>>, + val filesExpectedByConfiguration: Map<String, List<String>> = emptyMap() + ) + + listOf( + TestCase( + androidProject(), + listOf("testImplementation"), + mapOf( + "compileDebugUnitTestKotlin" to listOf("kotlin-test-junit"), + "compileReleaseUnitTestKotlin" to listOf("kotlin-test-junit") + ) + ), + TestCase( + androidProject(), + listOf("androidTestImplementation"), + mapOf("compileDebugAndroidTestKotlin" to listOf("kotlin-test-junit")) + ), + TestCase(jvmProject(), listOf("testImplementation"), mapOf("compileTestKotlin" to listOf("kotlin-test-testng"))), + TestCase(jsProject(), listOf("testImplementation"), mapOf("compileTestKotlinJs" to listOf("kotlin-test-js"))), + TestCase( + mppProject(), + listOf("commonTestImplementation"), + mapOf( + "compileTestKotlinJvm" to listOf("kotlin-test-junit"), + "compileTestKotlinJs" to listOf("kotlin-test-js") + ), + mapOf( + "commonTestImplementationDependenciesMetadata" to listOf("kotlin-test-common", "kotlin-test-annotations-common"), + "commonTestApiDependenciesMetadata" to listOf("!kotlin-test-common", "!kotlin-test-annotations-common"), + ) + ), + TestCase( + mppProject(), + listOf("jvmAndJsTestApi", "jvmAndJsTestCompileOnly"), // add to the intermediate source set, and to two scopes + mapOf( + "compileTestKotlinJvm" to listOf("kotlin-test-junit"), + "compileTestKotlinJs" to listOf("kotlin-test-js") + ), + mapOf( + "commonTestApiDependenciesMetadata" to listOf("!kotlin-test-common"), + "commonTestCompileOnlyDependenciesMetadata" to listOf("!kotlin-test-common"), + "jvmAndJsTestApiDependenciesMetadata" to listOf("kotlin-test-common"), + "jvmAndJsTestCompileOnlyDependenciesMetadata" to listOf("kotlin-test-common"), + "jvmAndJsTestImplementationDependenciesMetadata" to listOf("!kotlin-test-common"), + ) + ) + ).forEach { testCase -> + with(testCase) { + project.prepare() + project.gradleBuildScript().appendText( + configurationsToAddDependency.joinToString("\n", "\n") { configuration -> + "\ndependencies { \"$configuration\"(\"$kotlinTestMultiplatformDependency\") }" + } + ) + classpathElementsExpectedByTask.forEach { (task, expected) -> + val (notInClasspath, inClasspath) = expected.partition { it.startsWith("!") } + project.checkTaskCompileClasspath(task, inClasspath, notInClasspath.map { it.removePrefix("!") }) + } + filesExpectedByConfiguration.forEach { (configuration, expected) -> + val (notInItems, inItems) = expected.partition { it.startsWith("!") } + project.checkConfigurationContent(configuration, subproject = null, inItems, notInItems.map { it.removePrefix("!") }) + } + } + } + } + + @Test + fun testFrameworkSelection() { + data class TestCase( + val project: Project, + val testTaskName: String, + val compileTaskName: String, + val configurationToAddDependency: String + ) + + val frameworks = listOf("useJUnit()" to "junit", "useTestNG()" to "testng", "useJUnitPlatform()" to "junit5") + listOf( + TestCase(jvmProject(), "test", "compileTestKotlin", "testImplementation"), + TestCase(mppProject(), "jvmTest", "compileTestKotlinJvm", "commonTestImplementation"), + TestCase(mppProject(), "jvmTest", "compileTestKotlinJvm", "jvmAndJsTestImplementation") + ).forEach { (project, testTaskName, compileTaskName, configuration) -> + project.prepare() + project.gradleBuildScript().appendText("""${'\n'}dependencies { "$configuration"("$kotlinTestMultiplatformDependency") }""") + + frameworks.forEach { (setup, frameworkName) -> + with(project) { + gradleBuildScript().appendText("\n(tasks.getByName(\"$testTaskName\") as Test).$setup") + val expectedModule = "kotlin-test-$frameworkName-" + checkTaskCompileClasspath( + compileTaskName, + listOf(expectedModule), + frameworks.map { "kotlin-test-" + it.second + "-" } - expectedModule + ) + } + } + } + } + + @Test + fun testRemoveKotlinTestDependency() = with(jvmProject().apply { prepare() }) { + gradleBuildScript().appendText( + "\n" + """ + dependencies { testImplementation("$kotlinTestMultiplatformDependency") } + configurations.getByName("testImplementation").dependencies.removeAll { it.name == "$KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME" } + """.trimIndent() + ) + checkTaskCompileClasspath("compileTestKotlin", checkModulesNotInClasspath = listOf("kotlin-test")) + + // Add it back after removal: + gradleBuildScript().appendText( + "\n" + """ + dependencies { testImplementation("$kotlinTestMultiplatformDependency") } + """ + ) + checkTaskCompileClasspath("compileTestKotlin", checkModulesInClasspath = listOf("kotlin-test")) + } + + @Test + fun testCoreLibraryVersionsDsl() = with(jvmProject().apply { prepare() }) { + val customVersion = "1.3.70" + gradleBuildScript().appendText( + "\n" + """ + kotlin.coreLibrariesVersion = "$customVersion" + dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-reflect") + testImplementation("org.jetbrains.kotlin:kotlin-test-multiplatform") + } + test.useJUnit() + """.trimIndent() + ) + checkTaskCompileClasspath( + "compileTestKotlin", + listOf("kotlin-stdlib-", "kotlin-reflect-", "kotlin-test-junit-").map { it + customVersion } + ) + } + + private fun Project.checkConfigurationContent( + configurationName: String, + subproject: String? = null, + checkModulesInResolutionResult: List<String> = emptyList(), + checkModulesNotInResolutionResult: List<String> = emptyList() + ) { + val expression = """configurations["$configurationName"].toList()""" + checkPrintedItems(subproject, expression, checkModulesInResolutionResult, checkModulesNotInResolutionResult) + } + + private fun Project.checkTaskCompileClasspath( + taskPath: String, + checkModulesInClasspath: List<String> = emptyList(), + checkModulesNotInClasspath: List<String> = emptyList() + ) { + val subproject = taskPath.substringBeforeLast(":").takeIf { it.isNotEmpty() && it != taskPath } + val taskName = taskPath.removePrefix(subproject.orEmpty()) + val expression = """(tasks.getByName("$taskName") as AbstractCompile).classpath.toList()""" + checkPrintedItems(subproject, expression, checkModulesInClasspath, checkModulesNotInClasspath) + } + + private fun Project.checkPrintedItems( + subproject: String?, + itemsExpression: String, + checkAnyItemsContains: List<String>, + checkNoItemContains: List<String> + ) { + setupWorkingDir() + val printingTaskName = "printItems${testBuildRunId++}" + gradleBuildScript(subproject).appendText( + """ + ${'\n'} + tasks.create("$printingTaskName") { + doLast { + println("###$printingTaskName" + $itemsExpression) + } + } + """.trimIndent() + ) + build("${subproject?.prependIndent(":").orEmpty()}:$printingTaskName") { + assertSuccessful() + val itemsLine = output.lines().single { "###$printingTaskName" in it }.substringAfter(printingTaskName) + val items = itemsLine.removeSurrounding("[", "]").split(", ").toSet() + checkAnyItemsContains.forEach { pattern -> assertTrue { items.any { pattern in it } } } + checkNoItemContains.forEach { pattern -> assertFalse { items.any { pattern in it } } } + } + } +}
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt index 14010fca230..57a5ddcb4ea 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt @@ -2107,13 +2107,13 @@ class NewMultiplatformIT : BaseGradleIT() { fun testDependencies() = testResolveAllConfigurations("app") { assertContains(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata --> junit-4.12.jar") assertEquals( - 1, + 2, // the dependency above and stdlib (Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output).count() ) assertContains(">> :app:testNonTransitiveDependencyNotationApiDependenciesMetadata --> kotlin-reflect-${defaultBuildOptions().kotlinVersion}.jar") assertEquals( - 1, + 2, // the dependency above and stdlib (Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output).count() ) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt index f48b998afe3..14395c033ea 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt @@ -5,8 +5,10 @@ package org.jetbrains.kotlin.gradle +import org.jetbrains.kotlin.gradle.util.AGPVersion import org.jetbrains.kotlin.gradle.util.checkBytecodeContains import org.jetbrains.kotlin.gradle.util.modify +import org.jetbrains.kotlin.test.KotlinTestUtils import org.junit.Test import java.io.File import kotlin.test.assertTrue @@ -193,10 +195,10 @@ class SubpluginsIT : BaseGradleIT() { } @Test - fun testKotlinVersionDowngradeInSupbrojectKt39809() = with(Project("multiprojectWithDependency")) { + fun testKotlinVersionDowngradeInSupbrojectKt39809() = with(Project("android-dagger", directoryPrefix = "kapt2")) { setupWorkingDir() - projectDir.resolve("projA/build.gradle").modify { + gradleBuildScript("app").modify { """ buildscript { repositories { @@ -210,7 +212,13 @@ class SubpluginsIT : BaseGradleIT() { $it """.trimIndent() } - build(":projA:compileKotlin") { + build( + ":app:compileDebugKotlin", + options = defaultBuildOptions().copy( + androidGradlePluginVersion = AGPVersion.v3_4_1, + androidHome = KotlinTestUtils.findAndroidSdk() + ) + ) { assertSuccessful() } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/VariantAwareDependenciesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/VariantAwareDependenciesIT.kt index 889629f2c33..0066f2d5cde 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/VariantAwareDependenciesIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/VariantAwareDependenciesIT.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType import org.jetbrains.kotlin.gradle.util.* import org.junit.Test +import kotlin.test.assertTrue class VariantAwareDependenciesIT : BaseGradleIT() { private val gradleVersion = GradleVersionRequired.FOR_MPP_SUPPORT @@ -315,6 +316,27 @@ class VariantAwareDependenciesIT : BaseGradleIT() { } } + @Test + fun testResolveDependencyOnMppInCustomConfiguration() = with(Project("simpleProject", GradleVersionRequired.FOR_MPP_SUPPORT)) { + setupWorkingDir() + + gradleBuildScript().appendText( + "\n" + """ + configurations.create("custom") + repositories.maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") } + dependencies { custom("org.jetbrains.kotlinx:kotlinx-cli:0.2.0-dev-7") } + tasks.register("resolveCustom") { doLast { println("###" + configurations.custom.toList()) } } + """.trimIndent() + ) + + build("resolveCustom") { + assertSuccessful() + val printedLine = output.lines().single { "###" in it }.substringAfter("###") + val items = printedLine.removeSurrounding("[", "]").split(", ") + assertTrue(items.toString()) { items.any { "kotlinx-cli-jvm" in it } } + } + } + } internal fun BaseGradleIT.Project.embedProject(other: BaseGradleIT.Project, renameTo: String? = null) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/build.gradle.kts new file mode 100644 index 00000000000..6cb16f2b5e6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/build.gradle.kts @@ -0,0 +1,67 @@ +plugins { + kotlin("multiplatform").version("<pluginMarkerVersion>") + `maven-publish` +} + +repositories { + mavenLocal() + jcenter() +} + +group = "com.example.thirdparty" +version = "1.0" + +kotlin { + jvm() + js() + + sourceSets { + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + val jvmAndJsMain by creating { + dependsOn(commonMain) + } + val jvmAndJsTest by creating { + dependsOn(commonTest) + } + jvm().compilations["main"].defaultSourceSet { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib")) + } + } + jvm().compilations["test"].defaultSourceSet { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-junit")) + } + } + js().compilations["main"].defaultSourceSet { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib-js")) + } + } + js().compilations["test"].defaultSourceSet { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-js")) + } + } + } +} + +publishing { + repositories { + maven("../repo") + } +}
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/gradle.properties new file mode 100755 index 00000000000..2a391fe78b0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/gradle.properties @@ -0,0 +1 @@ +kotlin.mpp.enableGranularSourceSetsMetadata=true
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/settings.gradle.kts new file mode 100644 index 00000000000..055148414fb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/settings.gradle.kts @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } +} + +rootProject.name = "third-party-lib" + +enableFeaturePreview("GRADLE_METADATA")
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/commonMain/kotlin/ThirdParty.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/commonMain/kotlin/ThirdParty.kt new file mode 100644 index 00000000000..52ee4ee68a6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/commonMain/kotlin/ThirdParty.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +expect fun thirdPartyFun(): String + +private fun useStdlibInCommonMain() = listOf(1, 2, 3).joinToString()
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jsMain/kotlin/ThirdPartyJs.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jsMain/kotlin/ThirdPartyJs.kt new file mode 100644 index 00000000000..dba00046373 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jsMain/kotlin/ThirdPartyJs.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +actual fun thirdPartyFun(): String = "thirdPartyFun @ js" + +fun thirdPartyJsFun() { }
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmAndJsMain/kotlin/ThirdPartyJvmAndJs.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmAndJsMain/kotlin/ThirdPartyJvmAndJs.kt new file mode 100644 index 00000000000..21856b2ffb3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmAndJsMain/kotlin/ThirdPartyJvmAndJs.kt @@ -0,0 +1,3 @@ +package com.example.thirdparty + +private fun useStdlibInJvmAndJsMain() = listOf(1, 2, 3).joinToString()
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmMain/kotlin/ThirdPartyJvm.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmMain/kotlin/ThirdPartyJvm.kt new file mode 100644 index 00000000000..ad7e11903d8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmMain/kotlin/ThirdPartyJvm.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +actual fun thirdPartyFun(): String = "thirdPartyFun @ jvm" + +fun thirdPartyJvmFun() { }
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/build.gradle.kts new file mode 100644 index 00000000000..37bd9c77326 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/build.gradle.kts @@ -0,0 +1,6 @@ +allprojects { + repositories { + mavenLocal() + jcenter() + } +}
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/gradle.properties new file mode 100644 index 00000000000..0ae1e640ff1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/gradle.properties @@ -0,0 +1,2 @@ +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlin.mpp.enableCompatibilityMetadataVariant=true
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/build.gradle.kts new file mode 100644 index 00000000000..a6cd31c915a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/build.gradle.kts @@ -0,0 +1,62 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + jvm() + js { + browser() + } + + sourceSets { + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + } + } + + val commonTest by getting { + dependencies { + implementation(project(":libtests")) + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + + val jvmAndJsMain by creating { + dependsOn(commonMain) + } + + val jvmAndJsTest by creating { + dependsOn(commonTest) + } + + val jvmMain by getting { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib-jdk8")) + } + } + + val jvmTest by getting { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-junit")) + } + } + + val jsMain by getting { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib-js")) + } + } + + val jsTest by getting { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-js")) + } + } + } +}
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/src/commonMain/kotlin/CommonMain.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/src/commonMain/kotlin/CommonMain.kt new file mode 100644 index 00000000000..b8a633983b7 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/src/commonMain/kotlin/CommonMain.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package com.example + +fun libFun() { } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/src/commonTest/kotlin/CommonTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/src/commonTest/kotlin/CommonTest.kt new file mode 100644 index 00000000000..b2aea11ae7c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/lib/src/commonTest/kotlin/CommonTest.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package com.example + +fun libCommonTestFun() { + libtestsFun() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/libtests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/libtests/build.gradle.kts new file mode 100644 index 00000000000..28f9c1ad65a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/libtests/build.gradle.kts @@ -0,0 +1,62 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + jvm() + js { + browser() + } + + sourceSets { + val commonMain by getting { + dependencies { + api(project(":lib")) + implementation(kotlin("stdlib-common")) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + + val jvmAndJsMain by creating { + dependsOn(commonMain) + } + + val jvmAndJsTest by creating { + dependsOn(commonTest) + } + + val jvmMain by getting { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib-jdk8")) + } + } + + val jvmTest by getting { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-junit")) + } + } + + val jsMain by getting { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib-js")) + } + } + + val jsTest by getting { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-js")) + } + } + } +}
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/libtests/src/commonMain/kotlin/CommonMain.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/libtests/src/commonMain/kotlin/CommonMain.kt new file mode 100644 index 00000000000..b7c144f0961 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/libtests/src/commonMain/kotlin/CommonMain.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package com.example + +fun libtestsFun() { + libFun() +}
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/settings.gradle.kts new file mode 100644 index 00000000000..aae5124f5f2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/transitive-dep-on-self-hmpp/settings.gradle.kts @@ -0,0 +1,15 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } + plugins { + val kotlin_version: String by settings + kotlin("multiplatform").version(kotlin_version) + } +} + +rootProject.name = "lib-and-app" + +include("lib") +include("libtests")
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index b82eb5cd7b4..88867593723 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -11,10 +11,7 @@ import org.gradle.api.invocation.Gradle import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.tasks.bundling.AbstractArchiveTask import org.gradle.jvm.tasks.Jar -import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.* import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.daemon.client.CompileServiceSession import org.jetbrains.kotlin.daemon.common.CompilerId @@ -26,6 +23,7 @@ import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName +import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.utils.archivePathCompatible @@ -33,6 +31,8 @@ import org.jetbrains.kotlin.gradle.utils.newTmpFile import org.jetbrains.kotlin.gradle.utils.relativeToRoot import org.jetbrains.kotlin.incremental.IncrementalModuleEntry import org.jetbrains.kotlin.incremental.IncrementalModuleInfo +import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics +import org.jetbrains.kotlin.statistics.metrics.StringMetrics import java.io.File import java.lang.ref.WeakReference @@ -114,6 +114,19 @@ internal open class GradleCompilerRunner(protected val task: Task) { compilerArgs.version = false } val argsArray = ArgumentUtils.convertArgumentsToStringList(compilerArgs).toTypedArray() + + // compilerArgs arguments may have some attributes which are overrided by freeCompilerArguments. + // Here we perform the work which is repeated in compiler in order to obtain correct values. This extra work could be avoided when + // compiler would report metrics by itself via JMX + KotlinBuildStatsService.applyIfInitialised { + if (compilerArgs is K2JVMCompilerArguments) { + val args = K2JVMCompilerArguments() + parseCommandLineArguments(argsArray.toList(), args) + KotlinBuildStatsService.getInstance()?.report(BooleanMetrics.JVM_COMPILER_IR_MODE, args.useIR) + KotlinBuildStatsService.getInstance()?.report(StringMetrics.JVM_DEFAULTS, args.jvmDefault) + } + } + val incrementalCompilationEnvironment = environment.incrementalCompilationEnvironment val modulesInfo = incrementalCompilationEnvironment?.let { buildModulesInfo(project.gradle) } val workArgs = GradleKotlinCompilerWorkArguments( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index dc5bef558c4..14de11dc4f0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -47,6 +47,8 @@ open class KotlinProjectExtension : KotlinSourceSetContainer { val experimental: ExperimentalExtension get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java) + lateinit var coreLibrariesVersion: String + var explicitApi: ExplicitApiMode? = null fun explicitApi() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt new file mode 100644 index 00000000000..97920c0e41c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt @@ -0,0 +1,286 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.internal + +import com.android.build.gradle.TestedExtension +import com.android.build.gradle.api.TestVariant +import com.android.build.gradle.api.UnitTestVariant +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ExternalDependency +import org.gradle.api.tasks.testing.AbstractTestTask +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.junit.JUnitOptions +import org.gradle.api.tasks.testing.junitplatform.JUnitPlatformOptions +import org.gradle.api.tasks.testing.testng.TestNGOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.execution.KotlinAggregateExecutionSource +import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider +import org.jetbrains.kotlin.gradle.plugin.mpp.* +import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil +import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope +import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy +import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope +import org.jetbrains.kotlin.gradle.targets.jvm.JvmCompilationsTestRunSource +import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP +import org.jetbrains.kotlin.gradle.tasks.locateTask +import org.jetbrains.kotlin.gradle.testing.KotlinTaskTestRun +import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName + +internal fun customizeKotlinDependencies(project: Project) { + configureStdlibDefaultDependency(project) + configureKotlinTestDependencies(project) + configureDefaultVersionsResolutionStrategy(project) +} + +private fun configureDefaultVersionsResolutionStrategy(project: Project) { + project.configurations.all { configuration -> + // Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved: + configuration.withDependencies { dependencySet -> + val coreLibrariesVersion = project.kotlinExtension.coreLibrariesVersion + dependencySet.filterIsInstance<ExternalDependency>() + .filter { it.group == KOTLIN_MODULE_GROUP && it.version.isNullOrEmpty() } + .forEach { it.version { constraint -> constraint.require(coreLibrariesVersion) } } + } + } +} + +//region stdlib +internal fun configureStdlibDefaultDependency(project: Project) = project.whenEvaluated { + if (!PropertiesProvider(project).stdlibDefaultDependency) + return@whenEvaluated + + project.kotlinExtension.sourceSets.all { kotlinSourceSet -> + val scope = if (isRelatedToAndroidTestSourceSet(project, kotlinSourceSet)) // AGP deprecates API configurations in test source sets + KotlinDependencyScope.IMPLEMENTATION_SCOPE + else KotlinDependencyScope.API_SCOPE + + val scopeConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope) + + scopeConfiguration.withDependencies { dependencies -> + val sourceSetDependencyConfigurations = + KotlinDependencyScope.values().map { project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, it) } + + val hierarchySourceSetsDependencyConfigurations = kotlinSourceSet.getSourceSetHierarchy().flatMap { hierarchySourceSet -> + if (hierarchySourceSet === kotlinSourceSet) emptyList() else + KotlinDependencyScope.values().map { scope -> + project.sourceSetDependencyConfigurationByScope(hierarchySourceSet, scope) + } + } + + val compilations = CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(kotlinSourceSet) + .filter { it.target !is KotlinMetadataTarget } + val platformTypes = compilations.mapTo(mutableSetOf()) { it.platformType } + + val sourceSetStdlibPlatformType = when { + platformTypes.isEmpty() -> KotlinPlatformType.common + platformTypes.size == 1 -> platformTypes.single() + setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm + else -> KotlinPlatformType.common + } + + val isStdlibAddedByUser = sourceSetDependencyConfigurations + .flatMap { it.allDependencies } + .any { dependency -> dependency.group == KOTLIN_MODULE_GROUP && dependency.name in stdlibModules } + + if (!isStdlibAddedByUser) { + val stdlibModuleName = when (sourceSetStdlibPlatformType) { + KotlinPlatformType.jvm -> stdlibModuleForJvmCompilations(compilations) + KotlinPlatformType.androidJvm -> + if (kotlinSourceSet.name == androidMainSourceSetName(project)) stdlibModuleForJvmCompilations(compilations) else null + KotlinPlatformType.js -> "kotlin-stdlib-js" + KotlinPlatformType.native -> null + KotlinPlatformType.common -> // there's no platform compilation that the source set is default for + "kotlin-stdlib-common" + } + + // If the exact same module is added in the source sets hierarchy, possibly even with a different scope, we don't add it + val moduleAddedInHierarchy = hierarchySourceSetsDependencyConfigurations.any { + it.allDependencies.any { dependency -> dependency.group == KOTLIN_MODULE_GROUP && dependency.name == stdlibModuleName } + } + + if (stdlibModuleName != null && !moduleAddedInHierarchy) + dependencies.add(project.kotlinDependency(stdlibModuleName, project.kotlinExtension.coreLibrariesVersion)) + } + } + } +} + +private fun Project.findAndroidTarget(): KotlinAndroidTarget? { + val kotlinExtension = project.kotlinExtension + return when (kotlinExtension) { + is KotlinMultiplatformExtension -> kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).single() + is KotlinAndroidProjectExtension -> kotlinExtension.target + else -> null + } +} + +private fun androidMainSourceSetName(project: Project): String { + val target = project.findAndroidTarget() ?: error("No Android target found") + return AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(target, "main") +} + +private fun isRelatedToAndroidTestSourceSet(project: Project, kotlinSourceSet: KotlinSourceSet): Boolean { + val androidExtension = project.extensions.findByName("android") as? TestedExtension ?: return false + val androidTarget = project.findAndroidTarget() ?: return false + + if (androidTarget.compilations.any { + (it.androidVariant is UnitTestVariant || it.androidVariant is TestVariant) && it.defaultSourceSet === kotlinSourceSet + } + ) return true + + (androidExtension.testVariants + androidExtension.unitTestVariants).forEach { variant -> + if (variant.sourceSets.any { + kotlinSourceSet.name == AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(androidTarget, it.name) + } + ) return true + } + + return false +} + +private val stdlibModules = setOf("kotlin-stdlib-common", "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-stdlib-js") + +private fun stdlibModuleForJvmCompilations(compilations: Iterable<KotlinCompilation<*>>): String { + val jvmTargets = compilations.map { (it.kotlinOptions as KotlinJvmOptions).jvmTarget } + return if ("1.6" in jvmTargets) "kotlin-stdlib" else "kotlin-stdlib-jdk8" +} +//endregion + +//region kotlin-test +internal fun configureKotlinTestDependencies(project: Project) { + fun isKotlinTestMultiplatformDependency(dependency: Dependency) = + dependency.group == KOTLIN_MODULE_GROUP && dependency.name == KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME + + KotlinDependencyScope.values().forEach { scope -> + val versionOrNullBySourceSet = mutableMapOf<KotlinSourceSet, String?>() + + project.kotlinExtension.sourceSets.all { kotlinSourceSet -> + val configuration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope) + var finalizingDependencies = false + + configuration.dependencies.matching(::isKotlinTestMultiplatformDependency).apply { + firstOrNull()?.let { versionOrNullBySourceSet[kotlinSourceSet] = it.version } + whenObjectRemoved { + if (!finalizingDependencies && !any()) + versionOrNullBySourceSet.remove(kotlinSourceSet) + } + whenObjectAdded { item -> + versionOrNullBySourceSet[kotlinSourceSet] = item.version + } + } + + configuration.withDependencies { dependencies -> + val parentOrOwnVersions: List<String?> = + kotlinSourceSet.getSourceSetHierarchy().filter(versionOrNullBySourceSet::contains).map(versionOrNullBySourceSet::get) + + finalizingDependencies = true + + parentOrOwnVersions.distinct().forEach { version -> // add dependencies with each version and let Gradle disambiguate them + val dependenciesToAdd = kotlinTestDependenciesForSourceSet(project, kotlinSourceSet, version) + dependenciesToAdd.filterIsInstance<ExternalDependency>().forEach { + if (it.version == null) { + it.version { constraint -> constraint.require(project.kotlinExtension.coreLibrariesVersion) } + } + } + dependencies.addAll(dependenciesToAdd) + dependencies.removeIf(::isKotlinTestMultiplatformDependency) + } + } + } + } +} + +private fun kotlinTestDependenciesForSourceSet(project: Project, kotlinSourceSet: KotlinSourceSet, version: String?): List<Dependency> { + val compilations = CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(kotlinSourceSet) + .filter { it.target !is KotlinMetadataTarget } + + val platformTypes = compilations.mapTo(mutableSetOf()) { it.platformType } + + return when { + platformTypes.isEmpty() -> emptyList() + setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> listOf( + kotlinTestDependenciesForJvm(project, compilations, version) + ) + platformTypes.singleOrNull() == KotlinPlatformType.js -> listOf( + project.kotlinDependency("kotlin-test-js", version) + ) + platformTypes.singleOrNull() == KotlinPlatformType.native -> emptyList() + else -> listOf( + project.kotlinDependency("kotlin-test-common", version), + project.kotlinDependency("kotlin-test-annotations-common", version) + ) + } +} + +internal const val KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME = "kotlin-test-multiplatform" + +private fun Project.kotlinDependency(moduleName: String, versionOrNull: String?) = + project.dependencies.create("$KOTLIN_MODULE_GROUP:$moduleName${versionOrNull?.prependIndent(":").orEmpty()}") + +private fun kotlinTestDependenciesForJvm(project: Project, compilations: Iterable<KotlinCompilation<*>>, version: String?): Dependency { + val testTaskLists: List<List<Task>?> = compilations.map { compilation -> + val target = compilation.target + when { + target is KotlinTargetWithTests<*, *> -> + target.findTestRunsByCompilation(compilation)?.filterIsInstance<KotlinTaskTestRun<*, *>>()?.map { it.executionTask.get() } + target is KotlinWithJavaTarget<*> -> + if (compilation.name == KotlinCompilation.TEST_COMPILATION_NAME) + project.locateTask<AbstractTestTask>(target.testTaskName)?.get()?.let(::listOf) + else null + compilation is KotlinJvmAndroidCompilation -> when (compilation.androidVariant) { + is UnitTestVariant -> + project.locateTask<AbstractTestTask>(lowerCamelCaseName("test", compilation.androidVariant.name))?.get()?.let(::listOf) + is TestVariant -> (compilation.androidVariant as TestVariant).connectedInstrumentTest?.let(::listOf) + else -> null + } + else -> null + } + } + if (null in testTaskLists) { + return project.kotlinDependency("kotlin-test", version) + } + val testTasks = testTaskLists.flatMap { checkNotNull(it) } + val frameworks = testTasks.mapTo(mutableSetOf()) { testTask -> + when (testTask) { + is Test -> testFrameworkOf(testTask) + else -> // Android connected test tasks don't inherit from Test, but we use JUnit for them + KotlinTestJvmFramework.junit + } + } + return when { + frameworks.size > 1 -> project.kotlinDependency("kotlin-test", version) + else -> project.kotlinDependency("kotlin-test-${frameworks.single().name}", version) + } +} + +private enum class KotlinTestJvmFramework { + junit, testng, junit5 +} + +private fun testFrameworkOf(testTask: Test): KotlinTestJvmFramework = when (testTask.options) { + is JUnitOptions -> KotlinTestJvmFramework.junit + is JUnitPlatformOptions -> KotlinTestJvmFramework.junit5 + is TestNGOptions -> KotlinTestJvmFramework.testng + else -> // failed to detect, fallback to junit + KotlinTestJvmFramework.junit +} + +private fun KotlinTargetWithTests<*, *>.findTestRunsByCompilation(byCompilation: KotlinCompilation<*>): List<KotlinTargetTestRun<*>>? { + fun KotlinExecution.ExecutionSource.isProducedFromTheCompilation(): Boolean = when (this) { + is CompilationExecutionSource<*> -> compilation == byCompilation + is JvmCompilationsTestRunSource -> byCompilation in testCompilations + is KotlinAggregateExecutionSource<*> -> this.executionSources.any { it.isProducedFromTheCompilation() } + else -> false + } + return testRuns.filter { it.executionSource.isProducedFromTheCompilation() }.takeIf { it.isNotEmpty() } +} +//endregion
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index aa4a1b5a9f5..e8776c19782 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -43,9 +43,7 @@ import javax.inject.Inject // apply plugin: 'kotlin-kapt' class Kapt3GradleSubplugin @Inject internal constructor(private val registry: ToolingModelBuilderRegistry) : - KotlinCompilerPluginSupportPlugin, - @Suppress("DEPRECATION") // implementing to fix KT-39809 - KotlinGradleSubplugin<AbstractCompile> { + KotlinCompilerPluginSupportPlugin { override fun apply(target: Project) { target.extensions.create("kapt", KaptExtension::class.java) @@ -591,20 +589,6 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To override fun getPluginArtifact(): SubpluginArtifact = JetBrainsSubpluginArtifact(artifactId = KAPT_ARTIFACT_NAME) - - //region Stub implementation for legacy API, KT-39809 - internal constructor(): this(object : ToolingModelBuilderRegistry { - override fun register(p0: ToolingModelBuilder) = Unit - override fun getBuilder(p0: String): ToolingModelBuilder? = null - }) - - override fun isApplicable(project: Project, task: AbstractCompile): Boolean = false - - override fun apply( - project: Project, kotlinCompile: AbstractCompile, javaCompile: AbstractCompile?, variantData: Any?, androidProjectHandler: Any?, - kotlinCompilation: KotlinCompilation<KotlinCommonOptions>? - ): List<SubpluginOption> = emptyList() - //endregion } private val artifactType = Attribute.of("artifactType", String::class.java) @@ -708,4 +692,20 @@ private val BaseVariant.dataBindingDependencyArtifactsIfSupported: FileCollectio get() = this::class.java.methods .find { it.name == "getDataBindingDependencyArtifacts" } ?.also { it.isAccessible = true } - ?.invoke(this) as? FileCollection
\ No newline at end of file + ?.invoke(this) as? FileCollection + +//region Stub implementation for legacy API, KT-39809 +@Suppress("DEPRECATION") // implementing to fix KT-39809 +class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> { + override fun isApplicable(project: Project, task: AbstractCompile): Boolean = false + + override fun apply( + project: Project, kotlinCompile: AbstractCompile, javaCompile: AbstractCompile?, variantData: Any?, androidProjectHandler: Any?, + kotlinCompilation: KotlinCompilation<KotlinCommonOptions>? + ): List<SubpluginOption> = emptyList() + + override fun getCompilerPluginId(): String = Kapt3GradleSubplugin.KAPT_SUBPLUGIN_ID + + override fun getPluginArtifact(): SubpluginArtifact = JetBrainsSubpluginArtifact(artifactId = Kapt3GradleSubplugin.KAPT_ARTIFACT_NAME) +} +//endregion diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index dd9322b85d8..39b187d9b2a 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -6,11 +6,8 @@ package org.jetbrains.kotlin.gradle.plugin import com.android.build.gradle.* -import com.android.build.gradle.api.AndroidSourceSet -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.SourceKind +import com.android.build.gradle.api.* import org.gradle.api.* -import org.gradle.api.artifacts.ExternalDependency import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer import org.gradle.api.artifacts.maven.MavenResolver import org.gradle.api.attributes.Usage @@ -32,8 +29,9 @@ import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.jvm.tasks.Jar import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.dsl.* -import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin +import org.jetbrains.kotlin.gradle.internal.* import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage +import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.model.builder.KotlinModelBuilder import org.jetbrains.kotlin.gradle.plugin.mpp.* @@ -412,7 +410,7 @@ internal abstract class AbstractKotlinPlugin( rewriteMppDependenciesInPom(target) - configureProjectGlobalSettings(project, kotlinPluginVersion) + configureProjectGlobalSettings(project) registry.register(KotlinModelBuilder(kotlinPluginVersion, null)) project.components.addAll(target.components) @@ -452,8 +450,8 @@ internal abstract class AbstractKotlinPlugin( } companion object { - fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) { - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + fun configureProjectGlobalSettings(project: Project) { + customizeKotlinDependencies(project) configureClassInspectionForIC(project) project.setupGeneralKotlinExtensionParameters() } @@ -590,17 +588,6 @@ internal abstract class AbstractKotlinPlugin( } } -internal fun configureDefaultVersionsResolutionStrategy(project: Project, kotlinPluginVersion: String) { - project.configurations.all { configuration -> - // Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved: - configuration.withDependencies { dependencySet -> - dependencySet.filterIsInstance<ExternalDependency>() - .filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() } - .forEach { it.version { constraint -> constraint.require(kotlinPluginVersion) } } - } - } -} - internal open class KotlinPlugin( kotlinPluginVersion: String, registry: ToolingModelBuilderRegistry @@ -703,7 +690,7 @@ internal open class KotlinAndroidPlugin( applyUserDefinedAttributes(androidTarget) - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + customizeKotlinDependencies(project) registry.register(KotlinModelBuilder(kotlinPluginVersion, androidTarget)) @@ -748,6 +735,11 @@ class KotlinConfigurationTools internal constructor( ) abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTools: KotlinConfigurationTools) { + companion object { + fun kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget: KotlinAndroidTarget, androidSourceSetName: String) = + lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSetName) + } + protected val logger = Logging.getLogger(this.javaClass) abstract fun getFlavorNames(variant: BaseVariant): List<String> @@ -775,7 +767,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool ext.sourceSets.all { sourceSet -> logger.kotlinDebug("Creating KotlinBaseSourceSet for source set $sourceSet") val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate( - lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, sourceSet.name) + kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, sourceSet.name) ).apply { kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin"))) kotlin.srcDirs(sourceSet.java.srcDirs) @@ -875,7 +867,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool * see [org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.configureTarget] */ (project.extensions.getByName("android") as BaseExtension).sourceSets.forEach { androidSourceSet -> - val kotlinSourceSetName = lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSet.name) + val kotlinSourceSetName = kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, androidSourceSet.name) project.kotlinExtension.sourceSets.findByName(kotlinSourceSetName)?.let { kotlinSourceSet -> addDependenciesToAndroidSourceSet( androidSourceSet, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 0a6f897043f..fefad6cc77c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.gradle.plugin +import org.gradle.api.GradleException import org.gradle.api.NamedDomainObjectFactory import org.gradle.api.Plugin import org.gradle.api.Project @@ -26,6 +27,7 @@ import org.gradle.api.logging.Logging import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.logging.kotlinDebug +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory @@ -36,6 +38,7 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_KLIB_COMMONIZER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP +import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources @@ -60,6 +63,10 @@ abstract class KotlinBasePluginWrapper( checkGradleCompatibility() + project.gradle.projectsEvaluated { + whenBuildEvaluated(project) + } + project.configurations.maybeCreate(COMPILER_CLASSPATH_CONFIGURATION_NAME).defaultDependencies { it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_COMPILER_EMBEDDABLE:$kotlinPluginVersion")) } @@ -78,6 +85,8 @@ abstract class KotlinBasePluginWrapper( kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion) project.createKotlinExtension(projectExtensionClass).apply { + coreLibrariesVersion = kotlinPluginVersion + fun kotlinSourceSetContainer(factory: NamedDomainObjectFactory<KotlinSourceSet>) = project.container(KotlinSourceSet::class.java, factory) @@ -95,6 +104,9 @@ abstract class KotlinBasePluginWrapper( project.addNpmDependencyExtension() } + open fun whenBuildEvaluated(project: Project) { + } + internal open fun createTestRegistry(project: Project) = KotlinTestsRegistry(project) private fun setupAttributeMatchingStrategy(project: Project) = with(project.dependencies.attributesSchema) { @@ -163,6 +175,27 @@ open class KotlinJsPluginWrapper @Inject constructor( override val projectExtensionClass: KClass<out KotlinJsProjectExtension> get() = KotlinJsProjectExtension::class + override fun whenBuildEvaluated(project: Project) { + val isJsTargetUninitialized = (project.kotlinExtension as KotlinJsProjectExtension) + ._target == null + + if (isJsTargetUninitialized) { + throw GradleException( + """ + Please initialize the Kotlin/JS target in '${project.name} (${project.path})'. Use: + kotlin { + js { + // To build distributions and run tests for browser or Node.js use one or both of: + browser() + nodejs() + } + } + Read more https://kotlinlang.org/docs/reference/js-project-setup.html + """.trimIndent() + ) + } + } + override fun createTestRegistry(project: Project) = KotlinTestsRegistry(project, "test") } @@ -178,6 +211,21 @@ open class KotlinMultiplatformPluginWrapper @Inject constructor( override val projectExtensionClass: KClass<out KotlinMultiplatformExtension> get() = KotlinMultiplatformExtension::class + + override fun whenBuildEvaluated(project: Project) { + val isNoTargetsInitialized = (project.kotlinExtension as KotlinMultiplatformExtension) + .targets + .none { it !is KotlinMetadataTarget } + + if (isNoTargetsInitialized) { + throw GradleException( + """ + Please initialize at least one Kotlin target in '${project.name} (${project.path})'. + Read more https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets + """.trimIndent() + ) + } + } } fun Project.getKotlinPluginVersion(): String? = diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt index 918057a0512..60916deb739 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt @@ -202,6 +202,9 @@ internal class PropertiesProvider private constructor(private val project: Proje val jsCompiler: KotlinJsCompilerType get() = property(jsCompilerProperty)?.let { KotlinJsCompilerType.byArgumentOrNull(it) } ?: KotlinJsCompilerType.LEGACY + val stdlibDefaultDependency: Boolean + get() = booleanProperty("kotlin.stdlib.default.dependency") ?: true + private fun propertyWithDeprecatedVariant(propName: String, deprecatedPropName: String): String? { val deprecatedProperty = property(deprecatedPropName) if (deprecatedProperty != null) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt index dddbe39e467..ee51f254cbe 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt @@ -10,6 +10,7 @@ import org.gradle.api.artifacts.* import org.gradle.api.artifacts.component.* import org.gradle.api.artifacts.result.ResolvedComponentResult import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.attributes.Attribute import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet @@ -108,9 +109,14 @@ internal class GranularMetadataTransformation( requestedDependencies.forEach { dependency -> if (dependency !in originalDependencies) { - modifiedConfiguration = (modifiedConfiguration ?: allSourceSetsConfiguration.copyRecursive()).apply { - dependencies.add(dependency) + modifiedConfiguration = modifiedConfiguration ?: project.configurations.detachedConfiguration().apply { + fun <T> copyAttribute(key: Attribute<T>) { + attributes.attribute(key, allSourceSetsConfiguration.attributes.getAttribute(key)!!) + } + allSourceSetsConfiguration.attributes.keySet().forEach { copyAttribute(it) } + allSourceSetsConfiguration.extendsFrom.forEach { extendsFrom(it) } } + modifiedConfiguration!!.dependencies.add(dependency) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 6891f0603bc..37e3ba6d4ab 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.configureOrCreate import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.sourceSetFreeCompilerArgsPropertyName import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder @@ -84,7 +85,7 @@ class KotlinMultiplatformPlugin( } setupDefaultPresets(project) - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + customizeKotlinDependencies(project) configureSourceSets(project) // set up metadata publishing diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt index 1eeea339e4c..da9769e154f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt @@ -21,6 +21,7 @@ import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.internal.component.SoftwareComponentInternal import org.gradle.api.internal.component.UsageContext import org.gradle.api.internal.project.ProjectInternal +import org.gradle.api.provider.Provider import org.gradle.api.publish.maven.MavenPublication import org.gradle.util.ConfigureUtil import org.gradle.util.WrapUtil @@ -98,7 +99,10 @@ abstract class AbstractKotlinTarget( ?: project.configurations.create(kotlinUsageContext.name).also { configuration -> configuration.isCanBeConsumed = false configuration.isCanBeResolved = false - configuration.dependencies.addAll(kotlinUsageContext.dependencies) + /** Add dependencies lazily to avoid freezing the content of the configuration held by [kotlinUsageContext] */ + configuration.withDependencies { dependencies -> + dependencies.addAll(kotlinUsageContext.dependencies) + } configuration.dependencyConstraints.addAll(kotlinUsageContext.dependencyConstraints) configuration.artifacts.addAll(kotlinUsageContext.artifacts) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsService.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsService.kt index 27d54c8cb4c..8bd3f7dc272 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsService.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsService.kt @@ -118,6 +118,23 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd } } + /** + * Invokes provided collector if the reporting service is initialised. + * The duration of collector's wall time is reported into overall overhead metric. + */ + fun applyIfInitialised(collector: (IStatisticsValuesConsumer) -> Unit) { + getInstance()?.apply { + try { + val duration = measureTimeMillis { + collector.invoke(this) + } + this.report(NumericalMetrics.STATISTICS_COLLECT_METRICS_OVERHEAD, duration) + } catch (e: Throwable) { + logException("Could collect statistics metrics", e) + } + } + } + @JvmStatic internal fun getLogger() = Logging.getLogger(KotlinBuildStatsService::class.java) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt index ea3344ca0a8..d6f2c72ee03 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt @@ -10,10 +10,10 @@ import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin import org.jetbrains.kotlin.gradle.dsl.KotlinJsProjectExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.configureDefaultVersionsResolutionStrategy import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsSingleTargetPreset import org.jetbrains.kotlin.gradle.plugin.whenEvaluated import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrSingleTargetPreset @@ -36,7 +36,7 @@ open class KotlinJsPlugin( checkGradleCompatibility() val kotlinExtension = project.kotlinExtension as KotlinJsProjectExtension - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + customizeKotlinDependencies(project) kotlinExtension.apply { irPreset = KotlinJsIrSingleTargetPreset(project, kotlinPluginVersion) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnImportedPackagesVersionResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnImportedPackagesVersionResolver.kt index 07996dd3bdb..ea8dff5f895 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnImportedPackagesVersionResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnImportedPackagesVersionResolver.kt @@ -10,6 +10,7 @@ import org.gradle.api.Project import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModule import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson +import org.jetbrains.kotlin.gradle.targets.js.npm.fileVersion import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution import java.io.File @@ -18,7 +19,7 @@ class YarnImportedPackagesVersionResolver( private val npmProjects: Collection<KotlinCompilationNpmResolution>, private val nodeJsWorldDir: File ) { - private val resolvedVersion = mutableMapOf<String, String>() + private val resolvedVersion = mutableMapOf<String, ResolvedNpmDependency>() private val importedProjectWorkspaces = mutableListOf<String>() private val externalModules = npmProjects.flatMapTo(mutableSetOf()) { it.externalGradleDependencies @@ -48,7 +49,10 @@ class YarnImportedPackagesVersionResolver( "Only latest version will be used." ) val selected = sorted.last() - resolvedVersion[name] = selected.version + resolvedVersion[name] = ResolvedNpmDependency( + version = selected.version, + file = selected.path + ) selected } else versions.single() @@ -89,11 +93,16 @@ class YarnImportedPackagesVersionResolver( var doneSomething = false map.iterator().forEachRemaining { val resolved = resolvedVersion[it.key] - if (resolved != null && it.value != resolved) { - it.setValue(resolved) + if (resolved != null && it.value != resolved.version) { + it.setValue(fileVersion(resolved.file)) doneSomething = true } } return doneSomething } -}
\ No newline at end of file +} + +private data class ResolvedNpmDependency( + val version: String, + val file: File +)
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt index a6fc642114c..fc8d4e9d5e4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt @@ -64,6 +64,7 @@ open class KotlinJvmTestRun(testRunName: String, override val target: KotlinJvmT get() = _executionSource private set(value) { setTestTaskClasspathAndClassesDirs(value.classpath, value.testClassesDirs) + _executionSource = value } private fun setTestTaskClasspathAndClassesDirs(classpath: FileCollection, testClassesDirs: FileCollection) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/AdvancedCocoapodsTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/AdvancedCocoapodsTasks.kt index 95e7e0d15a8..de7c394d0f2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/AdvancedCocoapodsTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/AdvancedCocoapodsTasks.kt @@ -233,6 +233,9 @@ open class PodBuildTask : CocoapodsWithSyntheticTask() { @get:OutputDirectory internal var buildDirProvider: Provider<File>? = null + private val CocoapodsExtension.CocoapodsDependency.schemeName: String + get() = name.split("/")[0] + @TaskAction fun buildDependencies() { val podBuildSettings = PodBuildSettingsProperties.readSettingsFromStream( @@ -246,7 +249,7 @@ open class PodBuildTask : CocoapodsWithSyntheticTask() { val podXcodeBuildCommand = listOf( "xcodebuild", "-project", podsXcodeProjDir.name, - "-scheme", it.moduleName, + "-scheme", it.schemeName, "-sdk", kotlinNativeTarget.toValidSDK, "-configuration", podBuildSettings.configuration ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt index 1cd9ad5d151..a7c224b5349 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt @@ -26,3 +26,5 @@ const val NO_NATIVE_STDLIB_WARNING = NO_NATIVE_STDLIB_WARNING const val NO_NATIVE_STDLIB_PROPERTY_WARNING = NO_NATIVE_STDLIB_PROPERTY_WARNING val KOTLIN_12X_MPP_DEPRECATION_WARNING = KOTLIN_12X_MPP_DEPRECATION_WARNING + +const val KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME = org.jetbrains.kotlin.gradle.internal.KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME
\ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/BooleanMetrics.kt b/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/BooleanMetrics.kt index 9b37cbf99cc..5bbecbc6c26 100644 --- a/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/BooleanMetrics.kt +++ b/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/BooleanMetrics.kt @@ -36,6 +36,7 @@ enum class BooleanMetrics(val type: BooleanOverridePolicy, val anonymization: Bo KOTLIN_OFFICIAL_CODESTYLE(OVERRIDE, SAFE), KOTLIN_PROGRESSIVE_MODE(OVERRIDE, SAFE), KOTLIN_KTS_USED(OR, SAFE), + JVM_COMPILER_IR_MODE(OR, SAFE), // User scenarios DEBUGGER_ENABLED(OVERRIDE, SAFE), diff --git a/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/NumericalMetrics.kt b/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/NumericalMetrics.kt index a5afa5ab84b..93f3dacb9c0 100644 --- a/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/NumericalMetrics.kt +++ b/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/NumericalMetrics.kt @@ -48,6 +48,7 @@ enum class NumericalMetrics(val type: NumberOverridePolicy, val anonymization: N NUMBER_OF_SUBPROJECTS(SUM, RANDOM_10_PERCENT), STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD(SUM, RANDOM_10_PERCENT), + STATISTICS_COLLECT_METRICS_OVERHEAD(SUM, RANDOM_10_PERCENT), // User scenarios diff --git a/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt b/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt index b59b121678d..f4e52e31013 100644 --- a/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt +++ b/libraries/tools/kotlin-gradle-statistics/src/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt @@ -40,4 +40,7 @@ enum class StringMetrics(val type: StringOverridePolicy, val anonymization: Stri // Features KOTLIN_LANGUAGE_VERSION(OVERRIDE, COMPONENT_VERSION), KOTLIN_API_VERSION(OVERRIDE, COMPONENT_VERSION), + + // Compiler parameters + JVM_DEFAULTS(CONCAT, SAFE), } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle index c19d278c52b..ebfea74756a 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle @@ -11,6 +11,9 @@ repositories { url 'https://dl.bintray.com/kotlin/kotlin-dev' } maven { + url 'https://dl.bintray.com/kotlin/kotlinx' + } + maven { url 'https://dl.bintray.com/kotlin/kotlin-js-wrappers' } } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle.kts b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle.kts index a69262774d4..baaa91b5b44 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle.kts +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/frontendApplication/build.gradle.kts @@ -11,6 +11,9 @@ repositories { url = uri("https://dl.bintray.com/kotlin/kotlin-dev") } maven { + url = uri("https://dl.bintray.com/kotlin/kotlinx") + } + maven { url = uri("https://dl.bintray.com/kotlin/kotlin-js-wrappers") } } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle index d82476d9dd0..12d2d266693 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle @@ -17,6 +17,9 @@ repositories { url 'https://dl.bintray.com/kotlin/kotlin-dev' } maven { + url 'https://dl.bintray.com/kotlin/kotlinx' + } + maven { url 'https://dl.bintray.com/kotlin/kotlin-js-wrappers' } } @@ -59,8 +62,8 @@ kotlin { jvmMain { dependencies { implementation kotlin('stdlib-jdk8') - implementation 'io.ktor:ktor-server-netty:1.2.6' - implementation 'io.ktor:ktor-html-builder:1.2.6' + implementation 'io.ktor:ktor-server-netty:1.3.2-KOTLIN_VERSION' + implementation 'io.ktor:ktor-html-builder:1.3.2-KOTLIN_VERSION' implementation 'org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.1-KOTLIN_VERSION' } } diff --git a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle.kts b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle.kts index ff4bd81229e..30c2562b4d2 100644 --- a/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle.kts +++ b/libraries/tools/new-project-wizard/new-project-wizard-cli/testData/projectTemplatesBuildFileGeneration/fullStackWebApplication/build.gradle.kts @@ -17,6 +17,9 @@ repositories { url = uri("https://dl.bintray.com/kotlin/kotlin-dev") } maven { + url = uri("https://dl.bintray.com/kotlin/kotlinx") + } + maven { url = uri("https://dl.bintray.com/kotlin/kotlin-js-wrappers") } } @@ -59,8 +62,8 @@ kotlin { val jvmMain by getting { dependencies { implementation(kotlin("stdlib-jdk8")) - implementation("io.ktor:ktor-server-netty:1.2.6") - implementation("io.ktor:ktor-html-builder:1.2.6") + implementation("io.ktor:ktor-server-netty:1.3.2-KOTLIN_VERSION") + implementation("io.ktor:ktor-html-builder:1.3.2-KOTLIN_VERSION") implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.1-KOTLIN_VERSION") } } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt index c95cbaf71d0..2262bd9284a 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/Versions.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version object Versions { val KOTLIN = version("1.4-M1") // used as fallback version val GRADLE = version("6.3") - val KTOR = version("1.2.6") + val KTOR: (kotlinVersion: Version) -> Version = { kotlinVersion -> version("1.3.2-$kotlinVersion") } object ANDROID { val ANDROIDX_CORE_KTX = version("1.2.0") diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/KotlinVersionProviderService.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/KotlinVersionProviderService.kt index 5d3f325c687..8fb46348f69 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/KotlinVersionProviderService.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/KotlinVersionProviderService.kt @@ -43,6 +43,7 @@ abstract class KotlinVersionProviderService : WizardService { private fun getKotlinVersionKind(version: Version) = when { "eap" in version.toString().toLowerCase() -> KotlinVersionKind.EAP + "rc" in version.toString().toLowerCase() -> KotlinVersionKind.EAP "dev" in version.toString().toLowerCase() -> KotlinVersionKind.DEV "m" in version.toString().toLowerCase() -> KotlinVersionKind.M else -> KotlinVersionKind.STABLE diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt index 829f7f28bda..bf142e57574 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/settings/buildsystem/Repository.kt @@ -39,6 +39,7 @@ data class BintrayRepository(val repository: String, val base: String = "https:/ object Repositories { val KTOR_BINTRAY = BintrayRepository("kotlin/ktor") + val KOTLINX = BintrayRepository("kotlin/kotlinx") val KOTLIN_JS_WRAPPERS_BINTRAY = BintrayRepository("kotlin/kotlin-js-wrappers") val KOTLIN_EAP_BINTRAY = BintrayRepository("kotlin/kotlin-eap") val KOTLIN_DEV_BINTRAY = BintrayRepository("kotlin/kotlin-dev") diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt index 5e2dc444bf5..b62c96b2a35 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/KtorServerTemplate.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.tools.projectWizard.WizardRunConfiguration import org.jetbrains.kotlin.tools.projectWizard.core.Reader import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind +import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version class KtorServerTemplate : Template() { override val title: String = KotlinNewProjectWizardBundle.message("module.template.ktor.server.title") @@ -40,11 +41,12 @@ class KtorServerTemplate : Template() { override fun Writer.getRequiredLibraries(module: ModuleIR): List<DependencyIR> = withSettingsOf(module.originalModule) { + val kotlinVersion = KotlinPlugin::version.propertyValue.version buildList { - +ktorArtifactDependency(serverEngine.reference.settingValue.dependencyName) - +ktorArtifactDependency("ktor-html-builder") + +ktorArtifactDependency(serverEngine.reference.settingValue.dependencyName, kotlinVersion) + +ktorArtifactDependency("ktor-html-builder", kotlinVersion) +ArtifactBasedLibraryDependencyIR( - MavenArtifact(DefaultRepository.JCENTER, "org.jetbrains.kotlinx", "kotlinx-html-jvm"), + MavenArtifact(Repositories.KOTLINX, "org.jetbrains.kotlinx", "kotlinx-html-jvm"), Versions.KOTLINX.KOTLINX_HTML(KotlinPlugin::version.propertyValue.version), DependencyType.MAIN ) @@ -81,9 +83,9 @@ class KtorServerTemplate : Template() { override val settings: List<TemplateSetting<*, *>> = listOf(serverEngine) } -private fun ktorArtifactDependency(@NonNls name: String) = ArtifactBasedLibraryDependencyIR( +private fun ktorArtifactDependency(@NonNls name: String, kotlinVersion: Version) = ArtifactBasedLibraryDependencyIR( MavenArtifact(Repositories.KTOR_BINTRAY, "io.ktor", name), - Versions.KTOR, + Versions.KTOR(kotlinVersion), DependencyType.MAIN ) diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleJsClientTemplate.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleJsClientTemplate.kt index 9f916799e8b..7c55b0564cb 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleJsClientTemplate.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/SimpleJsClientTemplate.kt @@ -71,7 +71,7 @@ class SimpleJsClientTemplate : Template() { override fun Writer.getRequiredLibraries(module: ModuleIR): List<DependencyIR> = withSettingsOf(module.originalModule) { buildList { +ArtifactBasedLibraryDependencyIR( - MavenArtifact(DefaultRepository.JCENTER, "org.jetbrains.kotlinx", "kotlinx-html-js"), + MavenArtifact(Repositories.KOTLINX, "org.jetbrains.kotlinx", "kotlinx-html-js"), Versions.KOTLINX.KOTLINX_HTML(KotlinPlugin::version.propertyValue.version), DependencyType.MAIN ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt index 8efebf44abc..5b87fac3811 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt @@ -31,5 +31,5 @@ interface ModulesProvider { class ModuleInfo(val name: String, val originalLocation: File) fun loadModuleInfos(): Map<String, ModuleInfo> - fun loadModules(): Collection<ModuleDescriptor> + fun loadModules(): Map<String, ModuleDescriptor> } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt index aacb3cdc1e3..85cfdc7bdce 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt @@ -5,13 +5,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.utils.concat -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.constants.AnnotationValue import org.jetbrains.kotlin.storage.getValue @@ -19,14 +16,8 @@ class CommonizedAnnotationDescriptor( targetComponents: TargetDeclarationsBuilderComponents, cirAnnotation: CirAnnotation ) : AnnotationDescriptor { - override val fqName: FqName = cirAnnotation.fqName - override val type by targetComponents.storageManager.createLazyValue { - val annotationClass = findClassOrTypeAlias(targetComponents, fqName) - check(annotationClass is ClassDescriptor && annotationClass.kind == ANNOTATION_CLASS) { - "Not an annotation class: ${annotationClass::class.java}, $annotationClass" - } - annotationClass.defaultType + cirAnnotation.type.buildType(targetComponents, TypeParameterResolver.EMPTY) } override val allValueArguments by targetComponents.storageManager.createLazyValue { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor2.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor2.kt index 00ac861a6f1..37e86ce2359 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor2.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/DeclarationsBuilderVisitor2.kt @@ -80,7 +80,7 @@ internal class DeclarationsBuilderVisitor2( } override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { - val classes = components.cache.getCachedClasses(node.fqName) + val classes = components.cache.getCachedClasses(node.classId) // build class constructors: val allConstructorsByTargets = Array<MutableList<CommonizedClassConstructorDescriptor>>(node.dimension) { ArrayList() } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt index 0a2379e81b7..b6e5b894e85 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt @@ -8,13 +8,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.commonizer.cir.* -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.Companion.areCompatible -import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.cirSimpleTypeKind import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages -import org.jetbrains.kotlin.descriptors.commonizer.utils.resolveClassOrTypeAliasByFqName import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.* @@ -106,17 +101,26 @@ internal fun CirSimpleType.buildType( targetComponents: TargetDeclarationsBuilderComponents, typeParameterResolver: TypeParameterResolver ): SimpleType { - val classifier: ClassifierDescriptor = when (kind) { - - CirSimpleTypeKind.TYPE_PARAMETER -> { - typeParameterResolver.resolve(fqName.shortName()) - ?: error("Type parameter $fqName not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}") + val classifier: ClassifierDescriptor = when (val classifierId = classifierId) { + is CirClassifierId.Class -> { + targetComponents.findClassOrTypeAlias(classifierId.classId).checkClassifierType<ClassDescriptor>() } - - CirSimpleTypeKind.CLASS, CirSimpleTypeKind.TYPE_ALIAS -> { - val classOrTypeAlias = findClassOrTypeAlias(targetComponents, fqName) - checkClassifier(classOrTypeAlias, kind, fqName.isUnderStandardKotlinPackages || !targetComponents.isCommon) - classOrTypeAlias + is CirClassifierId.TypeAlias -> { + val classId = classifierId.classId + val classOrTypeAlias: ClassifierDescriptorWithTypeParameters = targetComponents.findClassOrTypeAlias(classId) + + if (classId.packageFqName.isUnderStandardKotlinPackages || !targetComponents.isCommon) { + // classifier type could be only type alias + classOrTypeAlias.checkClassifierType<TypeAliasDescriptor>() + } else { + // classifier could be class or type alias + classOrTypeAlias + } + } + is CirClassifierId.TypeParameter -> { + val name = classifierId.name + typeParameterResolver.resolve(name) + ?: error("Type parameter $name not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}") } } @@ -129,7 +133,7 @@ internal fun CirSimpleType.buildType( ) val computedType = if (classifier is TypeAliasDescriptor) - classifier.underlyingType.withAbbreviation(simpleType) + classifier.underlyingType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType) else simpleType @@ -139,38 +143,9 @@ internal fun CirSimpleType.buildType( computedType } -internal fun findClassOrTypeAlias( - targetComponents: TargetDeclarationsBuilderComponents, - fqName: FqName -): ClassifierDescriptorWithTypeParameters = when { - fqName.isUnderStandardKotlinPackages -> { - // look up for classifier in built-ins module: - val builtInsModule = targetComponents.builtIns.builtInsModule - - // TODO: this works fine for Native as far as built-ins module contains full Native stdlib, but this is not enough for JVM and JS - builtInsModule.resolveClassOrTypeAliasByFqName(fqName, NoLookupLocation.FOR_ALREADY_TRACKED) - ?: error("Classifier $fqName not found in built-ins module $builtInsModule for ${targetComponents.target}") - } - - else -> { - // otherwise, find the appropriate user classifier: - targetComponents.findAppropriateClassOrTypeAlias(fqName) - ?: error("Classifier $fqName not found in created descriptors cache for ${targetComponents.target}") - } -} - -private fun checkClassifier(classifier: ClassifierDescriptor, kind: CirSimpleTypeKind, strict: Boolean) { - val classifierKind = classifier.cirSimpleTypeKind - - if (strict) { - check(kind == classifierKind) { - "Mismatched classifier kinds.\nFound: $classifierKind, ${classifier::class.java}, $classifier\nShould be: $kind" - } - } else { - check(areCompatible(classifierKind, kind)) { - "Incompatible classifier kinds.\nExpect: $classifierKind, ${classifier::class.java}, $classifier\nActual: $kind" - } - } +private inline fun <reified T : ClassifierDescriptorWithTypeParameters> ClassifierDescriptorWithTypeParameters.checkClassifierType(): T { + check(this is T) { "Mismatched classifier kinds.\nFound: ${this::class.java}, $this\nShould be: ${T::class.java}" } + return this } private fun CirTypeProjection.buildArgument( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt index 70d0182d198..dfaebf7dea2 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassConstructo import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId internal fun CirClassNode.buildDescriptors( components: GlobalDeclarationsBuilderComponents, @@ -26,10 +26,10 @@ internal fun CirClassNode.buildDescriptors( val markAsActual = commonClass != null && commonClass.kind != ClassKind.ENUM_ENTRY targetDeclarations.forEachIndexed { index, clazz -> - clazz?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual) + clazz?.buildDescriptor(components, output, index, containingDeclarations, classId, isActual = markAsActual) } - commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true) + commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId, isExpect = true) // log stats components.statsCollector?.logStats(output) @@ -40,7 +40,7 @@ internal fun CirClass.buildDescriptor( output: CommonizedGroup<in ClassifierDescriptorWithTypeParameters>, index: Int, containingDeclarations: List<DeclarationDescriptor?>, - fqName: FqName, + classId: ClassId, isExpect: Boolean = false, isActual: Boolean = false ) { @@ -63,12 +63,12 @@ internal fun CirClass.buildDescriptor( isExpect = isExpect, isActual = isActual, cirDeclaredTypeParameters = typeParameters, - companionObjectName = companion?.shortName(), + companionObjectName = companion, cirSupertypes = supertypes ) // cache created class descriptor: - components.cache.cache(fqName, index, classDescriptor) + components.cache.cache(classId, index, classDescriptor) output[index] = classDescriptor } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt index f596ba470fd..eb53e83f625 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder +import gnu.trove.THashMap import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.commonizer.Parameters @@ -13,14 +14,15 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion. import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector -import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup +import org.jetbrains.kotlin.descriptors.commonizer.utils.* import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroupMap import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.storage.NotNullLazyValue import org.jetbrains.kotlin.storage.StorageManager /** @@ -33,8 +35,8 @@ class DeclarationsBuilderCache(private val dimension: Int) { private val modules = CommonizedGroup<List<ModuleDescriptorImpl>>(dimension) private val packageFragments = CommonizedGroupMap<Pair<Name, FqName>, CommonizedPackageFragmentDescriptor>(dimension) - private val classes = CommonizedGroupMap<FqName, CommonizedClassDescriptor>(dimension) - private val typeAliases = CommonizedGroupMap<FqName, CommonizedTypeAliasDescriptor>(dimension) + private val classes = CommonizedGroupMap<ClassId, CommonizedClassDescriptor>(dimension) + private val typeAliases = CommonizedGroupMap<ClassId, CommonizedTypeAliasDescriptor>(dimension) private val forwardDeclarationsModules = CommonizedGroup<ModuleDescriptorImpl>(dimension) private val allModulesWithDependencies = CommonizedGroup<List<ModuleDescriptor>>(dimension) @@ -42,15 +44,15 @@ class DeclarationsBuilderCache(private val dimension: Int) { fun getCachedPackageFragments(moduleName: Name, packageFqName: FqName): List<CommonizedPackageFragmentDescriptor?> = packageFragments.getOrFail(moduleName to packageFqName) - fun getCachedClasses(fqName: FqName): List<CommonizedClassDescriptor?> = classes.getOrFail(fqName) + fun getCachedClasses(classId: ClassId): List<CommonizedClassDescriptor?> = classes.getOrFail(classId) - fun getCachedClassifier(fqName: FqName, index: Int): ClassifierDescriptorWithTypeParameters? { + fun getCachedClassifier(classId: ClassId, index: Int): ClassifierDescriptorWithTypeParameters? { // first, look up for class - val classes: CommonizedGroup<CommonizedClassDescriptor>? = classes.getOrNull(fqName) + val classes: CommonizedGroup<CommonizedClassDescriptor>? = classes.getOrNull(classId) classes?.get(index)?.let { return it } // then, for type alias - val typeAliases: CommonizedGroup<CommonizedTypeAliasDescriptor>? = typeAliases.getOrNull(fqName) + val typeAliases: CommonizedGroup<CommonizedTypeAliasDescriptor>? = typeAliases.getOrNull(classId) typeAliases?.get(index)?.let { return it } val indexOfCommon = dimension - 1 @@ -73,12 +75,12 @@ class DeclarationsBuilderCache(private val dimension: Int) { packageFragments[moduleName to packageFqName][index] = descriptor } - fun cache(fqName: FqName, index: Int, descriptor: CommonizedClassDescriptor) { - classes[fqName][index] = descriptor + fun cache(classId: ClassId, index: Int, descriptor: CommonizedClassDescriptor) { + classes[classId][index] = descriptor } - fun cache(fqName: FqName, index: Int, descriptor: CommonizedTypeAliasDescriptor) { - typeAliases[fqName][index] = descriptor + fun cache(classId: ClassId, index: Int, descriptor: CommonizedTypeAliasDescriptor) { + typeAliases[classId][index] = descriptor } fun getOrPutForwardDeclarationsModule(index: Int, computable: () -> ModuleDescriptorImpl): ModuleDescriptorImpl { @@ -131,36 +133,56 @@ class TargetDeclarationsBuilderComponents( val storageManager: StorageManager, val target: Target, val builtIns: KotlinBuiltIns, + val lazyModulesLookupTable: NotNullLazyValue<MutableMap<String, ModuleDescriptor?>>, val isCommon: Boolean, val index: Int, private val cache: DeclarationsBuilderCache ) { // N.B. this function may create new classifiers for types from Kotlin/Native forward declarations packages - fun findAppropriateClassOrTypeAlias(fqName: FqName): ClassifierDescriptorWithTypeParameters? { - - return if (fqName.isUnderKotlinNativeSyntheticPackages) { - // that's a synthetic Kotlin/Native classifier that was exported as forward declaration in one or more modules, - // but did not match any existing class or typealias - val module = cache.getOrPutForwardDeclarationsModule(index) { - // N.B. forward declarations module is created only on demand - createKotlinNativeForwardDeclarationsModule( - storageManager = storageManager, - builtIns = builtIns - ) + fun findClassOrTypeAlias(classId: ClassId): ClassifierDescriptorWithTypeParameters { + return when { + classId.packageFqName.isUnderStandardKotlinPackages -> { + // look up for classifier in built-ins module: + val builtInsModule = builtIns.builtInsModule + + // TODO: this works fine for Native as far as built-ins module contains full Native stdlib, but this is not enough for JVM and JS + builtInsModule.resolveClassOrTypeAlias(classId) + ?: error("Classifier ${classId.asString()} not found in built-ins module $builtInsModule for $target") + } + classId.packageFqName.isUnderKotlinNativeSyntheticPackages -> { + // that's a synthetic Kotlin/Native classifier that was exported as forward declaration in one or more modules, + // but did not match any existing class or typealias + cache.getOrPutForwardDeclarationsModule(index) { + // N.B. forward declarations module is created only on demand + createKotlinNativeForwardDeclarationsModule( + storageManager = storageManager, + builtIns = builtIns + ) + }.resolveClassOrTypeAlias(classId) + ?: error("Classifier ${classId.asString()} not found for $target") + } + else -> { + // look up in created descriptors cache + val fromCache = cache.getCachedClassifier(classId, index) + fromCache + ?: run { + // attempt to load the original classifier + if (!classId.packageFqName.isRoot) { + // first, guess containing module and look up in it + val classifier = lazyModulesLookupTable() + .guessModuleByPackageFqName(classId.packageFqName) + ?.resolveClassOrTypeAlias(classId) + + // if failed, then look up though all modules + classifier + ?: lazyModulesLookupTable().values + .asSequence() + .mapNotNull { it?.resolveClassOrTypeAlias(classId) } + .firstOrNull() + } else null + } + ?: error("Classifier ${classId.asString()} not found for $target") } - - // create and return new classifier - module.packageFragmentProvider - .getPackageFragments(fqName.parent()) - .single() - .getMemberScope() - .getContributedClassifier( - name = fqName.shortName(), - location = NoLookupLocation.FOR_ALREADY_TRACKED - ) as ClassifierDescriptorWithTypeParameters - } else { - // look up in created descriptors cache - cache.getCachedClassifier(fqName, index) } } } @@ -173,6 +195,8 @@ fun CirRootNode.createGlobalBuilderComponents( val targetContexts = (0 until dimension).map { index -> val isCommon = index == indexOfCommon + + // do not leak root inside of createLazyValue {} closures!! val root = if (isCommon) commonDeclaration()!! else targetDeclarations[index]!! val builtIns = root.builtInsProvider.loadBuiltIns() @@ -180,10 +204,16 @@ fun CirRootNode.createGlobalBuilderComponents( "Unexpected built-ins class: ${builtIns::class.java}, $builtIns\nExpected: ${root.builtInsClass}" } + val lazyModulesLookupTable = storageManager.createLazyValue { + val source = if (isCommon) emptyMap() else parameters.targetProviders[index].modulesProvider.loadModules() + THashMap(source) + } + TargetDeclarationsBuilderComponents( storageManager = storageManager, target = root.target, builtIns = builtIns, + lazyModulesLookupTable = lazyModulesLookupTable, isCommon = isCommon, index = index, cache = cache diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt index f1fe9372ce6..185f06f766a 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId internal fun CirTypeAliasNode.buildDescriptors( components: GlobalDeclarationsBuilderComponents, @@ -29,14 +29,14 @@ internal fun CirTypeAliasNode.buildDescriptors( if (!isLiftedUp) { targetDeclarations.forEachIndexed { index, typeAlias -> - typeAlias?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual) + typeAlias?.buildDescriptor(components, output, index, containingDeclarations, classId, isActual = markAsActual) } } if (commonTypeAlias != null) { - commonTypeAlias.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName) + commonTypeAlias.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId) } else if (commonClassifier != null && commonClassifier is CirClass) { - commonClassifier.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true) + commonClassifier.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId, isExpect = true) } // log stats @@ -48,7 +48,7 @@ private fun CirTypeAlias.buildDescriptor( output: CommonizedGroup<ClassifierDescriptorWithTypeParameters>, index: Int, containingDeclarations: List<DeclarationDescriptor?>, - fqName: FqName, + classId: ClassId, isActual: Boolean = false ) { val targetComponents = components.targetComponents[index] @@ -77,7 +77,7 @@ private fun CirTypeAlias.buildDescriptor( ) // cache created type alias descriptor: - components.cache.cache(fqName, index, typeAliasDescriptor) + components.cache.cache(classId, index, typeAliasDescriptor) output[index] = typeAliasDescriptor } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt index 69d4a6f3462..0025b1e847f 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirAnnotation.kt @@ -8,7 +8,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue -interface CirAnnotation : CirHasFqName { +interface CirAnnotation { + val type: CirSimpleType val constantValueArguments: Map<Name, ConstantValue<*>> val annotationValueArguments: Map<Name, CirAnnotation> } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt index 7c46f0b168d..3cbf040122f 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClass.kt @@ -6,11 +6,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name interface CirClass : CirClassifier, CirHasModality { val kind: ClassKind - var companion: FqName? // null means no companion object + var companion: Name? // null means no companion object val isCompanion: Boolean val isData: Boolean val isInline: Boolean diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt new file mode 100644 index 00000000000..c9a5992c755 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirClassifierId.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.descriptors.commonizer.cir + +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +sealed class CirClassifierId { + interface ClassOrTypeAlias { + val classId: ClassId + } + + data class Class(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId() + data class TypeAlias(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId() + data class TypeParameter(val name: Name) : CirClassifierId() +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt index c6af9a94e3c..4ffc1b716e1 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/CirType.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.CLASS -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.TYPE_ALIAS import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.Variance @@ -26,24 +24,11 @@ sealed class CirType { * * Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost. */ -abstract class CirSimpleType : CirType(), CirHasVisibility, CirHasFqName { - abstract val kind: CirSimpleTypeKind +abstract class CirSimpleType : CirType(), CirHasVisibility { + abstract val classifierId: CirClassifierId abstract val arguments: List<CirTypeProjection> abstract val isMarkedNullable: Boolean abstract val isDefinitelyNotNullType: Boolean - - inline val isClassOrTypeAlias: Boolean get() = (kind == CLASS || kind == TYPE_ALIAS) -} - -enum class CirSimpleTypeKind { - CLASS, - TYPE_ALIAS, - TYPE_PARAMETER; - - companion object { - fun areCompatible(expect: CirSimpleTypeKind, actual: CirSimpleTypeKind): Boolean = - expect == actual || (expect == CLASS && actual == TYPE_ALIAS) - } } data class CirTypeProjection(val projectionKind: Variance, val isStarProjection: Boolean, val type: CirType) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt index acfec12f18e..226fd087fe6 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirAnnotationFactory.kt @@ -8,11 +8,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory import gnu.trove.THashMap import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirAnnotationImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner import org.jetbrains.kotlin.descriptors.commonizer.utils.checkConstantSupportedInCommonization import org.jetbrains.kotlin.descriptors.commonizer.utils.intern -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.AnnotationValue import org.jetbrains.kotlin.resolve.constants.ConstantValue @@ -21,11 +21,11 @@ object CirAnnotationFactory { private val interner = Interner<CirAnnotation>() fun create(source: AnnotationDescriptor): CirAnnotation { - val fqName: FqName = source.fqName?.intern() ?: error("Annotation with no FQ name: ${source::class.java}, $source") + val type = CirTypeFactory.create(source.type) as CirSimpleType val allValueArguments: Map<Name, ConstantValue<*>> = source.allValueArguments if (allValueArguments.isEmpty()) - return create(fqName = fqName, constantValueArguments = emptyMap(), annotationValueArguments = emptyMap()) + return create(type = type, constantValueArguments = emptyMap(), annotationValueArguments = emptyMap()) val constantValueArguments: MutableMap<Name, ConstantValue<*>> = THashMap() val annotationValueArguments: MutableMap<Name, CirAnnotation> = THashMap() @@ -45,20 +45,20 @@ object CirAnnotationFactory { } return create( - fqName = fqName, + type = type, constantValueArguments = constantValueArguments, annotationValueArguments = annotationValueArguments ) } fun create( - fqName: FqName, + type: CirSimpleType, constantValueArguments: Map<Name, ConstantValue<*>>, annotationValueArguments: Map<Name, CirAnnotation> ): CirAnnotation { return interner.intern( CirAnnotationImpl( - fqName = fqName, + type = type, constantValueArguments = constantValueArguments, annotationValueArguments = annotationValueArguments ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassFactory.kt index cd0b9496cad..ac37c79ed86 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassFactory.kt @@ -15,9 +15,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.intern -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe object CirClassFactory { fun create(source: ClassDescriptor): CirClass = create( @@ -27,7 +25,7 @@ object CirClassFactory { visibility = source.visibility, modality = source.modality, kind = source.kind, - companion = source.companionObjectDescriptor?.fqNameSafe?.intern(), + companion = source.companionObjectDescriptor?.name?.intern(), isCompanion = source.isCompanionObject, isData = source.isData, isInline = source.isInline, @@ -44,7 +42,7 @@ object CirClassFactory { visibility: Visibility, modality: Modality, kind: ClassKind, - companion: FqName?, + companion: Name?, isCompanion: Boolean, isData: Boolean, isInline: Boolean, diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt new file mode 100644 index 00000000000..112bb457f1c --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirClassifierIdFactory.kt @@ -0,0 +1,30 @@ +package org.jetbrains.kotlin.descriptors.commonizer.cir.factory + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId +import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner +import org.jetbrains.kotlin.descriptors.commonizer.utils.intern +import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +@Suppress("MemberVisibilityCanBePrivate") +object CirClassifierIdFactory { + private val interner = Interner<CirClassifierId>() + + fun create(source: ClassifierDescriptor): CirClassifierId { + return when (source) { + is ClassDescriptor -> createForClass(source.internedClassId) + is TypeAliasDescriptor -> createForTypeAlias(source.internedClassId) + is TypeParameterDescriptor -> createForTypeParameter(source.name.intern()) + else -> error("Unexpected classifier descriptor type: ${source::class.java}, $this") + } + } + + fun createForClass(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.Class(classId)) + fun createForTypeAlias(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.TypeAlias(classId)) + fun createForTypeParameter(name: Name): CirClassifierId = interner.intern(CirClassifierId.TypeParameter(name)) +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPackageFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPackageFactory.kt index daa68a42a41..b7b2d1898ef 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPackageFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirPackageFactory.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackage import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPackageImpl -import org.jetbrains.kotlin.descriptors.commonizer.utils.intern import org.jetbrains.kotlin.name.FqName object CirPackageFactory { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt index aa2e41a1566..5715a763ce7 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/factory/CirTypeFactory.kt @@ -5,13 +5,14 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.commonizer.cir.* -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind.* import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirSimpleTypeImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner import org.jetbrains.kotlin.descriptors.commonizer.utils.declarationDescriptor -import org.jetbrains.kotlin.descriptors.commonizer.utils.fqNameInterned import org.jetbrains.kotlin.descriptors.commonizer.utils.fqNameWithTypeParameters import org.jetbrains.kotlin.types.* @@ -29,10 +30,9 @@ object CirTypeFactory { val abbreviation: SimpleType = (source as? AbbreviatedType)?.abbreviation ?: source val classifierDescriptor: ClassifierDescriptor = abbreviation.declarationDescriptor - val simpleType = CirSimpleTypeImpl( - kind = classifierDescriptor.cirSimpleTypeKind, + return create( + classifierId = CirClassifierIdFactory.create(classifierDescriptor), visibility = (classifierDescriptor as? ClassifierDescriptorWithTypeParameters)?.visibility ?: Visibilities.UNKNOWN, - fqName = abbreviation.fqNameInterned, arguments = abbreviation.arguments.map { projection -> CirTypeProjection( projectionKind = projection.projectionKind, @@ -44,15 +44,25 @@ object CirTypeFactory { isDefinitelyNotNullType = abbreviation.isDefinitelyNotNullType, fqNameWithTypeParameters = source.fqNameWithTypeParameters ) - - return interner.intern(simpleType) } -} -val ClassifierDescriptor.cirSimpleTypeKind: CirSimpleTypeKind - get() = when (this) { - is ClassDescriptor -> CLASS - is TypeAliasDescriptor -> TYPE_ALIAS - is TypeParameterDescriptor -> TYPE_PARAMETER - else -> error("Unexpected classifier descriptor type: ${this::class.java}, $this") + fun create( + classifierId: CirClassifierId, + visibility: Visibility, + arguments: List<CirTypeProjection>, + isMarkedNullable: Boolean, + isDefinitelyNotNullType: Boolean, + fqNameWithTypeParameters: String + ): CirSimpleType { + return interner.intern( + CirSimpleTypeImpl( + classifierId = classifierId, + visibility = visibility, + arguments = arguments, + isMarkedNullable = isMarkedNullable, + isDefinitelyNotNullType = isDefinitelyNotNullType, + fqNameWithTypeParameters = fqNameWithTypeParameters + ) + ) } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt index 6565164b389..db9bc13945d 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirAnnotationImpl.kt @@ -6,21 +6,21 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue data class CirAnnotationImpl( - override val fqName: FqName, + override val type: CirSimpleType, override val constantValueArguments: Map<Name, ConstantValue<*>>, override val annotationValueArguments: Map<Name, CirAnnotation> ) : CirAnnotation { // See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode private var cachedHashCode = 0 - private fun computeHashCode() = hashCode(fqName) + private fun computeHashCode() = hashCode(type) .appendHashCode(constantValueArguments) .appendHashCode(annotationValueArguments) @@ -37,7 +37,7 @@ data class CirAnnotationImpl( if (other === this) return true return other is CirAnnotation - && fqName == other.fqName + && type == other.type && constantValueArguments == other.constantValueArguments && annotationValueArguments == other.annotationValueArguments } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirClassImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirClassImpl.kt index 831f098c4ec..e49be905535 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirClassImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirClassImpl.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name data class CirClassImpl( @@ -22,7 +21,7 @@ data class CirClassImpl( override val visibility: Visibility, override val modality: Modality, override val kind: ClassKind, - override var companion: FqName?, + override var companion: Name?, override val isCompanion: Boolean, override val isData: Boolean, override val isInline: Boolean, diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt index faf4dd78da0..7da5d873218 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/CirSimpleTypeImpl.kt @@ -6,17 +6,13 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection +import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode -import org.jetbrains.kotlin.name.FqName data class CirSimpleTypeImpl( - override val kind: CirSimpleTypeKind, + override val classifierId: CirClassifierId, override val visibility: Visibility, // visibility of the classifier descriptor - override val fqName: FqName, override val arguments: List<CirTypeProjection>, override val isMarkedNullable: Boolean, override val isDefinitelyNotNullType: Boolean, @@ -25,9 +21,8 @@ data class CirSimpleTypeImpl( // See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode private var cachedHashCode = 0 - private fun computeHashCode() = hashCode(kind) + private fun computeHashCode() = hashCode(classifierId) .appendHashCode(visibility) - .appendHashCode(fqName) .appendHashCode(arguments) .appendHashCode(isMarkedNullable) .appendHashCode(isDefinitelyNotNullType) @@ -46,8 +41,7 @@ data class CirSimpleTypeImpl( other === this -> true other is CirSimpleType -> { isMarkedNullable == other.isMarkedNullable - && fqName == other.fqName - && kind == other.kind + && classifierId == other.classifierId && visibility == other.visibility && arguments == other.arguments && fqNameWithTypeParameters == other.fqNameWithTypeParameters diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt index a5c1c3395eb..11bc1035935 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/cir/impl/RecursionMarkers.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.impl import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRecursionMarker -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name object CirClassRecursionMarker : CirClass, CirRecursionMarker { override val annotations get() = unsupported() @@ -17,7 +17,7 @@ object CirClassRecursionMarker : CirClass, CirRecursionMarker { override val visibility get() = unsupported() override val modality get() = unsupported() override val kind get() = unsupported() - override var companion: FqName? + override var companion: Name? get() = unsupported() set(_) = unsupported() override val isCompanion get() = unsupported() diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt index 34532a00e92..d600787cc5b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizer.kt @@ -5,10 +5,16 @@ package org.jetbrains.kotlin.descriptors.commonizer.core +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory +import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassifierIdFactory +import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE -import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_FQN +import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_CID +import org.jetbrains.kotlin.descriptors.commonizer.utils.intern +import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -32,9 +38,13 @@ class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, Li override fun initialize(first: List<CirAnnotation>) = Unit override fun doCommonizeWith(next: List<CirAnnotation>): Boolean { - val nextDeprecatedAnnotation = next.firstOrNull { it.fqName == DEPRECATED_ANNOTATION_FQN } ?: return true + val nextDeprecatedAnnotation = next.firstOrNull { annotation -> + (annotation.type.classifierId as? CirClassifierId.ClassOrTypeAlias)?.classId == DEPRECATED_ANNOTATION_CID + } ?: return true + val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer ?: DeprecatedAnnotationCommonizer().also { this.deprecatedAnnotationCommonizer = it } + return deprecatedAnnotationCommonizer.commonizeWith(nextDeprecatedAnnotation) } @@ -70,7 +80,7 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno mapOf(PROPERTY_NAME_REPLACE_WITH to replaceWithExpression.toReplaceWithValue(replaceWithImports)) return CirAnnotationFactory.create( - fqName = DEPRECATED_ANNOTATION_FQN, + type = DEPRECATED_ANNOTATION_TYPE, constantValueArguments = constantValueArguments, annotationValueArguments = annotationValueArguments ) @@ -126,12 +136,12 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno @Suppress("NOTHING_TO_INLINE") companion object { - private val PROPERTY_NAME_MESSAGE = Name.identifier(Deprecated::message.name) - private val PROPERTY_NAME_REPLACE_WITH = Name.identifier(Deprecated::replaceWith.name) - private val PROPERTY_NAME_LEVEL = Name.identifier(Deprecated::level.name) + private val PROPERTY_NAME_MESSAGE = Name.identifier(Deprecated::message.name).intern() + private val PROPERTY_NAME_REPLACE_WITH = Name.identifier(Deprecated::replaceWith.name).intern() + private val PROPERTY_NAME_LEVEL = Name.identifier(Deprecated::level.name).intern() - private val PROPERTY_NAME_EXPRESSION = Name.identifier(ReplaceWith::expression.name) - private val PROPERTY_NAME_IMPORTS = Name.identifier(ReplaceWith::imports.name) + private val PROPERTY_NAME_EXPRESSION = Name.identifier(ReplaceWith::expression.name).intern() + private val PROPERTY_NAME_IMPORTS = Name.identifier(ReplaceWith::imports.name).intern() // Optimization: Keep most frequently used message constants. private val FREQUENTLY_USED_MESSAGE_VALUES: Map<String, StringValue> = listOf( @@ -140,15 +150,24 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno ).associateWith { StringValue(it) } private val FALLBACK_MESSAGE_VALUE = StringValue(FALLBACK_MESSAGE) - private val DEPRECATION_LEVEL_FQN = FqName(DeprecationLevel::class.java.name) - private val DEPRECATION_LEVEL_CLASS_ID = ClassId.topLevel(DEPRECATION_LEVEL_FQN) + private val DEPRECATED_ANNOTATION_TYPE = buildAnnotationType(DEPRECATED_ANNOTATION_CID) + private val REPLACE_WITH_ANNOTATION_TYPE = buildAnnotationType(internedClassId(FqName(ReplaceWith::class.java.name))) + + private val DEPRECATION_LEVEL_CID = internedClassId(FqName(DeprecationLevel::class.java.name)) // Optimization: Keep DeprecationLevel enum constants. private val DEPRECATION_LEVEL_ENUM_ENTRY_VALUES: Map<String, EnumValue> = DeprecationLevel.values().associate { - it.name to EnumValue(DEPRECATION_LEVEL_CLASS_ID, Name.identifier(it.name)) + it.name to EnumValue(DEPRECATION_LEVEL_CID, Name.identifier(it.name).intern()) } - private val REPLACE_WITH_FQN = FqName(ReplaceWith::class.java.name) + private fun buildAnnotationType(classId: ClassId) = CirTypeFactory.create( + classifierId = CirClassifierIdFactory.createForClass(classId), + visibility = Visibilities.PUBLIC, + arguments = emptyList(), + isMarkedNullable = false, + isDefinitelyNotNullType = false, + fqNameWithTypeParameters = classId.asString() + ) private fun CirAnnotation.getDeprecationMessage(): String? = constantValueArguments.getString(PROPERTY_NAME_MESSAGE) @@ -204,7 +223,7 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno private inline fun createReplaceWithAnnotation(expression: String, imports: List<String>): CirAnnotation = CirAnnotationFactory.create( - fqName = REPLACE_WITH_FQN, + type = REPLACE_WITH_ANNOTATION_TYPE, constantValueArguments = mapOf( PROPERTY_NAME_EXPRESSION to StringValue(expression), PROPERTY_NAME_IMPORTS to ArrayValue( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt index 0c6778531ee..b7934bcd2a3 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CommonizationVisitor.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroupMap +import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId internal class CommonizationVisitor( private val root: CirRootNode @@ -77,15 +78,16 @@ internal class CommonizationVisitor( } if (commonClass != null) { - // companion object should have the same FQ name for each target class, then it could be set to common class - val companionObjectFqName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull() - if (companionObjectFqName != null) { - val companionObjectNode = root.cache.classes[companionObjectFqName] - ?: error("Can't find companion object with FQ name $companionObjectFqName") + // companion object should have the same name for each target class, then it could be set to common class + val companionObjectName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull() + if (companionObjectName != null) { + val companionObjectClassId = internedClassId(node.classId, companionObjectName) + val companionObjectNode = root.cache.classes[companionObjectClassId] + ?: error("Can't find companion object with class ID $companionObjectClassId") if (companionObjectNode.commonDeclaration() != null) { // companion object has been successfully commonized - commonClass.companion = companionObjectFqName + commonClass.companion = companionObjectName } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt index 6172ddc3ff7..b5782965298 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeAliasCommonizer.kt @@ -95,6 +95,6 @@ private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer<CirTyp override fun doCommonizeWith(next: CirTypeAlias) = next.typeParameters.isEmpty() // TAs with declared type parameters can't be commonized && next.underlyingType.arguments.isEmpty() // TAs with functional types or types with parameters at the right-hand side can't be commonized - && next.underlyingType.kind == CirSimpleTypeKind.CLASS // right-hand side could have only class + && next.underlyingType.classifierId is CirClassifierId.Class // right-hand side could have only class && classVisibility.commonizeWith(next.underlyingType) // the visibilities of the right-hand classes should be equal } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt index f660fb17336..3f971a7116e 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFlexibleType -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleTypeKind -import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType +import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages @@ -39,29 +36,42 @@ internal fun areTypesEqual(cache: CirClassifiersCache, a: CirType, b: CirType): } private fun areSimpleTypesEqual(cache: CirClassifiersCache, a: CirSimpleType, b: CirSimpleType): Boolean { - if (a !== b - && (a.arguments.size != b.arguments.size - || a.isMarkedNullable != b.isMarkedNullable - || a.isDefinitelyNotNullType != b.isDefinitelyNotNullType - || a.fqName != b.fqName) - ) { - return false + val aId = a.classifierId + val bId = b.classifierId + + if (a !== b) { + if (a.arguments.size != b.arguments.size + || a.isMarkedNullable != b.isMarkedNullable + || a.isDefinitelyNotNullType != b.isDefinitelyNotNullType + ) { + return false + } + + if (aId is CirClassifierId.ClassOrTypeAlias) { + if (bId !is CirClassifierId.ClassOrTypeAlias || aId.classId != bId.classId) return false + } + + if (aId is CirClassifierId.TypeParameter) { + if (bId !is CirClassifierId.TypeParameter || aId.name != bId.name) return false + } } - fun isClassOrTypeAliasUnderStandardKotlinPackages() = - // N.B. only for descriptors that represent classes or type aliases, but not type parameters! - a.isClassOrTypeAlias && b.isClassOrTypeAlias && a.fqName.isUnderStandardKotlinPackages + // N.B. only for descriptors that represent classes or type aliases, but not type parameters! + fun isClassOrTypeAliasUnderStandardKotlinPackages(): Boolean { + return (aId as? CirClassifierId.ClassOrTypeAlias)?.classId?.packageFqName?.isUnderStandardKotlinPackages == true + } - fun descriptorsCanBeCommonizedThemselves() = - a.kind == b.kind && when (a.kind) { - CirSimpleTypeKind.CLASS -> cache.classes[a.fqName].canBeCommonized() - CirSimpleTypeKind.TYPE_ALIAS -> cache.typeAliases[a.fqName].canBeCommonized() - CirSimpleTypeKind.TYPE_PARAMETER -> { + fun descriptorsCanBeCommonizedThemselves(): Boolean { + return when (aId) { + is CirClassifierId.Class -> bId is CirClassifierId.Class && cache.classes[aId.classId].canBeCommonized() + is CirClassifierId.TypeAlias -> bId is CirClassifierId.TypeAlias && cache.typeAliases[aId.classId].canBeCommonized() + is CirClassifierId.TypeParameter -> { // Real type parameter commonization is performed in TypeParameterCommonizer. // Here it is enough to check that FQ names are equal (which is already done above). true } } + } val descriptorsCanBeCommonized = /* either class or type alias from Kotlin stdlib */ isClassOrTypeAliasUnderStandardKotlinPackages() diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt index c88b2c0631b..7104fdd93eb 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt @@ -43,7 +43,7 @@ internal class NativeDistributionModulesProvider( } } - override fun loadModules(): Collection<ModuleDescriptor> { + override fun loadModules(): Map<String, ModuleDescriptor> { val builtIns = loadBuiltIns() val stdlib = builtIns.builtInsModule @@ -74,6 +74,6 @@ internal class NativeDistributionModulesProvider( module.setDependencies(listOf(module) + dependencies + forwardDeclarations) } - return platformModulesMap.values.toList() + return platformModulesMap } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassNode.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassNode.kt index 9d55b779bf2..afc3e958f3c 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassNode.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassNode.kt @@ -8,15 +8,15 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree import gnu.trove.THashMap import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.storage.NullableLazyValue class CirClassNode( override val targetDeclarations: CommonizedGroup<CirClass>, override val commonDeclaration: NullableLazyValue<CirClass>, - override val fqName: FqName -) : CirNodeWithFqName<CirClass, CirClass> { + override val classId: ClassId +) : CirNodeWithClassId<CirClass, CirClass> { val constructors: MutableMap<ConstructorApproximationKey, CirClassConstructorNode> = THashMap() val properties: MutableMap<PropertyApproximationKey, CirPropertyNode> = THashMap() diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt index b378b202a90..e45d454a794 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt @@ -5,9 +5,9 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId interface CirClassifiersCache { - val classes: Map<FqName, CirClassNode> - val typeAliases: Map<FqName, CirTypeAliasNode> + val classes: Map<ClassId, CirClassNode> + val typeAliases: Map<ClassId, CirTypeAliasNode> } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNode.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNode.kt index b94cda94b14..183bd53f733 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNode.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNode.kt @@ -24,7 +24,10 @@ interface CirNode<T : CirDeclaration, R : CirDeclaration> { fun toString(node: CirNode<*, *>) = buildString { if (node is CirNodeWithFqName) { - append("fqName=").append(node.fqName).append(", ") + append("fqName=").append(node.fqName.asString()).append(", ") + } + if (node is CirNodeWithClassId) { + append("classId=").append(node.classId.asString()).append(", ") } append("target=") node.targetDeclarations.joinTo(this) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNodeWithClassId.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNodeWithClassId.kt new file mode 100644 index 00000000000..6a4d3ef469a --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirNodeWithClassId.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.descriptors.commonizer.mergedtree + +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirDeclaration +import org.jetbrains.kotlin.name.ClassId + +interface CirNodeWithClassId<T : CirDeclaration, R : CirDeclaration> : CirNode<T, R> { + val classId: ClassId +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirRootNode.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirRootNode.kt index 64e9126e1cd..84dd78035f6 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirRootNode.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirRootNode.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree import gnu.trove.THashMap import org.jetbrains.kotlin.descriptors.commonizer.cir.CirRoot import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.storage.NullableLazyValue @@ -17,8 +17,8 @@ class CirRootNode( override val commonDeclaration: NullableLazyValue<CirRoot> ) : CirNode<CirRoot, CirRoot> { class CirClassifiersCacheImpl : CirClassifiersCache { - override val classes = THashMap<FqName, CirClassNode>() - override val typeAliases = THashMap<FqName, CirTypeAliasNode>() + override val classes = THashMap<ClassId, CirClassNode>() + override val typeAliases = THashMap<ClassId, CirTypeAliasNode>() } val modules: MutableMap<Name, CirModuleNode> = THashMap() diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt index f02fdb180c4..af36ab5b7be 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt @@ -14,9 +14,10 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.intern +import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.NullableLazyValue import org.jetbrains.kotlin.storage.StorageManager @@ -70,11 +71,11 @@ class CirTreeMerger( targetProvider.builtInsProvider ) - val moduleDescriptors: Collection<ModuleDescriptor> = targetProvider.modulesProvider.loadModules() + val moduleDescriptors: Map<String, ModuleDescriptor> = targetProvider.modulesProvider.loadModules() val modules: MutableMap<Name, CirModuleNode> = rootNode.modules - moduleDescriptors.forEach { moduleDescriptor -> - if (moduleDescriptor.name.asString().removeSurrounding("<", ">") in commonModuleNames) + moduleDescriptors.forEach { (name, moduleDescriptor) -> + if (name in commonModuleNames) processModule(modules, targetIndex, moduleDescriptor) } } @@ -115,10 +116,20 @@ class CirTreeMerger( val typeAliases: MutableMap<Name, CirTypeAliasNode> = packageNode.typeAliases packageMemberScope.collectMembers( - PropertyCollector { processProperty(properties, targetIndex, it, null) }, - FunctionCollector { processFunction(functions, targetIndex, it, null) }, - ClassCollector { processClass(classes, targetIndex, it, null) }, - TypeAliasCollector { processTypeAlias(typeAliases, targetIndex, it) } + PropertyCollector { propertyDescriptor -> + processProperty(properties, targetIndex, propertyDescriptor, null) + }, + FunctionCollector { functionDescriptor -> + processFunction(functions, targetIndex, functionDescriptor, null) + }, + ClassCollector { classDescriptor -> + processClass(classes, targetIndex, classDescriptor, null) { className -> + internedClassId(packageFqName, className) + } + }, + TypeAliasCollector { typeAliasDescriptor -> + processTypeAlias(typeAliases, targetIndex, typeAliasDescriptor, packageFqName) + } ) } @@ -150,10 +161,14 @@ class CirTreeMerger( classes: MutableMap<Name, CirClassNode>, targetIndex: Int, classDescriptor: ClassDescriptor, - parentCommonDeclaration: NullableLazyValue<*>? + parentCommonDeclaration: NullableLazyValue<*>?, + classIdFunction: (Name) -> ClassId ) { - val classNode: CirClassNode = classes.getOrPut(classDescriptor.name.intern()) { - buildClassNode(storageManager, size, cacheRW, parentCommonDeclaration, classDescriptor.fqNameSafe.intern()) + val className = classDescriptor.name.intern() + val classId = classIdFunction(className) + + val classNode: CirClassNode = classes.getOrPut(className) { + buildClassNode(storageManager, size, cacheRW, parentCommonDeclaration, classId) } classNode.targetDeclarations[targetIndex] = CirClassFactory.create(classDescriptor) @@ -167,9 +182,17 @@ class CirTreeMerger( classDescriptor.constructors.forEach { processClassConstructor(constructors, targetIndex, it, parentCommonDeclarationForMembers) } classDescriptor.unsubstitutedMemberScope.collectMembers( - PropertyCollector { processProperty(properties, targetIndex, it, parentCommonDeclarationForMembers) }, - FunctionCollector { processFunction(functions, targetIndex, it, parentCommonDeclarationForMembers) }, - ClassCollector { processClass(nestedClasses, targetIndex, it, parentCommonDeclarationForMembers) } + PropertyCollector { propertyDescriptor -> + processProperty(properties, targetIndex, propertyDescriptor, parentCommonDeclarationForMembers) + }, + FunctionCollector { functionDescriptor -> + processFunction(functions, targetIndex, functionDescriptor, parentCommonDeclarationForMembers) + }, + ClassCollector { nestedClassDescriptor -> + processClass(nestedClasses, targetIndex, nestedClassDescriptor, parentCommonDeclarationForMembers) { nestedClassName -> + internedClassId(classId, nestedClassName) + } + } ) } @@ -188,10 +211,14 @@ class CirTreeMerger( private fun processTypeAlias( typeAliases: MutableMap<Name, CirTypeAliasNode>, targetIndex: Int, - typeAliasDescriptor: TypeAliasDescriptor + typeAliasDescriptor: TypeAliasDescriptor, + packageFqName: FqName ) { - val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasDescriptor.name.intern()) { - buildTypeAliasNode(storageManager, size, cacheRW, typeAliasDescriptor.fqNameSafe.intern()) + val typeAliasName = typeAliasDescriptor.name.intern() + val typeAliasClassId = internedClassId(packageFqName, typeAliasName) + + val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasName) { + buildTypeAliasNode(storageManager, size, cacheRW, typeAliasClassId) } typeAliasNode.targetDeclarations[targetIndex] = CirTypeAliasFactory.create(typeAliasDescriptor) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTypeAliasNode.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTypeAliasNode.kt index 7dfd566055c..b781674ead3 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTypeAliasNode.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTypeAliasNode.kt @@ -8,14 +8,14 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.storage.NullableLazyValue class CirTypeAliasNode( override val targetDeclarations: CommonizedGroup<CirTypeAlias>, override val commonDeclaration: NullableLazyValue<CirClassifier>, - override val fqName: FqName -) : CirNodeWithFqName<CirTypeAlias, CirClassifier> { + override val classId: ClassId +) : CirNodeWithClassId<CirTypeAlias, CirClassifier> { override fun <R, T> accept(visitor: CirNodeVisitor<R, T>, data: T): R = visitor.visitTypeAliasNode(this, data) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt index e79d08c4e27..41f60d87bea 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/nodeBuilders.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassifierRecursi import org.jetbrains.kotlin.descriptors.commonizer.core.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.storage.NullableLazyValue @@ -81,7 +82,7 @@ internal fun buildClassNode( size: Int, cacheRW: CirClassifiersCacheImpl, parentCommonDeclaration: NullableLazyValue<*>?, - fqName: FqName + classId: ClassId ): CirClassNode = buildNode( storageManager = storageManager, size = size, @@ -89,8 +90,8 @@ internal fun buildClassNode( commonizerProducer = { ClassCommonizer(cacheRW) }, recursionMarker = CirClassRecursionMarker, nodeProducer = { targetDeclarations, commonDeclaration -> - CirClassNode(targetDeclarations, commonDeclaration, fqName).also { - cacheRW.classes[fqName] = it + CirClassNode(targetDeclarations, commonDeclaration, classId).also { + cacheRW.classes[classId] = it } } ) @@ -112,15 +113,15 @@ internal fun buildTypeAliasNode( storageManager: StorageManager, size: Int, cacheRW: CirClassifiersCacheImpl, - fqName: FqName + classId: ClassId ): CirTypeAliasNode = buildNode( storageManager = storageManager, size = size, commonizerProducer = { TypeAliasCommonizer(cacheRW) }, recursionMarker = CirClassifierRecursionMarker, nodeProducer = { targetDeclarations, commonDeclaration -> - CirTypeAliasNode(targetDeclarations, commonDeclaration, fqName).also { - cacheRW.typeAliases[fqName] = it + CirTypeAliasNode(targetDeclarations, commonDeclaration, classId).also { + cacheRW.typeAliases[classId] = it } } ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt index 7e67c737bd5..27635608544 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt @@ -6,10 +6,12 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.serialization.konan.impl.ForwardDeclarationsFqNames -internal val DEPRECATED_ANNOTATION_FQN: FqName = FqName(Deprecated::class.java.name) +internal val DEPRECATED_ANNOTATION_FQN: FqName = FqName(Deprecated::class.java.name).intern() +internal val DEPRECATED_ANNOTATION_CID: ClassId = internedClassId(DEPRECATED_ANNOTATION_FQN) private val STANDARD_KOTLIN_PACKAGE_PREFIXES = listOf( KotlinBuiltIns.BUILT_INS_PACKAGE_NAME.asString(), diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/interners.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/interners.kt new file mode 100644 index 00000000000..e72e708c02a --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/interners.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.descriptors.commonizer.utils + +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal fun FqName.intern(): FqName = fqNameInterner.intern(this) +internal fun Name.intern(): Name = nameInterner.intern(this) + +@Suppress("NOTHING_TO_INLINE") +internal inline fun internedClassId(topLevelFqName: FqName): ClassId { + val packageFqName = topLevelFqName.parent().intern() + val className = topLevelFqName.shortName().intern() + return internedClassId(packageFqName, className) +} + +internal fun internedClassId(packageFqName: FqName, classifierName: Name): ClassId { + val relativeClassName = FqName.topLevel(classifierName).intern() + return ClassId(packageFqName, relativeClassName, false).intern() +} + +internal fun internedClassId(ownerClassId: ClassId, nestedClassName: Name): ClassId { + val relativeClassName = ownerClassId.relativeClassName.child(nestedClassName).intern() + return ClassId(ownerClassId.packageFqName, relativeClassName, ownerClassId.isLocal).intern() +} + +@Suppress("NOTHING_TO_INLINE") +private inline fun ClassId.intern(): ClassId = classIdInterner.intern(this) + +private val fqNameInterner = Interner<FqName>() +private val nameInterner = Interner<Name>() +private val classIdInterner = Interner<ClassId>() diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/moduleDescriptor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/moduleDescriptor.kt index 068cd5722ed..45f2de06a87 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/moduleDescriptor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/moduleDescriptor.kt @@ -11,11 +11,13 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.konan.util.KlibMetadataFactories import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescriptorsFactoryImpl import org.jetbrains.kotlin.storage.StorageManager @@ -33,20 +35,67 @@ internal fun createKotlinNativeForwardDeclarationsModule( ) // similar to org.jetbrains.kotlin.descriptors.DescriptorUtilKt#resolveClassByFqName, but resolves also type aliases -internal fun ModuleDescriptor.resolveClassOrTypeAliasByFqName( - fqName: FqName, - lookupLocation: LookupLocation -): ClassifierDescriptorWithTypeParameters? { - if (fqName.isRoot) return null - - (getPackage(fqName.parent()).memberScope.getContributedClassifier( - fqName.shortName(), - lookupLocation - ) as? ClassifierDescriptorWithTypeParameters)?.let { return it } - - return (resolveClassOrTypeAliasByFqName(fqName.parent(), lookupLocation) as? ClassDescriptor) - ?.unsubstitutedInnerClassesScope - ?.getContributedClassifier(fqName.shortName(), lookupLocation) as? ClassifierDescriptorWithTypeParameters +internal fun ModuleDescriptor.resolveClassOrTypeAlias(classId: ClassId): ClassifierDescriptorWithTypeParameters? { + val relativeClassName: FqName = classId.relativeClassName + if (relativeClassName.isRoot) + return null + + var memberScope: MemberScope = getPackage(classId.packageFqName).memberScope + + val classifierName = if ('.' in relativeClassName.asString()) { + // resolve member scope of the nested class + relativeClassName.pathSegments().reduce { first, second -> + memberScope = (memberScope.getContributedClassifier( + first, + NoLookupLocation.FOR_ALREADY_TRACKED + ) as? ClassDescriptor)?.unsubstitutedMemberScope ?: return null + + second + } + } else { + relativeClassName.shortName() + } + + return memberScope.getContributedClassifier( + classifierName, + NoLookupLocation.FOR_ALREADY_TRACKED + ) as? ClassifierDescriptorWithTypeParameters +} + +internal fun MutableMap<String, ModuleDescriptor?>.guessModuleByPackageFqName(packageFqName: FqName): ModuleDescriptor? { + if (isEmpty()) return null + + val packageFqNameRaw = packageFqName.asString() + if (containsKey(packageFqNameRaw)) { + return this[packageFqNameRaw] // might return null if this is a previously cached result + } + + fun guessByEnding(): ModuleDescriptor? { + return entries + .firstOrNull { (name, _) -> name.endsWith(packageFqNameRaw, ignoreCase = true) } + ?.value + } + + fun guessBySmartEnding(): ModuleDescriptor? { + val packageFqNameFragments = packageFqNameRaw.split('.') + if (packageFqNameFragments.size < 2) return null + + return entries.firstOrNull { (name, _) -> + var startIndex = 0 + for (fragment in packageFqNameFragments) { + val index = name.indexOf(fragment, startIndex = startIndex, ignoreCase = true) + if (index < startIndex) + return@firstOrNull false + else + startIndex = index + fragment.length + } + true + }?.value + } + + val candidate = guessByEnding() ?: guessBySmartEnding() + this[packageFqNameRaw] = candidate // cache to speed-up the further look-ups + return candidate } internal val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer()) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt index 8b47496672e..4ae48838391 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt @@ -5,21 +5,27 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.types.AbbreviatedType +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.typeUtil.makeNotNullable internal inline val KotlinType.declarationDescriptor: ClassifierDescriptor get() = (constructor.declarationDescriptor ?: error("No declaration descriptor found for $constructor")) -internal inline val KotlinType.fqNameInterned: FqName - get() = declarationDescriptor.fqNameSafe.intern() - -internal fun FqName.intern(): FqName = fqNameInterner.intern(this) -internal fun Name.intern(): Name = nameInterner.intern(this) +internal val ClassifierDescriptorWithTypeParameters.internedClassId: ClassId + get() = when (val owner = containingDeclaration) { + is PackageFragmentDescriptor -> internedClassId(owner.fqName.intern(), name.intern()) + is ClassDescriptor -> internedClassId(owner.internedClassId, name.intern()) + else -> error("Unexpected containing declaration type for $this: ${owner::class}, $owner") + } internal val KotlinType.fqNameWithTypeParameters: String get() { @@ -28,12 +34,10 @@ internal val KotlinType.fqNameWithTypeParameters: String } private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, exploredTypeParameters: MutableSet<KotlinType>) { - val abbreviation = (type as? AbbreviatedType)?.abbreviation ?: type - append(abbreviation.fqNameInterned) - val typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type) if (typeParameterDescriptor != null) { // N.B this is type parameter type + append(typeParameterDescriptor.name.asString()) if (exploredTypeParameters.add(type.makeNotNullable())) { // print upper bounds once the first time when type parameter type is met append(":[") @@ -46,6 +50,8 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, explor } } else { // N.B. this is classifier type + val abbreviation = (type as? AbbreviatedType)?.abbreviation ?: type + append(abbreviation.declarationDescriptor.classId!!.asString()) val arguments = type.arguments if (arguments.isNotEmpty()) { @@ -73,6 +79,3 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, explor // dedicated to hold unique entries of "fqNameWithTypeParameters" private val stringInterner = Interner<String>() - -private val fqNameInterner = Interner<FqName>() -private val nameInterner = Interner<Name>() diff --git a/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/common/package_root.kt b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/common/package_root.kt new file mode 100644 index 00000000000..c4efae94909 --- /dev/null +++ b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/common/package_root.kt @@ -0,0 +1,5 @@ +expect class Foo() + +typealias TypeAlias = Foo + +expect fun bar(x: TypeAlias?)
\ No newline at end of file diff --git a/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/js/package_root.kt b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/js/package_root.kt new file mode 100644 index 00000000000..eab6a1203c8 --- /dev/null +++ b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/js/package_root.kt @@ -0,0 +1,3 @@ +actual class Foo actual constructor() + +actual fun bar(x: TypeAlias?) { }
\ No newline at end of file diff --git a/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/jvm/package_root.kt b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/jvm/package_root.kt new file mode 100644 index 00000000000..eab6a1203c8 --- /dev/null +++ b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/commonized/jvm/package_root.kt @@ -0,0 +1,3 @@ +actual class Foo actual constructor() + +actual fun bar(x: TypeAlias?) { }
\ No newline at end of file diff --git a/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/original/js/package_root.kt b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/original/js/package_root.kt new file mode 100644 index 00000000000..99ff5d3cd74 --- /dev/null +++ b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/original/js/package_root.kt @@ -0,0 +1,5 @@ +class Foo + +typealias TypeAlias = Foo + +fun bar(x: TypeAlias?) { }
\ No newline at end of file diff --git a/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/original/jvm/package_root.kt b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/original/jvm/package_root.kt new file mode 100644 index 00000000000..99ff5d3cd74 --- /dev/null +++ b/native/commonizer/testData/functionCommonization/signaturesWithNullableTypealiases/original/jvm/package_root.kt @@ -0,0 +1,5 @@ +class Foo + +typealias TypeAlias = Foo + +fun bar(x: TypeAlias?) { }
\ No newline at end of file diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/FunctionCommonizationFromSourcesTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/FunctionCommonizationFromSourcesTest.kt index a3469857839..5cf962495e2 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/FunctionCommonizationFromSourcesTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/FunctionCommonizationFromSourcesTest.kt @@ -15,4 +15,6 @@ class FunctionCommonizationFromSourcesTest : AbstractCommonizationFromSourcesTes fun testAnnotations() = doTestSuccessfulCommonization() fun testSpecifics() = doTestSuccessfulCommonization() + + fun testSignaturesWithNullableTypealiases() = doTestSuccessfulCommonization() } diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt index dca4bc1104d..5e3cbd67590 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/AnnotationsCommonizerTest.kt @@ -6,7 +6,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation +import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory +import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory +import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -287,7 +290,7 @@ private fun mockAnnotation( constantValueArguments: Map<Name, ConstantValue<*>> = emptyMap(), annotationValueArguments: Map<Name, CirAnnotation> = emptyMap() ): CirAnnotation = CirAnnotationFactory.create( - fqName = FqName(fqName), + type = CirTypeFactory.create(mockClassType(fqName)) as CirSimpleType, constantValueArguments = constantValueArguments, annotationValueArguments = annotationValueArguments ) diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt index b6fb42b7abe..c0654caa241 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizerTest.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildClassNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildTypeAliasNode import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockTAType -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.getAbbreviation @@ -459,27 +459,26 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() { val descriptor = (type.getAbbreviation() ?: type).constructor.declarationDescriptor when (descriptor) { is ClassDescriptor -> { - val fqName = descriptor.fqNameSafe - val node = cache.classes.getOrPut(fqName) { + val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor") + val node = cache.classes.getOrPut(classId) { buildClassNode( storageManager = LockBasedStorageManager.NO_LOCKS, size = variants.size, cacheRW = cache, parentCommonDeclaration = null, - fqName = fqName + classId = classId ) } node.targetDeclarations[index] = CirClassFactory.create(descriptor) } is TypeAliasDescriptor -> { - val fqName = descriptor.fqNameSafe - val node = cache.typeAliases.getOrPut(fqName) { + val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor") + val node = cache.typeAliases.getOrPut(classId) { buildTypeAliasNode( storageManager = LockBasedStorageManager.NO_LOCKS, size = variants.size, cacheRW = cache, - fqName = fqName - + classId = classId ) } node.targetDeclarations[index] = CirTypeAliasFactory.create(descriptor) diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt index ac8a3954a1e..bb3a8797f19 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.AnnotationValue import org.jetbrains.kotlin.resolve.constants.ConstantValue +import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType @@ -484,10 +485,10 @@ internal class ComparingDeclarationsVisitor( context.nextLevel("Unwrapped/unabbreviated type annotations") ) - val expectedFqName = expectedUnwrapped.fqNameInterned - val actualFqName = actualUnwrapped.fqNameInterned + val expectedId = expectedUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() } + val actualId = actualUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() } - context.assertEquals(expectedFqName, actualFqName, "type FQN") + context.assertEquals(expectedId, actualId, "type class ID / name") val expectedArguments = expectedUnwrapped.arguments val actualArguments = actualUnwrapped.arguments diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/mocks.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/mocks.kt index 12db715c5b7..7a96e1473f1 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/mocks.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/mocks.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.builder.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.parentOrNull import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -43,6 +44,7 @@ internal fun mockClassType( storageManager = LockBasedStorageManager.NO_LOCKS, target = InputTarget("Arbitrary target"), builtIns = DefaultBuiltIns.Instance, + lazyModulesLookupTable = LockBasedStorageManager.NO_LOCKS.createLazyValue { mutableMapOf() }, isCommon = false, index = 0, cache = DeclarationsBuilderCache(1) @@ -120,8 +122,8 @@ private fun createPackageFragmentForClassifier(classifierFqName: FqName): Packag } internal val EMPTY_CLASSIFIERS_CACHE = object : CirClassifiersCache { - override val classes: Map<FqName, CirClassNode> get() = emptyMap() - override val typeAliases: Map<FqName, CirTypeAliasNode> get() = emptyMap() + override val classes: Map<ClassId, CirClassNode> get() = emptyMap() + override val typeAliases: Map<ClassId, CirTypeAliasNode> get() = emptyMap() } internal class MockBuiltInsProvider(private val builtIns: KotlinBuiltIns) : BuiltInsProvider { @@ -144,7 +146,7 @@ internal class MockModulesProvider : ModulesProvider { } override fun loadModuleInfos() = moduleInfos - override fun loadModules() = modules.values + override fun loadModules() = modules private fun fakeModuleInfo(name: String) = ModuleInfo(name, File("/tmp/commonizer/mocks/$name")) } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/AbstractSerialGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/AbstractSerialGenerator.kt index 76c46f666f4..dda81c7cc1a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/AbstractSerialGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/AbstractSerialGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -38,6 +38,11 @@ abstract class AbstractSerialGenerator(val bindingContext: BindingContext, val c getKClassListFromFileAnnotation( SerializationAnnotations.contextualFqName, currentDeclaration + ).plus( + getKClassListFromFileAnnotation( + SerializationAnnotations.contextualOnFileFqName, + currentDeclaration + ) ).toSet() } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt index 938e044c214..032e637a2f3 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlinx.serialization.compiler.backend.common @@ -118,7 +107,7 @@ fun analyzeSpecialSerializers( moduleDescriptor: ModuleDescriptor, annotations: Annotations ): ClassDescriptor? = when { - annotations.hasAnnotation(SerializationAnnotations.contextualFqName) -> + annotations.hasAnnotation(SerializationAnnotations.contextualFqName) || annotations.hasAnnotation(SerializationAnnotations.contextualOnPropertyFqName) -> moduleDescriptor.getClassFromSerializationPackage(SpecialBuiltins.contextSerializer) // can be annotation on type usage, e.g. List<@Polymorphic Any> annotations.hasAnnotation(SerializationAnnotations.polymorphicFqName) -> @@ -147,7 +136,7 @@ fun AbstractSerialGenerator.findTypeSerializerOrContext( if (kType.isTypeParameter()) return null return findTypeSerializerOrContextUnchecked(module, kType) ?: throw CompilationException( "Serializer for element of type $kType has not been found.\n" + - "To use context serializer as fallback, explicitly annotate element with @ContextualSerialization", + "To use context serializer as fallback, explicitly annotate element with @Contextual", null, sourceElement ) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java index 7a0d339e30e..5616ece19ec 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -32,6 +32,8 @@ public interface SerializationErrors { DiagnosticFactory0<PsiElement> TRANSIENT_IS_REDUNDANT = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0<PsiElement> INCORRECT_TRANSIENT = DiagnosticFactory0.create(WARNING); + @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginDeclarationChecker.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginDeclarationChecker.kt index 5f44776c2dc..2729b12a3fb 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginDeclarationChecker.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginDeclarationChecker.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -14,10 +14,14 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces import org.jetbrains.kotlin.resolve.hasBackingField import org.jetbrains.kotlin.resolve.isInlineClassType +import org.jetbrains.kotlin.resolve.jvm.annotations.TRANSIENT_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor +import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.util.slicedMap.Slices @@ -37,10 +41,27 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker { if (!canBeSerializedInternally(descriptor, declaration, context.trace)) return if (declaration !is KtPureClassOrObject) return val props = buildSerializableProperties(descriptor, context.trace) ?: return + checkCorrectTransientAnnotationIsUsed(descriptor, props.serializableProperties, context.trace) checkTransients(declaration, context.trace) analyzePropertiesSerializers(context.trace, descriptor, props.serializableProperties) } + private fun checkCorrectTransientAnnotationIsUsed( + descriptor: ClassDescriptor, + properties: List<SerializableProperty>, + trace: BindingTrace + ) { + if (descriptor.getSuperInterfaces().any { it.fqNameSafe.asString() == "java.io.Serializable" }) return // do not check + for (prop in properties) { + if (prop.transient) continue // correct annotation is used + val incorrectTransient = prop.descriptor.backingField?.annotations?.findAnnotation(TRANSIENT_ANNOTATION_FQ_NAME) + if (incorrectTransient != null) { + val elementToReport = incorrectTransient.source.getPsi() ?: prop.descriptor.findPsi() ?: continue + trace.report(SerializationErrors.INCORRECT_TRANSIENT.on(elementToReport)) + } + } + } + private fun canBeSerializedInternally(descriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace): Boolean { if (descriptor.isSerializableEnumWithMissingSerializer()) { val declarationToReport = declaration.modifierList ?: declaration diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt index 0289440de4d..f071e10e63f 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt @@ -48,7 +48,7 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension { MAP.put( SerializationErrors.SERIALIZER_NOT_FOUND, "Serializer has not been found for type ''{0}''. " + - "To use context serializer as fallback, explicitly annotate type or property with @ContextualSerialization", + "To use context serializer as fallback, explicitly annotate type or property with @Contextual", Renderers.RENDER_TYPE_WITH_ANNOTATIONS ) MAP.put( @@ -65,5 +65,9 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension { SerializationErrors.TRANSIENT_IS_REDUNDANT, "Property does not have backing field which makes it non-serializable and therefore @Transient is redundant" ) + MAP.put( + SerializationErrors.INCORRECT_TRANSIENT, + "@kotlin.jvm.Transient does not affect @Serializable classes. Please use @kotlinx.serialization.Transient instead." + ) } }
\ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt index 29cfbe3d6e4..9a3e2e8b3d8 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt @@ -23,10 +23,12 @@ object SerializationAnnotations { val serializerAnnotationFqName = FqName("kotlinx.serialization.Serializer") internal val serialNameAnnotationFqName = FqName("kotlinx.serialization.SerialName") internal val requiredAnnotationFqName = FqName("kotlinx.serialization.Required") - internal val serialTransientFqName = FqName("kotlinx.serialization.Transient") + val serialTransientFqName = FqName("kotlinx.serialization.Transient") internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo") - internal val contextualFqName = FqName("kotlinx.serialization.ContextualSerialization") + internal val contextualFqName = FqName("kotlinx.serialization.ContextualSerialization") // this one is deprecated + internal val contextualOnFileFqName = FqName("kotlinx.serialization.UseContextualSerialization") + internal val contextualOnPropertyFqName = FqName("kotlinx.serialization.Contextual") internal val polymorphicFqName = FqName("kotlinx.serialization.Polymorphic") internal val additionalSerializersFqName = FqName("kotlinx.serialization.UseSerializers") } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationPluginDiagnosticTestGenerated.java b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationPluginDiagnosticTestGenerated.java index 2a07c127c73..04f8eacec97 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationPluginDiagnosticTestGenerated.java +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationPluginDiagnosticTestGenerated.java @@ -25,7 +25,9 @@ public class SerializationPluginDiagnosticTestGenerated extends AbstractSerializ } public void testAllFilesPresentInDiagnostics() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true); + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File( + "plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, + true); } @TestMetadata("DuplicateSerialName.kt") @@ -33,6 +35,16 @@ public class SerializationPluginDiagnosticTestGenerated extends AbstractSerializ runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.kt"); } + @TestMetadata("IncorrectTransient.kt") + public void testIncorrectTransient() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient.kt"); + } + + @TestMetadata("IncorrectTransient2.kt") + public void testIncorrectTransient2() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient2.kt"); + } + @TestMetadata("LazyRecursionBug.kt") public void testLazyRecursionBug() throws Exception { runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.kt"); diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient.kt new file mode 100644 index 00000000000..b1eef1936d2 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE +// WITH_RUNTIME +// SKIP_TXT + +import kotlinx.serialization.Serializable +import java.io.Serializable as JavaSerializable + +@Serializable +class Data(val x: Int, <!INCORRECT_TRANSIENT!>@Transient<!> val y: String) + +@Serializable +class Data2(val x: Int, @Transient val y: String) : JavaSerializable
\ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient2.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient2.kt new file mode 100644 index 00000000000..8c1e812a131 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient2.kt @@ -0,0 +1,20 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE +// WITH_RUNTIME +// SKIP_TXT + +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import java.io.Serializable as JavaSerializable +import kotlin.jvm.Transient as JavaTransient + +@Serializable +class Data(val x: Int, @Transient val y: String = "a") + +@Serializable +class Data2(val x: Int, @Transient val y: String = "a") : JavaSerializable + +@Serializable +class Data3(val x: Int, @Transient @JavaTransient val y: String = "a") : JavaSerializable + +@Serializable +class Data4(val x: Int, <!INCORRECT_TRANSIENT!>@JavaTransient<!> val y: String)
\ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts b/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts index 80119173823..2ef3944b795 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts @@ -15,6 +15,9 @@ dependencies { compile(project(":idea:idea-maven")) compile(project(":plugins:annotation-based-compiler-plugins-ide-support")) compileOnly(intellijDep()) + Platform[192].orHigher { + compileOnly(intellijPluginDep("java")) + } excludeInAndroidStudio(rootProject) { compileOnly(intellijPluginDep("maven")) } compileOnly(intellijPluginDep("gradle")) @@ -30,5 +33,5 @@ sourceSets { runtimeJar() projectTest(parallel = true) { - + }
\ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/IncorrectTransientQuickFix.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/IncorrectTransientQuickFix.kt new file mode 100644 index 00000000000..cca28360931 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/IncorrectTransientQuickFix.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea.quickfixes + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction +import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory +import org.jetbrains.kotlin.idea.util.ImportInsertHelperImpl +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationErrors +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations + +internal class AddKotlinxSerializationTransientImportQuickFix(expression: PsiElement) : + KotlinQuickFixAction<PsiElement>(expression) { + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + // Do not use Helper itself because it does not insert import on conflict; + // so it will always fail because k.jvm.Transient is always in auto-import + ImportInsertHelperImpl.addImport(project, file, SerializationAnnotations.serialTransientFqName, allUnder = false) + } + + override fun getFamilyName(): String = text + + override fun getText(): String = "Import ${SerializationAnnotations.serialTransientFqName}" + + object Factory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + if (diagnostic.factory != SerializationErrors.INCORRECT_TRANSIENT) return null + val castedDiagnostic = SerializationErrors.INCORRECT_TRANSIENT.cast(diagnostic) + + val element = castedDiagnostic.psiElement + + return AddKotlinxSerializationTransientImportQuickFix(element) + } + } +}
\ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt new file mode 100644 index 00000000000..df870ab45ba --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea.quickfixes + +import org.jetbrains.kotlin.idea.quickfix.QuickFixContributor +import org.jetbrains.kotlin.idea.quickfix.QuickFixes +import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationErrors + +class SerializationQuickFixContributor : QuickFixContributor { + override fun registerQuickFixes(quickFixes: QuickFixes) { + quickFixes.register(SerializationErrors.INCORRECT_TRANSIENT, AddKotlinxSerializationTransientImportQuickFix.Factory) + } +}
\ No newline at end of file diff --git a/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/ReplCompletionAndErrorsAnalysisTest.kt b/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/ReplCompletionAndErrorsAnalysisTest.kt index 181ee208b94..6fd33962c34 100644 --- a/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/ReplCompletionAndErrorsAnalysisTest.kt +++ b/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/ReplCompletionAndErrorsAnalysisTest.kt @@ -322,6 +322,20 @@ class ReplCompletionAndErrorsAnalysisTest : TestCase() { run(setupDefaultImportsCompletionRun) } + @Test + fun testImportCompletion() = test { + run { + code = """ + import kotl + """.trimIndent() + cursor = 11 + expect { + completions.mode = ComparisonType.INCLUDES + addCompletion("kotlin", "kotlin", "package kotlin", "package") + } + } + } + @Ignore("Should be fixed by KT-39314") @Test fun ignore_testDefaultImportsNotFirst() = test { diff --git a/plugins/scripting/scripting-ide-services/src/org/jetbrains/kotlin/scripting/ide_services/compiler/impl/KotlinResolutionFacadeForRepl.kt b/plugins/scripting/scripting-ide-services/src/org/jetbrains/kotlin/scripting/ide_services/compiler/impl/KotlinResolutionFacadeForRepl.kt index 8b6116efea6..308eacc7c39 100644 --- a/plugins/scripting/scripting-ide-services/src/org/jetbrains/kotlin/scripting/ide_services/compiler/impl/KotlinResolutionFacadeForRepl.kt +++ b/plugins/scripting/scripting-ide-services/src/org/jetbrains/kotlin/scripting/ide_services/compiler/impl/KotlinResolutionFacadeForRepl.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.container.ComponentProvider +import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.resolve.ResolutionFacade @@ -35,10 +36,7 @@ class KotlinResolutionFacadeForRepl( throw UnsupportedOperationException() } - override val moduleDescriptor: ModuleDescriptor - get() { - throw UnsupportedOperationException() - } + override val moduleDescriptor: ModuleDescriptor = provider.getService(ModuleDescriptor::class.java) override fun <T : Any> getFrontendService(serviceClass: Class<T>): T { return provider.resolve(serviceClass)!!.getValue() as T diff --git a/prepare/compiler/compiler.pro b/prepare/compiler/compiler.pro index 501f6c84e72..445451498e7 100644 --- a/prepare/compiler/compiler.pro +++ b/prepare/compiler/compiler.pro @@ -100,7 +100,7 @@ public protected *; } --keep class com.google.common.** { *; } +-keepclassmembers class com.google.common.** { *; } -keep class org.jetbrains.kotlin.container.** { *; } diff --git a/tests/mute-common.csv b/tests/mute-common.csv index 07263e90713..b02ef197fb1 100644 --- a/tests/mute-common.csv +++ b/tests/mute-common.csv @@ -43,8 +43,7 @@ org.jetbrains.kotlin.idea.maven.configuration.MavenConfigureProjectByChangingFil org.jetbrains.kotlin.idea.quickfix.DeprecatedSymbolUsageFixSpecialTest.testDefaultParameterValuesFromLibrary, Always red because of additional import,, FLAKY org.jetbrains.kotlin.idea.quickfix.QuickFixMultiModuleTestGenerated.CreateActual.testWithTestDummy, Very flaky on teamcity,, FLAKY org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.CreateFromUsage.CreateClass.CallExpression.testCallInWhenEntry, KT-35728,, -org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.Libraries.testJunit, ERROR: Couldn't find the following libraries,, -org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.Libraries.testTestNG, ERROR: Couldn't find the following libraries,, +org.jetbrains.kotlin.idea.quickfix.QuickFixTestGenerated.ObsoleteKotlinJsPackages.testKotlinDomAndBrowserImport, Always red because UAST does not work with JS,, org.jetbrains.kotlin.idea.refactoring.move.MultiModuleMoveTestGenerated.testMoveFromJvmModuleToJsModule_MoveFromJvmModuleToJsModule, KT-34106,, org.jetbrains.kotlin.idea.refactoring.move.MultiModuleMoveTestGenerated.testMoveJdkDependentToJsModule_MoveJdkDependentToJsModule, KT-34106,, org.jetbrains.kotlin.idea.resolve.PartialBodyResolveTestGenerated.testSmartCastInTheSameStatement, KT-35922,, |