From 2fd7d64db03c8b1350841d7780a51e71451026d8 Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Thu, 22 Oct 2020 02:00:30 +0300 Subject: [PATCH 001/554] Promote CancellationException to stable #KT-41837 --- libraries/stdlib/api/js-v1/kotlin.coroutines.cancellation.kt | 1 - libraries/stdlib/api/js/kotlin.coroutines.cancellation.kt | 1 - .../kotlin/coroutines/cancellation/CancellationException.kt | 1 - .../kotlin/coroutines/cancellation/CancellationException.kt | 3 --- .../kotlin/coroutines/cancellation/CancellationExceptionH.kt | 3 --- 5 files changed, 9 deletions(-) diff --git a/libraries/stdlib/api/js-v1/kotlin.coroutines.cancellation.kt b/libraries/stdlib/api/js-v1/kotlin.coroutines.cancellation.kt index 7c780a279df..fe258a7c943 100644 --- a/libraries/stdlib/api/js-v1/kotlin.coroutines.cancellation.kt +++ b/libraries/stdlib/api/js-v1/kotlin.coroutines.cancellation.kt @@ -1,4 +1,3 @@ -@kotlin.ExperimentalStdlibApi @kotlin.SinceKotlin(version = "1.4") public open class CancellationException : kotlin.IllegalStateException { public constructor CancellationException() diff --git a/libraries/stdlib/api/js/kotlin.coroutines.cancellation.kt b/libraries/stdlib/api/js/kotlin.coroutines.cancellation.kt index 7c780a279df..fe258a7c943 100644 --- a/libraries/stdlib/api/js/kotlin.coroutines.cancellation.kt +++ b/libraries/stdlib/api/js/kotlin.coroutines.cancellation.kt @@ -1,4 +1,3 @@ -@kotlin.ExperimentalStdlibApi @kotlin.SinceKotlin(version = "1.4") public open class CancellationException : kotlin.IllegalStateException { public constructor CancellationException() diff --git a/libraries/stdlib/js/src/kotlin/coroutines/cancellation/CancellationException.kt b/libraries/stdlib/js/src/kotlin/coroutines/cancellation/CancellationException.kt index 0438d8b0b19..4f4de5417ca 100644 --- a/libraries/stdlib/js/src/kotlin/coroutines/cancellation/CancellationException.kt +++ b/libraries/stdlib/js/src/kotlin/coroutines/cancellation/CancellationException.kt @@ -5,7 +5,6 @@ package kotlin.coroutines.cancellation -@ExperimentalStdlibApi @SinceKotlin("1.4") public actual open class CancellationException : IllegalStateException { actual constructor() : super() diff --git a/libraries/stdlib/jvm/src/kotlin/coroutines/cancellation/CancellationException.kt b/libraries/stdlib/jvm/src/kotlin/coroutines/cancellation/CancellationException.kt index aad9d70e07e..e6abcec5518 100644 --- a/libraries/stdlib/jvm/src/kotlin/coroutines/cancellation/CancellationException.kt +++ b/libraries/stdlib/jvm/src/kotlin/coroutines/cancellation/CancellationException.kt @@ -7,18 +7,15 @@ package kotlin.coroutines.cancellation import kotlin.internal.InlineOnly -@ExperimentalStdlibApi @SinceKotlin("1.4") public actual typealias CancellationException = java.util.concurrent.CancellationException @InlineOnly -@ExperimentalStdlibApi @SinceKotlin("1.4") public actual inline fun CancellationException(message: String?, cause: Throwable?): CancellationException { return CancellationException(message).also { it.initCause(cause) } } @InlineOnly -@ExperimentalStdlibApi @SinceKotlin("1.4") public actual inline fun CancellationException(cause: Throwable?): CancellationException { return CancellationException(cause?.toString()).also { it.initCause(cause) } diff --git a/libraries/stdlib/src/kotlin/coroutines/cancellation/CancellationExceptionH.kt b/libraries/stdlib/src/kotlin/coroutines/cancellation/CancellationExceptionH.kt index 7ac0e7173a1..b64b1ffa9c9 100644 --- a/libraries/stdlib/src/kotlin/coroutines/cancellation/CancellationExceptionH.kt +++ b/libraries/stdlib/src/kotlin/coroutines/cancellation/CancellationExceptionH.kt @@ -9,7 +9,6 @@ package kotlin.coroutines.cancellation * Thrown by cancellable suspending functions if the coroutine is cancelled while it is suspended. * It indicates _normal_ cancellation of a coroutine. */ -@ExperimentalStdlibApi @SinceKotlin("1.4") public expect open class CancellationException : IllegalStateException { public constructor() @@ -19,7 +18,6 @@ public expect open class CancellationException : IllegalStateException { /** * Creates an instance of [CancellationException] with the given [message] and [cause]. */ -@ExperimentalStdlibApi @SinceKotlin("1.4") @Suppress("FunctionName", "NO_ACTUAL_FOR_EXPECT") public expect fun CancellationException(message: String?, cause: Throwable?): CancellationException @@ -27,7 +25,6 @@ public expect fun CancellationException(message: String?, cause: Throwable?): Ca /** * Creates an instance of [CancellationException] with the given [cause]. */ -@ExperimentalStdlibApi @SinceKotlin("1.4") @Suppress("FunctionName", "NO_ACTUAL_FOR_EXPECT") public expect fun CancellationException(cause: Throwable?): CancellationException \ No newline at end of file From 2c5c15f50371eeae54052c6d2483953326d8ee27 Mon Sep 17 00:00:00 2001 From: Ivan Gavrilovic Date: Thu, 24 Sep 2020 16:50:30 +0200 Subject: [PATCH 002/554] Clean-up outputs on non-incremental run Always clean all outputs on non-incremental run of the Kotlin compile task. #KT-38692 Fixed --- .../kotlin/gradle/KotlinGradlePluginIT.kt | 27 +++++++++++++++++++ .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 2 ++ 2 files changed, 29 insertions(+) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index c7ca33d8a89..98534eeaf69 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -1053,4 +1053,31 @@ class KotlinGradleIT : BaseGradleIT() { assertTasksExecuted(":lib1:compileDebugKotlin") } } + + /** Regression test for KT-38692. */ + @Test + fun testIncrementalWhenNoKotlinSources() = with( + Project("kotlinProject") + ) { + setupWorkingDir() + assertTrue(this.allKotlinFiles.toList().isNotEmpty()) + build(":compileKotlin") { + assertSuccessful() + assertTasksExecuted(":compileKotlin") + } + + // Remove all Kotlin sources and force non-incremental run + allKotlinFiles.forEach { assertTrue(it.delete()) } + projectDir.resolve("src/main/java/Sample.java").also { + it.parentFile.mkdirs() + it.writeText("public class Sample {}") + } + build("compileKotlin", "--rerun-tasks") { + assertSuccessful() + assertTasksExecuted(":compileKotlin") + val compiledKotlinClasses = fileInWorkingDir(classesDir()).allFilesWithExtension("class").toList() + + assertTrue(compiledKotlinClasses.isEmpty()) + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 5df1e0d974f..7329c47862d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -334,6 +334,8 @@ abstract class AbstractKotlinCompile() : AbstractKo if (!isIncrementalCompilationEnabled()) { clearLocalState("IC is disabled") + } else if (!inputs.isIncremental) { + clearLocalState("Task cannot run incrementally") } try { From ce407471ec0607415f6abc2b19b94e8889e73162 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Tue, 8 Sep 2020 09:26:19 +0900 Subject: [PATCH 003/554] Convert to secondary constructor: suggest on class name #KT-40861 Fixed --- ...tPrimaryConstructorToSecondaryIntention.kt | 65 ++++++++++--------- .../caretOnClassBody.kt | 4 ++ .../caretOnClassName.kt | 1 + .../caretOnClassName.kt.after | 7 ++ .../caretOnClassNameWithConstructorKeyword.kt | 2 + ...retOnClassNameWithoutPrimaryConstructor.kt | 2 + .../intentions/IntentionTestGenerated.java | 20 ++++++ 7 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassBody.kt create mode 100644 idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt create mode 100644 idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt.after create mode 100644 idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithConstructorKeyword.kt create mode 100644 idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithoutPrimaryConstructor.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPrimaryConstructorToSecondaryIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPrimaryConstructorToSecondaryIntention.kt index 280efc07315..714ef3ca2b1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPrimaryConstructorToSecondaryIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPrimaryConstructorToSecondaryIntention.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor +import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -21,21 +22,23 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder.Target.CONSTRUCTOR import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject +import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType +import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.parents -class ConvertPrimaryConstructorToSecondaryIntention : SelfTargetingIntention( - KtPrimaryConstructor::class.java, +class ConvertPrimaryConstructorToSecondaryIntention : SelfTargetingRangeIntention( + KtClass::class.java, KotlinBundle.lazyMessage("convert.to.secondary.constructor") ) { - override fun isApplicableTo(element: KtPrimaryConstructor, caretOffset: Int): Boolean { - val containingClass = element.containingClassOrObject as? KtClass ?: return false - if (containingClass.isAnnotation() || containingClass.isData() - || containingClass.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry } - ) return false - return element.valueParameters.all { !it.hasValOrVar() || (it.name != null && it.annotationEntries.isEmpty()) } + override fun applicabilityRange(element: KtClass): TextRange? { + val primaryCtor = element.primaryConstructor ?: return null + val startOffset = + (if (primaryCtor.getConstructorKeyword() != null) primaryCtor else element.nameIdentifier)?.startOffset ?: return null + if (element.isAnnotation() || element.isData() || element.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry }) return null + if (primaryCtor.valueParameters.any { it.hasValOrVar() && (it.name == null || it.annotationEntries.isNotEmpty()) }) return null + return TextRange(startOffset, primaryCtor.endOffset) } private fun KtReferenceExpression.isIndependent(classDescriptor: ClassDescriptor, context: BindingContext): Boolean = @@ -54,15 +57,15 @@ class ConvertPrimaryConstructorToSecondaryIntention : SelfTargetingIntention { !it.isIndependent(classDescriptor, context) } } - override fun applyTo(element: KtPrimaryConstructor, editor: Editor?) { - val klass = element.containingClassOrObject as? KtClass ?: return - if (klass.isAnnotation()) return - val context = klass.analyze() - val factory = KtPsiFactory(klass) - val commentSaver = CommentSaver(element) + override fun applyTo(element: KtClass, editor: Editor?) { + val primaryCtor = element.primaryConstructor ?: return + if (element.isAnnotation()) return + val context = element.analyze() + val factory = KtPsiFactory(element) + val commentSaver = CommentSaver(primaryCtor) val initializerMap = mutableMapOf() - for (property in klass.getProperties()) { - if (property.isIndependent(klass, context)) continue + for (property in element.getProperties()) { + if (property.isIndependent(element, context)) continue if (property.typeReference == null) { with(SpecifyTypeExplicitlyIntention()) { if (applicabilityRange(property) != null) { @@ -77,10 +80,10 @@ class ConvertPrimaryConstructorToSecondaryIntention : SelfTargetingIntention + stmt.text } ?: "" } } @@ -124,20 +127,20 @@ class ConvertPrimaryConstructorToSecondaryIntention : SelfTargetingIntention{ + fun bar() {} +} \ No newline at end of file diff --git a/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt new file mode 100644 index 00000000000..70c4386d3b3 --- /dev/null +++ b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt @@ -0,0 +1 @@ +class Foo(val x: Int) \ No newline at end of file diff --git a/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt.after b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt.after new file mode 100644 index 00000000000..1d5ddae62fb --- /dev/null +++ b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt.after @@ -0,0 +1,7 @@ +class Foo { + val x: Int + + constructor(x: Int) { + this.x = x + } +} \ No newline at end of file diff --git a/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithConstructorKeyword.kt b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithConstructorKeyword.kt new file mode 100644 index 00000000000..5a604301014 --- /dev/null +++ b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithConstructorKeyword.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +class Foo constructor() \ No newline at end of file diff --git a/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithoutPrimaryConstructor.kt b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithoutPrimaryConstructor.kt new file mode 100644 index 00000000000..6f2363e340a --- /dev/null +++ b/idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithoutPrimaryConstructor.kt @@ -0,0 +1,2 @@ +// IS_APPLICABLE: false +class Foo \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 373bc9190b0..db1b2b4dc6f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -5962,6 +5962,26 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/convertPrimaryConstructorToSecondary/annotationClass.kt"); } + @TestMetadata("caretOnClassBody.kt") + public void testCaretOnClassBody() throws Exception { + runTest("idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassBody.kt"); + } + + @TestMetadata("caretOnClassName.kt") + public void testCaretOnClassName() throws Exception { + runTest("idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassName.kt"); + } + + @TestMetadata("caretOnClassNameWithConstructorKeyword.kt") + public void testCaretOnClassNameWithConstructorKeyword() throws Exception { + runTest("idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithConstructorKeyword.kt"); + } + + @TestMetadata("caretOnClassNameWithoutPrimaryConstructor.kt") + public void testCaretOnClassNameWithoutPrimaryConstructor() throws Exception { + runTest("idea/testData/intentions/convertPrimaryConstructorToSecondary/caretOnClassNameWithoutPrimaryConstructor.kt"); + } + @TestMetadata("dataClass.kt") public void testDataClass() throws Exception { runTest("idea/testData/intentions/convertPrimaryConstructorToSecondary/dataClass.kt"); From 5c3269f489e89805457d26e6aa3444e86742bf6d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 26 Oct 2020 18:26:34 +0300 Subject: [PATCH 004/554] [FIR] JvmMappedScope: don't add Java methods if Kotlin ones are here --- .../kotlin/fir/scopes/jvm/JvmMappedScope.kt | 16 +++++++++++++--- .../methodsFromAny/builtinFunctionsToString.kt | 1 - .../tests/targetedBuiltIns/getOrDefault.fir.kt | 12 ++++++------ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt index f66a9dc8113..77d4fe295df 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addIfNotNull class JvmMappedScope( private val declaredMemberScope: FirScope, @@ -21,14 +22,23 @@ class JvmMappedScope( override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { val visibleMethods = signatures.visibleMethodSignaturesByName[name] ?: return declaredMemberScope.processFunctionsByName(name, processor) + + val declared = mutableListOf() + declaredMemberScope.processFunctionsByName(name) { symbol -> + declared.addIfNotNull(symbol as FirNamedFunctionSymbol) + processor(symbol) + } + + val declaredSignatures by lazy { + declared.mapTo(mutableSetOf()) { it.fir.computeJvmDescriptorReplacingKotlinToJava() } + } + javaMappedClassUseSiteScope.processFunctionsByName(name) { symbol -> val jvmSignature = symbol.fir.computeJvmDescriptorReplacingKotlinToJava() - if (jvmSignature in visibleMethods) { + if (jvmSignature in visibleMethods && jvmSignature !in declaredSignatures) { processor(symbol) } } - - declaredMemberScope.processFunctionsByName(name, processor) } override fun processDirectOverriddenFunctionsWithBaseScope( diff --git a/compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt b/compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt index 5cc381840d4..5c7bc1de260 100644 --- a/compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt +++ b/compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt @@ -1,6 +1,5 @@ // SKIP_JDK6 // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // FULL_JDK // WITH_REFLECT diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/getOrDefault.fir.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/getOrDefault.fir.kt index 66aec7f85f4..b4b0ecc3eae 100644 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/getOrDefault.fir.kt +++ b/compiler/testData/diagnostics/tests/targetedBuiltIns/getOrDefault.fir.kt @@ -4,14 +4,14 @@ abstract class A : Map fun foo(x: Map, a: A, b: java.util.HashMap) { x.getOrDefault(1, "") - x.getOrDefault("", "") - x.getOrDefault(1, 2) - x.getOrDefault("", 2) + x.getOrDefault("", "") + x.getOrDefault(1, 2) + x.getOrDefault("", 2) a.getOrDefault(1, "") - a.getOrDefault("", "") - a.getOrDefault(1, 2) - a.getOrDefault("", 2) + a.getOrDefault("", "") + a.getOrDefault(1, 2) + a.getOrDefault("", 2) b.getOrDefault(1, "") b.getOrDefault("", "") From 09043fb98dfbd20a56ad47621f29dbc54561c249 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 26 Oct 2020 19:17:13 +0300 Subject: [PATCH 005/554] [FIR] JvmMappedScope: add mutable methods or not depending on a class --- .../testData/resolveWithStdlib/j+k/MyMap.txt | 2 +- .../kotlin/fir/resolve/scopes/JvmMappedScopes.kt | 5 +++-- .../jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt | 5 +++-- .../mapGetOrDefault/noTypeSafeBridge.kt | 1 - .../mapGetOrDefault/typeSafeBridge.kt | 1 - .../mapGetOrDefault/typeSafeBridgeNotNullAny.kt | 1 - .../ir/irText/firProblems/AbstractMutableMap.fir.txt | 10 +++++----- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MyMap.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MyMap.txt index 7ba11f34937..c205590d84b 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MyMap.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MyMap.txt @@ -26,7 +26,7 @@ FILE: test.kt ^ String(value) } ) - lval otherResult: R|ft!| = R|/map|.R|FakeOverride!|>|(String(key), String(value)) + lval otherResult: R|kotlin/String| = R|/map|.R|FakeOverride|(String(key), String(value)) lval anotherResult: R|kotlin/String?| = R|/map|.R|FakeOverride|(String(key), String(value)) R|/map|.R|FakeOverride|( = forEach@fun (key: R|ft!|, value: R|ft!|): R|kotlin/Unit| { R|kotlin/io/println|((R|/key|.R|kotlin/Any.toString|(), String(: ), R|/value|.R|kotlin/Any.toString|())) diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt index 14bc65f7aa6..2745335d041 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt @@ -28,12 +28,13 @@ fun wrapScopeWithJvmMapped( scopeSession: ScopeSession ): FirScope { val classId = klass.classId - val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(classId.asSingleFqName().toUnsafe()) + val kotlinUnsafeFqName = classId.asSingleFqName().toUnsafe() + val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(kotlinUnsafeFqName) ?: return declaredMemberScope val symbolProvider = useSiteSession.firSymbolProvider val javaClass = symbolProvider.getClassLikeSymbolByFqName(javaClassId)?.fir as? FirRegularClass ?: return declaredMemberScope - val preparedSignatures = JvmMappedScope.prepareSignatures(javaClass) + val preparedSignatures = JvmMappedScope.prepareSignatures(javaClass, JavaToKotlinClassMap.isMutable(kotlinUnsafeFqName)) return if (preparedSignatures.isNotEmpty()) { javaClass.unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator = false).let { javaClassUseSiteScope -> val jvmMappedScope = JvmMappedScope(declaredMemberScope, javaClassUseSiteScope, preparedSignatures) diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt index 77d4fe295df..b0764383e8b 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt @@ -114,12 +114,13 @@ class JvmMappedScope( ).mapTo(this) { arguments -> "java/lang/Throwable.($arguments)V" } } - fun prepareSignatures(klass: FirRegularClass): Signatures { + fun prepareSignatures(klass: FirRegularClass, isMutable: Boolean): Signatures { val signaturePrefix = klass.symbol.classId.toString() val visibleMethodsByName = mutableMapOf>() JvmBuiltInsSignatures.VISIBLE_METHOD_SIGNATURES.filter { signature -> - signature.startsWith(signaturePrefix) + signature in JvmBuiltInsSignatures.MUTABLE_METHOD_SIGNATURES == isMutable && + signature.startsWith(signaturePrefix) }.map { signature -> // +1 to delete dot before function name signature.substring(signaturePrefix.length + 1) diff --git a/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/noTypeSafeBridge.kt b/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/noTypeSafeBridge.kt index a2b8144fb70..76b1dbadea6 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/noTypeSafeBridge.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/noTypeSafeBridge.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // SKIP_JDK6 // TARGET_BACKEND: JVM // FULL_JDK diff --git a/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridge.kt b/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridge.kt index e065073b68a..30b5d8246d1 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridge.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridge.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // SKIP_JDK6 // TARGET_BACKEND: JVM // FULL_JDK diff --git a/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridgeNotNullAny.kt b/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridgeNotNullAny.kt index a1ba239ddd3..af94cf5946c 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridgeNotNullAny.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/mapGetOrDefault/typeSafeBridgeNotNullAny.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // SKIP_JDK6 // TARGET_BACKEND: JVM // FULL_JDK diff --git a/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt b/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt index 7eb7c1bd1f3..4b18121f51d 100644 --- a/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt +++ b/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt @@ -80,12 +80,12 @@ FILE fqName: fileName:/AbstractMutableMap.kt public abstract fun get (key: K of kotlin.collections.Map): V of kotlin.collections.Map? [operator] declared in kotlin.collections.Map $this: VALUE_PARAMETER name: type:kotlin.collections.Map VALUE_PARAMETER name:key index:0 type:K of .MyMap - FUN FAKE_OVERRIDE name:getOrDefault visibility:public modality:OPEN <> ($this:java.util.Map, p0:K of .MyMap?, p1:V of .MyMap?) returnType:V of .MyMap? [fake_override] + FUN FAKE_OVERRIDE name:getOrDefault visibility:public modality:OPEN <> ($this:kotlin.collections.Map, key:K of .MyMap, defaultValue:V of .MyMap) returnType:V of .MyMap [fake_override] overridden: - public open fun getOrDefault (p0: K of java.util.Map?, p1: V of java.util.Map?): V of java.util.Map? declared in java.util.Map - $this: VALUE_PARAMETER name: type:java.util.Map - VALUE_PARAMETER name:p0 index:0 type:K of .MyMap? - VALUE_PARAMETER name:p1 index:1 type:V of .MyMap? + public open fun getOrDefault (key: K of kotlin.collections.Map, defaultValue: V of kotlin.collections.Map): V of kotlin.collections.Map declared in kotlin.collections.Map + $this: VALUE_PARAMETER name: type:kotlin.collections.Map + VALUE_PARAMETER name:key index:0 type:K of .MyMap + VALUE_PARAMETER name:defaultValue index:1 type:V of .MyMap FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:OPEN <> ($this:kotlin.collections.Map) returnType:kotlin.Boolean [fake_override] overridden: public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.Map From e1a380ec95b3ad1d92f18254b30bbcdc3edf1f21 Mon Sep 17 00:00:00 2001 From: "nataliya.valtman" Date: Fri, 2 Oct 2020 13:43:20 +0300 Subject: [PATCH 006/554] KT-34862 use relative path for incremental build cache --- .../storage/IncrementalFileToPathConverter.kt | 33 ++++++++++ .../IncrementalFileToPathConverterTest.kt | 61 +++++++++++++++++++ .../kotlin/daemon/CompileServiceImpl.kt | 4 +- .../incremental/IncrementalCachesManager.kt | 19 +++--- .../incremental/IncrementalCompilerRunner.kt | 9 +-- .../IncrementalJsCompilerRunner.kt | 6 +- .../IncrementalJvmCompilerRunner.kt | 5 +- .../jetbrains/kotlin/jps/incremental/local.kt | 2 +- .../gradle/tasks/kotlinCompileTaskData.kt | 1 + 9 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt create mode 100644 build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt diff --git a/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt b/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt new file mode 100644 index 00000000000..0e4bf9b6277 --- /dev/null +++ b/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt @@ -0,0 +1,33 @@ +/* + * 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.incremental.storage + +import java.io.File + +open class IncrementalFileToPathConverter(val rootProjectDir: File?) : FileToPathConverter { + //project root dir + private val projectDirPath = rootProjectDir?.normalize()?.absolutePath + + override fun toPath(file: File): String { + val path = file.normalize().absolutePath + return when { + projectDirPath == null || !path.startsWith(projectDirPath) -> path + else -> PROJECT_DIR_PLACEHOLDER + path.substring(projectDirPath.length) + } + } + + override fun toFile(path: String): File = + when { + rootProjectDir != null && path.startsWith(PROJECT_DIR_PLACEHOLDER) -> rootProjectDir.resolve(path.substring(PATH_PREFIX.length)) + else -> File(path) + } + + private companion object { + private const val PROJECT_DIR_PLACEHOLDER = "${'$'}PROJECT_DIR$" + private const val PATH_PREFIX = "$PROJECT_DIR_PLACEHOLDER/" + + } +} \ No newline at end of file diff --git a/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt b/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt new file mode 100644 index 00000000000..b049077b810 --- /dev/null +++ b/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt @@ -0,0 +1,61 @@ +/* + * 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.incremental.storage + +import org.jetbrains.kotlin.TestWithWorkingDir +import org.junit.Test +import java.io.File + +internal class IncrementalFileToPathConverterTest : TestWithWorkingDir() { + + @Test + fun testPathTransform() { + val relativeFilePath = "testFile.txt" + val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath) + + assertEquals("${'$'}PROJECT_DIR${'$'}/$relativeFilePath", transformedPath) + } + + @Test + fun testComplicatedProjectRootPath() { + val relativeFilePath = "testFile.txt" + val transformedPath = testPathTransformation(workingDir.resolve("first/../testDir"), relativeFilePath) + + assertEquals("${'$'}PROJECT_DIR${'$'}/$relativeFilePath", transformedPath) + } + + @Test + fun testInccorectProjectRootPath() { + val relativeFilePath = "testFile.txt" + val transformedPath = testPathTransformation(workingDir.resolve("testDir/"), relativeFilePath) + + assertEquals("${'$'}PROJECT_DIR${'$'}/$relativeFilePath", transformedPath) + } + + @Test + fun testFileOutOfProject() { + val relativeFilePath = "../testFile.txt" + val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath) + + assertEquals("${workingDir.absolutePath}/testFile.txt", transformedPath) + } + + @Test + fun testFileWithExtraSlash() { + val relativeFilePath = "testFile.txt/" + val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath) + + assertEquals("${'$'}PROJECT_DIR${'$'}/testFile.txt", transformedPath) + } + + private fun testPathTransformation(projectRoot: File, relativeFilePath: String): String { + val pathConverter = IncrementalFileToPathConverter(projectRoot) + val testFile = projectRoot.resolve(relativeFilePath) + val transformedPath = pathConverter.toPath(testFile) + assertEquals(testFile.normalize().absolutePath, pathConverter.toFile(transformedPath).normalize().absolutePath) + return transformedPath + } +} \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index 53fa924fe76..11e32d1147a 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -589,6 +589,8 @@ abstract class CompileServiceImplBase( } } + val projectRoot = incrementalCompilationOptions.modulesInfo.projectRoot + val compiler = IncrementalJvmCompilerRunner( workingDir, reporter, @@ -599,7 +601,7 @@ abstract class CompileServiceImplBase( kotlinSourceFilesExtensions = allKotlinExtensions ) return try { - compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles) + compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles, projectRoot) } finally { reporter.flush() } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt index 68d63bc85ad..d66f7a92a7e 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt @@ -17,16 +17,17 @@ package org.jetbrains.kotlin.incremental import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner -import org.jetbrains.kotlin.incremental.storage.FileToCanonicalPathConverter +import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol import java.io.File -private val PATH_CONVERTER = FileToCanonicalPathConverter abstract class IncrementalCachesManager>( cachesRootDir: File, + rootProjectDir: File?, protected val reporter: ICReporter ) { + val pathConverter = IncrementalFileToPathConverter(rootProjectDir) private val caches = arrayListOf() protected fun T.registerCache() { caches.add(this) @@ -36,7 +37,7 @@ abstract class IncrementalCachesManager(cacheDirectory, reporter) { - +) : IncrementalCachesManager(cacheDirectory, rootProjectDir, reporter) { private val jvmCacheDir = File(cacheDirectory, "jvm").apply { mkdirs() } - override val platformCache = IncrementalJvmCache(jvmCacheDir, outputDir, PATH_CONVERTER).apply { registerCache() } + override val platformCache = IncrementalJvmCache(jvmCacheDir, outputDir, pathConverter).apply { registerCache() } } class IncrementalJsCachesManager( cachesRootDir: File, + rootProjectDir: File, reporter: ICReporter, serializerProtocol: SerializerExtensionProtocol -) : IncrementalCachesManager(cachesRootDir, reporter) { - +) : IncrementalCachesManager(cachesRootDir, rootProjectDir, reporter) { private val jsCacheFile = File(cachesRootDir, "js").apply { mkdirs() } - override val platformCache = IncrementalJsCache(jsCacheFile, PATH_CONVERTER, serializerProtocol).apply { registerCache() } + override val platformCache = IncrementalJsCache(jsCacheFile, pathConverter, serializerProtocol).apply { registerCache() } } \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index 80fc775b2ff..fef27c91c2b 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -54,7 +54,7 @@ abstract class IncrementalCompilerRunner< protected open val kotlinSourceFilesExtensions: List = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS protected abstract fun isICEnabled(): Boolean - protected abstract fun createCacheManager(args: Args): CacheManager + protected abstract fun createCacheManager(args: Args, projectDir: File?): CacheManager protected abstract fun destinationDir(args: Args): File fun compile( @@ -63,16 +63,17 @@ abstract class IncrementalCompilerRunner< messageCollector: MessageCollector, // when [providedChangedFiles] is not null, changes are provided by external system (e.g. Gradle) // otherwise we track source files changes ourselves. - providedChangedFiles: ChangedFiles? + providedChangedFiles: ChangedFiles?, + projectDir: File? = null ): ExitCode { assert(isICEnabled()) { "Incremental compilation is not enabled" } - var caches = createCacheManager(args) + var caches = createCacheManager(args, projectDir) fun rebuild(reason: () -> String): ExitCode { reporter.report(reason) caches.close(false) clearLocalStateOnRebuild(args) - caches = createCacheManager(args) + caches = createCacheManager(args, projectDir) if (providedChangedFiles == null) { caches.inputsCache.sourceSnapshotMap.compareAndUpdate(allSourceFiles) } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt index 9709b75e6a4..51d66a2d573 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt @@ -68,7 +68,7 @@ inline fun withJsIC(fn: () -> R): R { } class IncrementalJsCompilerRunner( - workingDir: File, + private val workingDir: File, reporter: ICReporter, buildHistoryFile: File, private val modulesApiHistory: ModulesApiHistory, @@ -82,9 +82,9 @@ class IncrementalJsCompilerRunner( override fun isICEnabled(): Boolean = IncrementalCompilation.isEnabledForJs() - override fun createCacheManager(args: K2JSCompilerArguments): IncrementalJsCachesManager { + override fun createCacheManager(args: K2JSCompilerArguments, projectDir: File?): IncrementalJsCachesManager { val serializerProtocol = if (!args.isIrBackendEnabled()) JsSerializerProtocol else KlibMetadataSerializerProtocol - return IncrementalJsCachesManager(cacheDirectory, reporter, serializerProtocol) + return IncrementalJsCachesManager(cacheDirectory, workingDir, reporter, serializerProtocol) } override fun destinationDir(args: K2JSCompilerArguments): File = diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt index 2694e9337d2..5ba09291e97 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt @@ -120,8 +120,9 @@ class IncrementalJvmCompilerRunner( override fun isICEnabled(): Boolean = IncrementalCompilation.isEnabledForJvm() - override fun createCacheManager(args: K2JVMCompilerArguments): IncrementalJvmCachesManager = - IncrementalJvmCachesManager(cacheDirectory, File(args.destination), reporter) + //TODO + override fun createCacheManager(args: K2JVMCompilerArguments, projectDir: File?): IncrementalJvmCachesManager = + IncrementalJvmCachesManager(cacheDirectory, projectDir, File(args.destination), reporter) override fun destinationDir(args: K2JVMCompilerArguments): File = args.destinationAsFile diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/local.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/local.kt index 2d5b915f069..6f51a4e29b3 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/local.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/local.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.jps.incremental import java.io.File -private val NORMAL_VERSION = 13 +private val NORMAL_VERSION = 14 private val NORMAL_VERSION_FILE_NAME = "format-version.txt" fun localCacheVersionManager(dataRoot: File, isCachesEnabled: Boolean) = diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kotlinCompileTaskData.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kotlinCompileTaskData.kt index 1f46ac220dd..7e2a05fb0b6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kotlinCompileTaskData.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kotlinCompileTaskData.kt @@ -27,6 +27,7 @@ internal open class KotlinCompileTaskData( File(File(compilation.target.project.buildDir, KOTLIN_BUILD_DIR_NAME), taskName) } + //TODO val buildHistoryFile: File by project.provider { File(taskBuildDirectory, "build-history.bin") } From 5e9333773cab661a21f7907b598b1b6a220180c8 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 12 Aug 2020 15:53:29 +0900 Subject: [PATCH 007/554] Remove explicit type arguments: don't report when type argument has annotations #KT-40985 Fixed --- .../intentions/RemoveExplicitTypeArgumentsIntention.kt | 3 ++- .../removeExplicitTypeArguments/hasAnnotation.kt | 7 +++++++ .../kotlin/idea/intentions/IntentionTestGenerated.java | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 idea/testData/intentions/removeExplicitTypeArguments/hasAnnotation.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt index c72e467c993..906ca36beee 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt @@ -44,7 +44,8 @@ class RemoveExplicitTypeArgumentsIntention : SelfTargetingOffsetIndependentInten companion object { fun isApplicableTo(element: KtTypeArgumentList, approximateFlexible: Boolean): Boolean { val callExpression = element.parent as? KtCallExpression ?: return false - if (callExpression.typeArguments.isEmpty()) return false + val typeArguments = callExpression.typeArguments + if (typeArguments.isEmpty() || typeArguments.any { it.typeReference?.annotationEntries?.isNotEmpty() == true }) return false val resolutionFacade = callExpression.getResolutionFacade() val bindingContext = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL_WITH_CFA) diff --git a/idea/testData/intentions/removeExplicitTypeArguments/hasAnnotation.kt b/idea/testData/intentions/removeExplicitTypeArguments/hasAnnotation.kt new file mode 100644 index 00000000000..035d153b97f --- /dev/null +++ b/idea/testData/intentions/removeExplicitTypeArguments/hasAnnotation.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME +annotation class Foo(val value: String) + +fun main() { + val l = listOf<@Foo("bar") String>("") +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index db1b2b4dc6f..ec83710c5e7 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -14466,6 +14466,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/removeExplicitTypeArguments/getterBody.kt"); } + @TestMetadata("hasAnnotation.kt") + public void testHasAnnotation() throws Exception { + runTest("idea/testData/intentions/removeExplicitTypeArguments/hasAnnotation.kt"); + } + @TestMetadata("inapplicableTypeThatIsAFunItCannotBeInferred.kt") public void testInapplicableTypeThatIsAFunItCannotBeInferred() throws Exception { runTest("idea/testData/intentions/removeExplicitTypeArguments/inapplicableTypeThatIsAFunItCannotBeInferred.kt"); From 994cb6f28eebfa508946ef1ea430971b316e0af8 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 27 Oct 2020 17:28:08 +0900 Subject: [PATCH 008/554] Update deprecation message for the Android Extensions plugin --- .../gradle/targets/android/internal/AndroidSubplugin.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt index 99c57d1ac63..4a7fe1ae336 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt @@ -40,9 +40,10 @@ class AndroidExtensionsSubpluginIndicator @Inject internal constructor(private v project.plugins.apply(AndroidSubplugin::class.java) project.logger.warn( - "'kotlin-android-extensions' plugin is deprecated. " + - "Use 'kotlin-parcelize' for the @Parcelize functionality, " + - "and View Binding (https://developer.android.com/topic/libraries/view-binding) instead of synthetic view accessors." + "Warning: The 'kotlin-android-extensions' Gradle plugin is deprecated. " + + "Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start " + + "working with View Binding (https://developer.android.com/topic/libraries/view-binding) " + + "and the 'kotlin-parcelize' plugin." ) } From ac98bc985310bbe2c39410ac48a6b859ee79aa1f Mon Sep 17 00:00:00 2001 From: Alexander Dudinsky Date: Mon, 14 Sep 2020 12:21:24 +0300 Subject: [PATCH 009/554] New highlighting/line markers/diagnostics test infrastructure The current test framework has a number of shortcomings, such as different markups for different kinds, those formats can not be mixed in one test file, lacks composability, re-use of it is complicated This commit contains the first version of the new test runner to which tests will be migrated in the future. --- .../kotlin/checkers/utils/CheckerTestUtil.kt | 2 +- .../codeMetaInfo/AbstractCodeMetaInfoTest.kt | 252 ++++++++++++++++++ .../idea/codeMetaInfo/CodeMetaInfoRenderer.kt | 91 +++++++ .../idea/codeMetaInfo/models/CodeMetaInfo.kt | 106 ++++++++ ...AbstractCodeMetaInfoRenderConfiguration.kt | 131 +++++++++ 5 files changed, 581 insertions(+), 1 deletion(-) create mode 100644 idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt create mode 100644 idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt create mode 100644 idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt create mode 100644 idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt index 9787deadf42..f26b939d807 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt @@ -62,7 +62,7 @@ object CheckerTestUtil { private const val IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE" private const val INDIVIDUAL_DIAGNOSTIC = """(\w+;)?(\w+:)?(\w+)(?:\(((?:".*?")(?:,\s*".*?")*)\))?""" - internal val rangeStartOrEndPattern = Pattern.compile("()|()") + val rangeStartOrEndPattern = Pattern.compile("()|()") val individualDiagnosticPattern: Pattern = Pattern.compile(INDIVIDUAL_DIAGNOSTIC) fun getDiagnosticsIncludingSyntaxErrors( diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt new file mode 100644 index 00000000000..4dd3922b15a --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt @@ -0,0 +1,252 @@ +/* + * 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.codeMetaInfo + +import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase +import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl +import com.intellij.lang.annotation.HighlightSeverity +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.project.DumbService +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VfsUtilCore +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiManager +import com.intellij.psi.impl.PsiManagerImpl +import com.intellij.psi.impl.cache.CacheManager +import com.intellij.psi.impl.source.tree.PsiErrorElementImpl +import com.intellij.psi.impl.source.tree.TreeElement +import com.intellij.psi.impl.source.tree.TreeUtil +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.UsageSearchContext +import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl +import com.intellij.testFramework.runInEdtAndWait +import com.intellij.util.io.exists +import gnu.trove.TIntArrayList +import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest +import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic +import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil +import org.jetbrains.kotlin.checkers.utils.DiagnosticsRenderingConfiguration +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.diagnostics.AbstractDiagnostic +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfoFactory +import org.jetbrains.kotlin.idea.codeMetaInfo.models.DiagnosticCodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRenderConfiguration +import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromTextFile +import org.jetbrains.kotlin.idea.resolve.getDataFlowValueFactory +import org.jetbrains.kotlin.idea.resolve.getLanguageVersionSettings +import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest +import org.jetbrains.kotlin.idea.util.sourceRoots +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File +import java.nio.file.Paths + +class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection) : DaemonAnalyzerTestCase() { + + fun getDiagnosticCodeMetaInfos( + configuration: DiagnosticCodeMetaInfoRenderConfiguration?, + parseDirective: Boolean = true + ): Collection { + val tempSourceKtFile = PsiManager.getInstance(project).findFile(file.virtualFile) as KtFile + val resolutionFacade = tempSourceKtFile.getResolutionFacade() + val (bindingContext, moduleDescriptor) = resolutionFacade.analyzeWithAllCompilerChecks(listOf(tempSourceKtFile)) + val directives = KotlinTestUtils.parseDirectives(file.text) + val diagnosticsFilter = BaseDiagnosticsTest.parseDiagnosticFilterDirective(directives, allowUnderscoreUsage = false) + val diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors( + bindingContext, + file, + markDynamicCalls = false, + dynamicCallDescriptors = mutableListOf(), + configuration = DiagnosticsRenderingConfiguration( + platform = null, // we don't need to attach platform-description string to diagnostic here + withNewInference = false, + languageVersionSettings = resolutionFacade.getLanguageVersionSettings(), + ), + dataFlowValueFactory = resolutionFacade.getDataFlowValueFactory(), + moduleDescriptor = moduleDescriptor as ModuleDescriptorImpl + ).map { it.diagnostic }.filter { !parseDirective || diagnosticsFilter.value(it) } + configuration?.renderParams = directives.contains(BaseDiagnosticsTest.RENDER_DIAGNOSTICS_MESSAGES) + return CodeMetaInfoFactory.getCodeMetaInfo(diagnostics, configuration) + } + + fun getLineMarkerCodeMetaInfos(configuration: LineMarkerRenderConfiguration): Collection { + if ("!CHECK_HIGHLIGHTING" in file.text) + return emptyList() + + CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, TIntArrayList().toNativeArray(), false) + val lineMarkers = DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(file), project) + return CodeMetaInfoFactory.getCodeMetaInfo(lineMarkers, configuration) + } + + fun getHighlightingCodeMetaInfos(configuration: HighlightingRenderConfiguration?): Collection { + val infos = CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, TIntArrayList().toNativeArray(), false) + + return CodeMetaInfoFactory.getCodeMetaInfo(infos, configuration) + } + + fun checkFile(expectedFile: File, project: Project, editor: Editor) { + myProject = project + myPsiManager = PsiManager.getInstance(myProject) as PsiManagerImpl + runInEdtAndWait { + setActiveEditor(editor) + check(expectedFile) + } + } + + fun checkFile(file: VirtualFile, expectedFile: File, project: Project) { + myProject = project + myPsiManager = PsiManager.getInstance(myProject) as PsiManagerImpl + configureByExistingFile(file) + check(expectedFile) + } + + fun check(expectedFile: File) { + + val codeMetaInfoForCheck = mutableListOf() + PsiDocumentManager.getInstance(myProject).commitAllDocuments() + + //to load text + ApplicationManager.getApplication().runWriteAction { TreeUtil.clearCaches(myFile.node as TreeElement) } + + //to initialize caches + if (!DumbService.isDumb(myProject)) { + CacheManager.SERVICE.getInstance(myProject) + .getFilesWithWord("XXX", UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(myProject), true) + } + + for (configuration in codeMetaInfoTypes) { + when (configuration) { + is DiagnosticCodeMetaInfoRenderConfiguration -> { + codeMetaInfoForCheck.addAll(getDiagnosticCodeMetaInfos(configuration)) + } + is HighlightingRenderConfiguration -> { + codeMetaInfoForCheck.addAll(getHighlightingCodeMetaInfos(configuration)) + } + is LineMarkerRenderConfiguration -> { + codeMetaInfoForCheck.addAll(getLineMarkerCodeMetaInfos(configuration)) + } + else -> throw IllegalArgumentException("Unexpected code meta info configuration: $configuration") + } + } + if (codeMetaInfoTypes.any { it is DiagnosticCodeMetaInfoRenderConfiguration } && + !codeMetaInfoTypes.any { it is HighlightingRenderConfiguration } + ) { + checkHighlightErrorItemsInDiagnostics( + getDiagnosticCodeMetaInfos(null, false).filterIsInstance() + ) + } + + val textWithCodeMetaInfo = CodeMetaInfoRenderer.renderTagsToText(codeMetaInfoForCheck, myEditor.document.text) + KotlinTestUtils.assertEqualsToFile( + expectedFile, + textWithCodeMetaInfo.toString() + ) + } + + private fun checkHighlightErrorItemsInDiagnostics( + diagnostics: Collection + ) { + val highlightItems: List = + getHighlightingCodeMetaInfos(null).filter { (it as HighlightingCodeMetaInfo).highlightingInfo.severity == HighlightSeverity.ERROR } + + highlightItems.forEach { highlightingCodeMetaInfo -> + assert( + diagnostics.any { diagnosticCodeMetaInfo -> + diagnosticCodeMetaInfo.start == highlightingCodeMetaInfo.start && + when (diagnosticCodeMetaInfo.diagnostic) { + is SyntaxErrorDiagnostic -> { + val diagnostic: SyntaxErrorDiagnostic = diagnosticCodeMetaInfo.diagnostic + (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description in (diagnostic.psiElement as PsiErrorElementImpl).errorDescription + } + is AbstractDiagnostic<*> -> { + val diagnostic: AbstractDiagnostic<*> = diagnosticCodeMetaInfo.diagnostic + diagnostic.factory.toString() in (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description + } + else -> throw java.lang.IllegalArgumentException("Unknown diagnostic type: ${diagnosticCodeMetaInfo.diagnostic}") + } + }, + ) { "Could not find DIAGNOSTIC for ${(highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo}" } + } + } +} + +abstract class AbstractDiagnosticCodeMetaInfoTest : AbstractCodeMetaInfoTest() { + override fun getConfigurations() = listOf( + DiagnosticCodeMetaInfoRenderConfiguration() + ) +} + +abstract class AbstractLineMarkerCodeMetaInfoTest : AbstractCodeMetaInfoTest() { + override fun getConfigurations() = listOf( + LineMarkerRenderConfiguration() + ) +} + +abstract class AbstractHighlightingCodeMetaInfoTest : AbstractCodeMetaInfoTest() { + override fun getConfigurations() = listOf( + HighlightingRenderConfiguration() + ) +} + +abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { + + open fun getConfigurations() = listOf( + DiagnosticCodeMetaInfoRenderConfiguration(), + LineMarkerRenderConfiguration(), + HighlightingRenderConfiguration() + ) + + protected open fun setupProject(testDataPath: String) { + val dependenciesTxt = File(testDataPath, "dependencies.txt") + require(dependenciesTxt.exists()) { + "${dependenciesTxt.absolutePath} does not exist. dependencies.txt is required" + } + setupMppProjectFromTextFile(File(testDataPath)) + } + + fun doTest(testDataPath: String) { + val testRoot = File(testDataPath) + val checker = CodeMetaInfoTestCase(getConfigurations()) + setupProject(testDataPath) + + for (module in ModuleManager.getInstance(project).modules) { + for (sourceRoot in module.sourceRoots) { + VfsUtilCore.processFilesRecursively(sourceRoot) { file -> + if (file.isDirectory) return@processFilesRecursively true + + checker.checkFile(file, file.findCorrespondingFileInTestDir(sourceRoot, testRoot), project) + true + } + } + } + } + + private fun VirtualFile.findCorrespondingFileInTestDir(containingRoot: VirtualFile, testDir: File): File { + val tempRootPath = Paths.get(containingRoot.path) + val tempProjectDirPath = tempRootPath.parent + val tempSourcePath = Paths.get(path) + + val relativeToProjectRootPath = tempProjectDirPath.relativize(tempSourcePath) + + val testSourcesProjectDirPath = testDir.toPath() + val testSourcePath = testSourcesProjectDirPath.resolve(relativeToProjectRootPath) + + require(testSourcePath.exists()) { + "Can't find file in testdata for copied file $this: checked at path ${testSourcePath.toAbsolutePath()}" + } + + return testSourcePath.toFile() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt new file mode 100644 index 00000000000..326bfb18b04 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt @@ -0,0 +1,91 @@ +/* + * 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.codeMetaInfo + +import com.intellij.util.containers.Stack +import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil +import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import java.io.File + +object CodeMetaInfoRenderer { + + fun renderTagsToText( + codeMetaInfos: List, + originalText: String + ): StringBuffer { + val result = StringBuffer() + if (codeMetaInfos.isEmpty()) { + result.append(originalText) + return result + } + val sortedMetaInfos = getSortedCodeMetaInfos(codeMetaInfos) + val opened = Stack() + + for (i in originalText.indices) { + val c = originalText[i] + var prev: ICodeMetaInfo? = null + + while (!opened.isEmpty() && i == opened.peek().end) { + if (prev == null || prev.start != opened.peek().start) + closeString(result) + prev = opened.pop() + } + if (sortedMetaInfos.any { it.start == i }) { + openStartTag(result) + val matchedCodeMetaInfos = sortedMetaInfos.filter { it.start == i }.toMutableList() + val iterator = matchedCodeMetaInfos.listIterator() + var current: ICodeMetaInfo? = iterator.next() + + while (current != null) { + val next: ICodeMetaInfo? = if (iterator.hasNext()) iterator.next() else null + opened.push(current) + result.append(current.asString()) + when { + next == null -> + closeStartTag(result) + next.end == current.end -> + result.append(", ") + else -> + closeStartAndOpenNewTag(result) + } + current = next + } + } + result.append(c) + } + var prev: ICodeMetaInfo? = null + + while (!opened.isEmpty() && originalText.length == opened.peek().end) { + if (prev == null || prev.start != opened.peek().start) + closeString(result) + prev = opened.pop() + } + return result + } + + private fun getSortedCodeMetaInfos( + metaInfos: Collection, + ): MutableList { + val result = metaInfos.toMutableList() + result.sortWith(Comparator { d1: ICodeMetaInfo, d2: ICodeMetaInfo -> + if (d1.start != d2.start) d1.start - d2.start else d2.end - d1.end + }) + return result + } + + private fun closeString(result: StringBuffer) = result.append("") + private fun openStartTag(result: StringBuffer) = result.append("") + private fun closeStartAndOpenNewTag(result: StringBuffer) = result.append("!> +) : ICodeMetaInfo { + + override val start: Int + get() = lineMarker.startOffset + override val end: Int + get() = lineMarker.endOffset + + val withDescription = true + + override fun asString(): String { + return renderConfiguration!!.asString(this) + } +} + +class HighlightingCodeMetaInfo( + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + val highlightingInfo: HighlightInfo +) : ICodeMetaInfo { + + override val start: Int + get() = highlightingInfo.startOffset + override val end: Int + get() = highlightingInfo.endOffset + + override fun asString(): String { + return renderConfiguration!!.asString(this) + } +} + +object CodeMetaInfoFactory { + private fun createCodeMetaInfo(obj: Any, renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?): Collection { + return when (obj) { + is Diagnostic -> { + if (renderConfiguration != null && renderConfiguration !is DiagnosticCodeMetaInfoRenderConfiguration) + throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") + obj.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj) } + } + is ActualDiagnostic -> { + if (renderConfiguration != null && renderConfiguration !is DiagnosticCodeMetaInfoRenderConfiguration) + throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") + obj.diagnostic.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj.diagnostic) } + } + is HighlightInfo -> { + if (renderConfiguration != null && renderConfiguration !is HighlightingRenderConfiguration) + throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") + listOf(HighlightingCodeMetaInfo(renderConfiguration, obj)) + } + is LineMarkerInfo<*> -> { + if (renderConfiguration != null && renderConfiguration !is LineMarkerRenderConfiguration) + throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") + listOf(LineMarkerCodeMetaInfo(renderConfiguration, obj)) + } + else -> throw IllegalArgumentException("Unknown type for creating CodeMetaInfo object $obj") + } + } + + fun getCodeMetaInfo( + objects: Collection, + renderConfiguration: AbstractCodeMetaInfoRenderConfiguration? + ): Collection { + return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt new file mode 100644 index 00000000000..f5a86b4caca --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt @@ -0,0 +1,131 @@ +/* + * 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.codeMetaInfo.renderConfigurations + +import com.intellij.codeInsight.daemon.impl.HighlightInfo +import com.intellij.lang.annotation.HighlightSeverity +import com.intellij.openapi.util.text.StringUtil +import com.intellij.util.containers.ContainerUtil +import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory1 +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.rendering.* +import org.jetbrains.kotlin.idea.codeMetaInfo.models.DiagnosticCodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.LineMarkerCodeMetaInfo + + +abstract class AbstractCodeMetaInfoRenderConfiguration(var renderParams: Boolean = true) { + + abstract fun asString(codeMetaInfo: ICodeMetaInfo): String + + open fun getAdditionalTags(codeMetaInfo: ICodeMetaInfo) = "" + + protected fun sanitizeLineMarkerTooltip(originalText: String?): String { + if (originalText == null) return "null" + val noHtmlTags = StringUtil.removeHtmlTags(originalText) + return sanitizeLineBreaks(noHtmlTags) + } + + protected fun sanitizeLineBreaks(originalText: String): String { + return StringUtil.replace(originalText, "\n", " ") + } +} + +open class DiagnosticCodeMetaInfoRenderConfiguration( + val withNewInference: Boolean = true, + val renderSeverity: Boolean = false +) : AbstractCodeMetaInfoRenderConfiguration() { + + override fun asString(codeMetaInfo: ICodeMetaInfo): String { + if (codeMetaInfo !is DiagnosticCodeMetaInfo) return "" + return (getTag(codeMetaInfo) + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "") + .replace(Regex("""\r?\n"""), "") + } + + private fun getParamsString(codeMetaInfo: DiagnosticCodeMetaInfo): String { + val params = mutableListOf() + val renderer = when (codeMetaInfo.diagnostic.factory) { + is DebugInfoDiagnosticFactory1 -> DiagnosticWithParameters1Renderer( + "{0}", + Renderers.TO_STRING + ) as DiagnosticRenderer + else -> DefaultErrorMessages.getRendererForDiagnostic(codeMetaInfo.diagnostic) + } + if (renderer is AbstractDiagnosticWithParametersRenderer) { + val renderParameters = renderer.renderParameters(codeMetaInfo.diagnostic) + params.addAll(ContainerUtil.map(renderParameters) { it.toString() }) + } + if (renderSeverity) + params.add("severity='${codeMetaInfo.diagnostic.severity}'") + + params.add(getAdditionalTags(codeMetaInfo)) + + return params.filter { it.isNotEmpty() }.joinToString("; ") + } + + private fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { + return codeMetaInfo.diagnostic.factory.name + } +} + +open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { + override fun asString(codeMetaInfo: ICodeMetaInfo): String { + if (codeMetaInfo !is LineMarkerCodeMetaInfo) return "" + return getTag() + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "" + } + + private fun getTag(): String { + return "LINE_MARKER" + } + + private fun getParamsString(lineMarkerCodeMetaInfo: LineMarkerCodeMetaInfo): String { + val params = mutableListOf() + + if (renderDescription) + params.add("descr='${sanitizeLineMarkerTooltip(lineMarkerCodeMetaInfo.lineMarker.lineMarkerTooltip)}'") + + params.add(getAdditionalTags(lineMarkerCodeMetaInfo)) + + return params.filter { it.isNotEmpty() }.joinToString("; ") + } +} + +open class HighlightingRenderConfiguration( + val renderDescription: Boolean = true, + val renderTextAttributesKey: Boolean = true, + val renderSeverity: Boolean = true +) : AbstractCodeMetaInfoRenderConfiguration() { + + override fun asString(codeMetaInfo: ICodeMetaInfo): String { + if (codeMetaInfo !is HighlightingCodeMetaInfo) return "" + return getTag() + if (renderParams) "(${getParamsString(codeMetaInfo)})" else "" + } + + private fun getTag(): String { + return "HIGHLIGHTING" + } + + private fun getParamsString(highlightingCodeMetaInfo: HighlightingCodeMetaInfo): String { + val params = mutableListOf() + + if (renderSeverity) + params.add("severity='${getSeverity(highlightingCodeMetaInfo.highlightingInfo)}'") + if (renderDescription) + params.add("descr='${sanitizeLineBreaks(highlightingCodeMetaInfo.highlightingInfo.description)}'") + if (renderTextAttributesKey) + params.add("textAttributesKey='${highlightingCodeMetaInfo.highlightingInfo.forcedTextAttributesKey}'") + + params.add(getAdditionalTags(highlightingCodeMetaInfo)) + + return params.filter { it.isNotEmpty() }.joinToString("; ") + } + + private fun getSeverity(highlightingInfo: HighlightInfo): String { + return if (highlightingInfo.severity == HighlightSeverity.INFORMATION) "info" else highlightingInfo.severity.toString() + .toLowerCase() + } +} \ No newline at end of file From 84d24e5b7666b4db621bcd3b1e4d6f96f09eed2a Mon Sep 17 00:00:00 2001 From: Alexander Dudinsky Date: Mon, 14 Sep 2020 12:33:35 +0300 Subject: [PATCH 010/554] Migrate `MultiplatformAnalysisTest` to new test runner --- .../multiplatform/diamondDuplicateActuals/top/top.kt | 4 ++-- .../multiplatform/duplicateActualsImplicit/top/top.kt | 6 +++--- .../duplicateActualsOneWeaklyIncompatible/top/top.kt | 2 +- .../bottom/bottom.kt | 2 +- .../multiplatform/duplicateExpectsExplicit/bottom/bottom.kt | 2 +- .../caches/resolve/AbstractMultiModuleIdeResolveTest.kt | 3 ++- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/idea/testData/multiplatform/diamondDuplicateActuals/top/top.kt b/idea/testData/multiplatform/diamondDuplicateActuals/top/top.kt index b4eed14b822..ace4e1bab24 100644 --- a/idea/testData/multiplatform/diamondDuplicateActuals/top/top.kt +++ b/idea/testData/multiplatform/diamondDuplicateActuals/top/top.kt @@ -2,6 +2,6 @@ package sample -expect class A { - fun foo(): Int +expect class A { + fun foo(): Int } \ No newline at end of file diff --git a/idea/testData/multiplatform/duplicateActualsImplicit/top/top.kt b/idea/testData/multiplatform/duplicateActualsImplicit/top/top.kt index 237a5d750af..502bde6fc0c 100644 --- a/idea/testData/multiplatform/duplicateActualsImplicit/top/top.kt +++ b/idea/testData/multiplatform/duplicateActualsImplicit/top/top.kt @@ -2,7 +2,7 @@ package foo -expect class ActualInMiddleCompatibleInBottom -expect class CompatibleInMiddleActualInBottom +expect class ActualInMiddleCompatibleInBottom +expect class CompatibleInMiddleActualInBottom -expect class CompatibleInMiddleAndBottom \ No newline at end of file +expect class CompatibleInMiddleAndBottom \ No newline at end of file diff --git a/idea/testData/multiplatform/duplicateActualsOneWeaklyIncompatible/top/top.kt b/idea/testData/multiplatform/duplicateActualsOneWeaklyIncompatible/top/top.kt index 2cc6d86f804..587cf9e0e7e 100644 --- a/idea/testData/multiplatform/duplicateActualsOneWeaklyIncompatible/top/top.kt +++ b/idea/testData/multiplatform/duplicateActualsOneWeaklyIncompatible/top/top.kt @@ -2,4 +2,4 @@ package foo -expect class A \ No newline at end of file +expect class A \ No newline at end of file diff --git a/idea/testData/multiplatform/duplicateActualsOneWithStrongIncompatibility/bottom/bottom.kt b/idea/testData/multiplatform/duplicateActualsOneWithStrongIncompatibility/bottom/bottom.kt index 35f51d5efbc..6da3b5ddb84 100644 --- a/idea/testData/multiplatform/duplicateActualsOneWithStrongIncompatibility/bottom/bottom.kt +++ b/idea/testData/multiplatform/duplicateActualsOneWithStrongIncompatibility/bottom/bottom.kt @@ -2,4 +2,4 @@ package foo -actual fun foo(x: Int): Int = x \ No newline at end of file +actual fun foo(x: Int): Int = x \ No newline at end of file diff --git a/idea/testData/multiplatform/duplicateExpectsExplicit/bottom/bottom.kt b/idea/testData/multiplatform/duplicateExpectsExplicit/bottom/bottom.kt index 4b63aec7964..21a344f975a 100644 --- a/idea/testData/multiplatform/duplicateExpectsExplicit/bottom/bottom.kt +++ b/idea/testData/multiplatform/duplicateExpectsExplicit/bottom/bottom.kt @@ -1,3 +1,3 @@ // !RENDER_DIAGNOSTICS_MESSAGES -actual class A \ No newline at end of file +actual class A \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleIdeResolveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleIdeResolveTest.kt index fafe2c3a388..3a04a61725f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleIdeResolveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleIdeResolveTest.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.checkers.utils.DiagnosticsRenderingConfiguration import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromTextFile import org.jetbrains.kotlin.idea.project.KotlinMultiplatformAnalysisModeComponent +import org.jetbrains.kotlin.idea.codeMetaInfo.AbstractDiagnosticCodeMetaInfoTest import org.jetbrains.kotlin.idea.resolve.getDataFlowValueFactory import org.jetbrains.kotlin.idea.resolve.getLanguageVersionSettings import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest @@ -120,7 +121,7 @@ abstract class AbstractHierarchicalExpectActualTest : AbstractMultiModuleIdeReso } } -abstract class AbstractMultiplatformAnalysisTest : AbstractMultiModuleIdeResolveTest() { +abstract class AbstractMultiplatformAnalysisTest : AbstractDiagnosticCodeMetaInfoTest() { override fun getTestDataPath(): String = "${PluginTestCaseBase.getTestDataPathBase()}/multiplatform" override fun setUp() { From 94bf38a7b554c8ea6c0c80995ad6418d40775a57 Mon Sep 17 00:00:00 2001 From: Alexander Dudinsky Date: Sat, 10 Oct 2020 10:05:03 +0300 Subject: [PATCH 011/554] Added support for various platforms for CodeMetaInfo tests. ^KT-41996 The tests need to be able to parse and render CodeMetaInfo for different platforms. For example, we must draw a run gutter a MAC application on OSX, but for a Win application, the gutter should not be drawn at the same time. This commit allows to do such checks. In order to indicate on which platform it should be rendered, it is necessary to specify the platform for a specific CodeMetaInfo in the test data in the format {OSX,Unix,Win}, if the block with platforms is missing, this means that it should be rendered on each platform. - should only be on OSX - should be on any platform --- .../kotlin/checkers/utils/CheckerTestUtil.kt | 2 +- .../codeMetaInfo/AbstractCodeMetaInfoTest.kt | 70 ++++++---- .../idea/codeMetaInfo/CodeMetaInfoParser.kt | 65 ++++++++++ .../idea/codeMetaInfo/CodeMetaInfoRenderer.kt | 53 +++----- .../idea/codeMetaInfo/models/CodeMetaInfo.kt | 122 ++++++++++-------- ...AbstractCodeMetaInfoRenderConfiguration.kt | 54 ++++---- 6 files changed, 226 insertions(+), 140 deletions(-) create mode 100644 idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt index f26b939d807..8c50415868d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt @@ -60,7 +60,7 @@ object CheckerTestUtil { const val OLD_INFERENCE_PREFIX = "OI" private const val IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE" - private const val INDIVIDUAL_DIAGNOSTIC = """(\w+;)?(\w+:)?(\w+)(?:\(((?:".*?")(?:,\s*".*?")*)\))?""" + private const val INDIVIDUAL_DIAGNOSTIC = """(\w+;)?(\w+:)?(\w+)(\{[\w;]+})?(?:\(((?:".*?")(?:,\s*".*?")*)\))?""" val rangeStartOrEndPattern = Pattern.compile("()|()") val individualDiagnosticPattern: Pattern = Pattern.compile(INDIVIDUAL_DIAGNOSTIC) diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt index 4dd3922b15a..b82e39a2f52 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt @@ -32,13 +32,12 @@ import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil import org.jetbrains.kotlin.checkers.utils.DiagnosticsRenderingConfiguration +import org.jetbrains.kotlin.daemon.common.OSKind import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.diagnostics.AbstractDiagnostic +import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfoFactory -import org.jetbrains.kotlin.idea.codeMetaInfo.models.DiagnosticCodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.* import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration @@ -53,12 +52,15 @@ import org.jetbrains.kotlin.test.KotlinTestUtils import java.io.File import java.nio.file.Paths -class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection) : DaemonAnalyzerTestCase() { +class CodeMetaInfoTestCase( + val codeMetaInfoTypes: Collection, + val checkNoDiagnosticError: Boolean = false +) : DaemonAnalyzerTestCase() { fun getDiagnosticCodeMetaInfos( - configuration: DiagnosticCodeMetaInfoRenderConfiguration?, + configuration: DiagnosticCodeMetaInfoRenderConfiguration = DiagnosticCodeMetaInfoRenderConfiguration(), parseDirective: Boolean = true - ): Collection { + ): List { val tempSourceKtFile = PsiManager.getInstance(project).findFile(file.virtualFile) as KtFile val resolutionFacade = tempSourceKtFile.getResolutionFacade() val (bindingContext, moduleDescriptor) = resolutionFacade.analyzeWithAllCompilerChecks(listOf(tempSourceKtFile)) @@ -77,23 +79,23 @@ class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection { + fun getLineMarkerCodeMetaInfos(configuration: LineMarkerRenderConfiguration): Collection { if ("!CHECK_HIGHLIGHTING" in file.text) return emptyList() CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, TIntArrayList().toNativeArray(), false) val lineMarkers = DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(file), project) - return CodeMetaInfoFactory.getCodeMetaInfo(lineMarkers, configuration) + return getCodeMetaInfo(lineMarkers, configuration) } - fun getHighlightingCodeMetaInfos(configuration: HighlightingRenderConfiguration?): Collection { + fun getHighlightingCodeMetaInfos(configuration: HighlightingRenderConfiguration): Collection { val infos = CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, TIntArrayList().toNativeArray(), false) - return CodeMetaInfoFactory.getCodeMetaInfo(infos, configuration) + return getCodeMetaInfo(infos, configuration) } fun checkFile(expectedFile: File, project: Project, editor: Editor) { @@ -113,8 +115,7 @@ class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection() + val codeMetaInfoForCheck = mutableListOf() PsiDocumentManager.getInstance(myProject).commitAllDocuments() //to load text @@ -144,22 +145,46 @@ class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection() + getDiagnosticCodeMetaInfos(DiagnosticCodeMetaInfoRenderConfiguration(), false).filterIsInstance() ) } - + val parsedMetaInfo = CodeMetaInfoParser.getCodeMetaInfoFromText(expectedFile.readText()).toMutableList() + codeMetaInfoForCheck.forEach { codeMetaInfo -> + val correspondingParsed = parsedMetaInfo.firstOrNull { it == codeMetaInfo } + if (correspondingParsed != null) { + parsedMetaInfo.remove(correspondingParsed) + codeMetaInfo.platforms.addAll(correspondingParsed.platforms) + if (correspondingParsed.platforms.isNotEmpty() && OSKind.current.toString() !in correspondingParsed.platforms) + codeMetaInfo.platforms.add(OSKind.current.toString()) + } + } + if (parsedMetaInfo.isNotEmpty()) + parsedMetaInfo.forEach { + if (it.platforms.isNotEmpty() && OSKind.current.toString() !in it.platforms) codeMetaInfoForCheck.add( + it + ) + } val textWithCodeMetaInfo = CodeMetaInfoRenderer.renderTagsToText(codeMetaInfoForCheck, myEditor.document.text) KotlinTestUtils.assertEqualsToFile( expectedFile, textWithCodeMetaInfo.toString() ) + + if (checkNoDiagnosticError) { + val diagnosticsErrors = + getDiagnosticCodeMetaInfos().filter { (it as DiagnosticCodeMetaInfo).diagnostic.severity == Severity.ERROR } + assertTrue( + "Diagnostics with severity ERROR were found: ${diagnosticsErrors.joinToString { it.asString() }}", + diagnosticsErrors.isEmpty() + ) + } } private fun checkHighlightErrorItemsInDiagnostics( diagnostics: Collection ) { - val highlightItems: List = - getHighlightingCodeMetaInfos(null).filter { (it as HighlightingCodeMetaInfo).highlightingInfo.severity == HighlightSeverity.ERROR } + val highlightItems: List = + getHighlightingCodeMetaInfos(HighlightingRenderConfiguration()).filter { (it as HighlightingCodeMetaInfo).highlightingInfo.severity == HighlightSeverity.ERROR } highlightItems.forEach { highlightingCodeMetaInfo -> assert( @@ -201,7 +226,7 @@ abstract class AbstractHighlightingCodeMetaInfoTest : AbstractCodeMetaInfoTest() } abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { - + open val checkNoDiagnosticError get() = false open fun getConfigurations() = listOf( DiagnosticCodeMetaInfoRenderConfiguration(), LineMarkerRenderConfiguration(), @@ -218,7 +243,7 @@ abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { fun doTest(testDataPath: String) { val testRoot = File(testDataPath) - val checker = CodeMetaInfoTestCase(getConfigurations()) + val checker = CodeMetaInfoTestCase(getConfigurations(), checkNoDiagnosticError) setupProject(testDataPath) for (module in ModuleManager.getInstance(project).modules) { @@ -237,16 +262,13 @@ abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { val tempRootPath = Paths.get(containingRoot.path) val tempProjectDirPath = tempRootPath.parent val tempSourcePath = Paths.get(path) - val relativeToProjectRootPath = tempProjectDirPath.relativize(tempSourcePath) - val testSourcesProjectDirPath = testDir.toPath() val testSourcePath = testSourcesProjectDirPath.resolve(relativeToProjectRootPath) require(testSourcePath.exists()) { "Can't find file in testdata for copied file $this: checked at path ${testSourcePath.toAbsolutePath()}" } - return testSourcePath.toFile() } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt new file mode 100644 index 00000000000..0888b5b084e --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt @@ -0,0 +1,65 @@ +/* + * 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.codeMetaInfo + +import com.intellij.util.containers.Stack +import org.jetbrains.kotlin.idea.codeMetaInfo.models.ParsedCodeMetaInfo +import org.junit.Assert + +object CodeMetaInfoParser { + private val openingRegex = "(]+?)!>)".toRegex() + private val closingRegex = "()".toRegex() + + private val descriptionRegex = "\\(\".*?\"\\)".toRegex() + private val platformRegex = "\\{(.+)}".toRegex() + + fun getCodeMetaInfoFromText(renderedText: String): List { + var text = renderedText + val openingMatchResults = Stack() + val closingMatchResults = Stack() + val result = mutableListOf() + + while (true) { + var openingStartOffset = Int.MAX_VALUE + var closingStartOffset = Int.MAX_VALUE + val opening = openingRegex.find(text) + val closing = closingRegex.find(text) + if (opening == null && closing == null) break + + if (opening != null) + openingStartOffset = opening.range.first + if (closing != null) + closingStartOffset = closing.range.first + + text = if (openingStartOffset < closingStartOffset) { + openingMatchResults.push(opening) + text.removeRange(openingStartOffset, opening!!.range.last + 1) + } else { + closingMatchResults.push(closing) + text.removeRange(closingStartOffset, closing!!.range.last + 1) + } + } + if (openingMatchResults.size != closingMatchResults.size) { + Assert.fail("Opening and closing tags counts are not equals") + } + while (!openingMatchResults.isEmpty()) { + val openingMatchResult = openingMatchResults.pop() + val closingMatchResult = closingMatchResults.pop() + val metaInfoWithoutParams = openingMatchResult.groups[2]!!.value.replace(descriptionRegex, "") + metaInfoWithoutParams.split(",").forEach { + val tag = platformRegex.replace(it, "").trim() + val platforms = + if (platformRegex.containsMatchIn(it)) platformRegex.find(it)!!.destructured.component1().split(";") else listOf() + result.add( + ParsedCodeMetaInfo( + openingMatchResult.range.first, closingMatchResult.range.first, platforms.toMutableList(), tag, + ) + ) + } + } + return result + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt index 326bfb18b04..a1f6da6e64f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt @@ -7,13 +7,12 @@ package org.jetbrains.kotlin.idea.codeMetaInfo import com.intellij.util.containers.Stack import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfo import java.io.File object CodeMetaInfoRenderer { - fun renderTagsToText( - codeMetaInfos: List, + codeMetaInfos: List, originalText: String ): StringBuffer { val result = StringBuffer() @@ -22,25 +21,18 @@ object CodeMetaInfoRenderer { return result } val sortedMetaInfos = getSortedCodeMetaInfos(codeMetaInfos) - val opened = Stack() + val opened = Stack() - for (i in originalText.indices) { - val c = originalText[i] - var prev: ICodeMetaInfo? = null - - while (!opened.isEmpty() && i == opened.peek().end) { - if (prev == null || prev.start != opened.peek().start) - closeString(result) - prev = opened.pop() - } - if (sortedMetaInfos.any { it.start == i }) { + for ((i, c) in originalText.withIndex()) { + checkOpenedAndCloseStringIfNeeded(opened, i, result) + val matchedCodeMetaInfos = sortedMetaInfos.filter { it.start == i } + if (matchedCodeMetaInfos.isNotEmpty()) { openStartTag(result) - val matchedCodeMetaInfos = sortedMetaInfos.filter { it.start == i }.toMutableList() val iterator = matchedCodeMetaInfos.listIterator() - var current: ICodeMetaInfo? = iterator.next() + var current: CodeMetaInfo? = iterator.next() while (current != null) { - val next: ICodeMetaInfo? = if (iterator.hasNext()) iterator.next() else null + val next: CodeMetaInfo? = if (iterator.hasNext()) iterator.next() else null opened.push(current) result.append(current.asString()) when { @@ -56,30 +48,27 @@ object CodeMetaInfoRenderer { } result.append(c) } - var prev: ICodeMetaInfo? = null - - while (!opened.isEmpty() && originalText.length == opened.peek().end) { - if (prev == null || prev.start != opened.peek().start) - closeString(result) - prev = opened.pop() - } + checkOpenedAndCloseStringIfNeeded(opened, originalText.length, result) return result } - private fun getSortedCodeMetaInfos( - metaInfos: Collection, - ): MutableList { - val result = metaInfos.toMutableList() - result.sortWith(Comparator { d1: ICodeMetaInfo, d2: ICodeMetaInfo -> - if (d1.start != d2.start) d1.start - d2.start else d2.end - d1.end - }) - return result + private fun getSortedCodeMetaInfos(metaInfos: Collection): List { + return metaInfos.sortedWith(compareBy { it.start }.then(compareByDescending { it.end })) } private fun closeString(result: StringBuffer) = result.append("") private fun openStartTag(result: StringBuffer) = result.append("") private fun closeStartAndOpenNewTag(result: StringBuffer) = result.append("!>, end: Int, result: StringBuffer) { + var prev: CodeMetaInfo? = null + while (!opened.isEmpty() && end == opened.peek().end) { + if (prev == null || prev.start != opened.peek().start) + closeString(result) + prev = opened.pop() + } + } } fun clearFileFromDiagnosticMarkup(file: File) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt index 2e5fea44887..8e483721a5a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt @@ -16,91 +16,103 @@ import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRen import org.jetbrains.kotlin.idea.editor.fixers.end import org.jetbrains.kotlin.idea.editor.fixers.start -interface ICodeMetaInfo { - +interface CodeMetaInfo { val start: Int val end: Int - val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration? + val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration + val platforms: MutableList fun asString(): String + fun getTag(): String } class DiagnosticCodeMetaInfo( override val start: Int, override val end: Int, - override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration, val diagnostic: Diagnostic -) : - ICodeMetaInfo { +) : CodeMetaInfo { + override val platforms: MutableList = mutableListOf() - override fun asString(): String { - return renderConfiguration!!.asString(this) - } + override fun asString() = renderConfiguration.asString(this) + + override fun getTag() = (renderConfiguration as DiagnosticCodeMetaInfoRenderConfiguration).getTag(this) } class LineMarkerCodeMetaInfo( - override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration, val lineMarker: LineMarkerInfo<*> -) : ICodeMetaInfo { - +) : CodeMetaInfo { override val start: Int get() = lineMarker.startOffset override val end: Int get() = lineMarker.endOffset + override val platforms: MutableList = mutableListOf() - val withDescription = true + override fun asString() = renderConfiguration.asString(this) - override fun asString(): String { - return renderConfiguration!!.asString(this) - } + override fun getTag() = (renderConfiguration as LineMarkerRenderConfiguration).getTag() } class HighlightingCodeMetaInfo( - override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration, val highlightingInfo: HighlightInfo -) : ICodeMetaInfo { - +) : CodeMetaInfo { override val start: Int get() = highlightingInfo.startOffset override val end: Int get() = highlightingInfo.endOffset + override val platforms: MutableList = mutableListOf() - override fun asString(): String { - return renderConfiguration!!.asString(this) + override fun asString() = renderConfiguration.asString(this) + + override fun getTag() = (renderConfiguration as HighlightingRenderConfiguration).getTag() +} + +class ParsedCodeMetaInfo( + override val start: Int, + override val end: Int, + override val platforms: MutableList, + private val tag: String +) : CodeMetaInfo { + override val renderConfiguration = object : AbstractCodeMetaInfoRenderConfiguration(false) {} + + override fun asString() = renderConfiguration.asString(this) + + override fun equals(other: Any?): Boolean { + if (other == null || other !is CodeMetaInfo) return false + return this.tag == other.getTag() && this.start == other.start && this.end == other.end + } + + override fun getTag() = tag +} + +fun createCodeMetaInfo(obj: Any, renderConfiguration: AbstractCodeMetaInfoRenderConfiguration): List { + fun errorMessage() = "Unexpected render configuration for object $obj" + return when (obj) { + is Diagnostic -> { + require(renderConfiguration is DiagnosticCodeMetaInfoRenderConfiguration, ::errorMessage) + obj.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj) } + } + is ActualDiagnostic -> { + require(renderConfiguration is DiagnosticCodeMetaInfoRenderConfiguration, ::errorMessage) + obj.diagnostic.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj.diagnostic) } + } + is HighlightInfo -> { + require(renderConfiguration is HighlightingRenderConfiguration, ::errorMessage) + listOf(HighlightingCodeMetaInfo(renderConfiguration, obj)) + } + is LineMarkerInfo<*> -> { + require(renderConfiguration is LineMarkerRenderConfiguration, ::errorMessage) + listOf(LineMarkerCodeMetaInfo(renderConfiguration, obj)) + } + else -> throw IllegalArgumentException("Unknown type for creating CodeMetaInfo object $obj") } } -object CodeMetaInfoFactory { - private fun createCodeMetaInfo(obj: Any, renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?): Collection { - return when (obj) { - is Diagnostic -> { - if (renderConfiguration != null && renderConfiguration !is DiagnosticCodeMetaInfoRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - obj.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj) } - } - is ActualDiagnostic -> { - if (renderConfiguration != null && renderConfiguration !is DiagnosticCodeMetaInfoRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - obj.diagnostic.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj.diagnostic) } - } - is HighlightInfo -> { - if (renderConfiguration != null && renderConfiguration !is HighlightingRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - listOf(HighlightingCodeMetaInfo(renderConfiguration, obj)) - } - is LineMarkerInfo<*> -> { - if (renderConfiguration != null && renderConfiguration !is LineMarkerRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - listOf(LineMarkerCodeMetaInfo(renderConfiguration, obj)) - } - else -> throw IllegalArgumentException("Unknown type for creating CodeMetaInfo object $obj") - } - } - - fun getCodeMetaInfo( - objects: Collection, - renderConfiguration: AbstractCodeMetaInfoRenderConfiguration? - ): Collection { - return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } - } -} \ No newline at end of file +fun getCodeMetaInfo( + objects: List, + renderConfiguration: AbstractCodeMetaInfoRenderConfiguration +): List { + return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt index f5a86b4caca..efb82bb2380 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations -import com.intellij.codeInsight.daemon.impl.HighlightInfo -import com.intellij.lang.annotation.HighlightSeverity import com.intellij.openapi.util.text.StringUtil import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory1 @@ -14,39 +12,48 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.rendering.* import org.jetbrains.kotlin.idea.codeMetaInfo.models.DiagnosticCodeMetaInfo import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfo import org.jetbrains.kotlin.idea.codeMetaInfo.models.LineMarkerCodeMetaInfo abstract class AbstractCodeMetaInfoRenderConfiguration(var renderParams: Boolean = true) { - abstract fun asString(codeMetaInfo: ICodeMetaInfo): String + open fun asString(codeMetaInfo: CodeMetaInfo) = codeMetaInfo.getTag() + getPlatformsString(codeMetaInfo) - open fun getAdditionalTags(codeMetaInfo: ICodeMetaInfo) = "" + open fun getAdditionalParams(codeMetaInfo: CodeMetaInfo) = "" protected fun sanitizeLineMarkerTooltip(originalText: String?): String { if (originalText == null) return "null" - val noHtmlTags = StringUtil.removeHtmlTags(originalText) + val noHtmlTags = StringUtil.removeHtmlTags(originalText).replace(" ", "") return sanitizeLineBreaks(noHtmlTags) } protected fun sanitizeLineBreaks(originalText: String): String { return StringUtil.replace(originalText, "\n", " ") } + + protected fun getPlatformsString(codeMetaInfo: CodeMetaInfo): String { + if (codeMetaInfo.platforms.isEmpty()) return "" + return "{${codeMetaInfo.platforms.joinToString(";")}}" + } } open class DiagnosticCodeMetaInfoRenderConfiguration( val withNewInference: Boolean = true, val renderSeverity: Boolean = false ) : AbstractCodeMetaInfoRenderConfiguration() { + private val crossPlatformLineBreak = """\r?\n""".toRegex() - override fun asString(codeMetaInfo: ICodeMetaInfo): String { + override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is DiagnosticCodeMetaInfo) return "" - return (getTag(codeMetaInfo) + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "") - .replace(Regex("""\r?\n"""), "") + return (getTag(codeMetaInfo) + + getPlatformsString(codeMetaInfo) + + getParamsString(codeMetaInfo)) + .replace(crossPlatformLineBreak, "") } private fun getParamsString(codeMetaInfo: DiagnosticCodeMetaInfo): String { + if (!renderParams) return "" val params = mutableListOf() val renderer = when (codeMetaInfo.diagnostic.factory) { is DebugInfoDiagnosticFactory1 -> DiagnosticWithParameters1Renderer( @@ -62,25 +69,23 @@ open class DiagnosticCodeMetaInfoRenderConfiguration( if (renderSeverity) params.add("severity='${codeMetaInfo.diagnostic.severity}'") - params.add(getAdditionalTags(codeMetaInfo)) + params.add(getAdditionalParams(codeMetaInfo)) - return params.filter { it.isNotEmpty() }.joinToString("; ") + return "(\"${params.filter { it.isNotEmpty() }.joinToString("; ")}\")" } - private fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { + fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { return codeMetaInfo.diagnostic.factory.name } } open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { - override fun asString(codeMetaInfo: ICodeMetaInfo): String { + override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is LineMarkerCodeMetaInfo) return "" return getTag() + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "" } - private fun getTag(): String { - return "LINE_MARKER" - } + fun getTag() = "LINE_MARKER" private fun getParamsString(lineMarkerCodeMetaInfo: LineMarkerCodeMetaInfo): String { val params = mutableListOf() @@ -88,7 +93,7 @@ open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) if (renderDescription) params.add("descr='${sanitizeLineMarkerTooltip(lineMarkerCodeMetaInfo.lineMarker.lineMarkerTooltip)}'") - params.add(getAdditionalTags(lineMarkerCodeMetaInfo)) + params.add(getAdditionalParams(lineMarkerCodeMetaInfo)) return params.filter { it.isNotEmpty() }.joinToString("; ") } @@ -100,32 +105,25 @@ open class HighlightingRenderConfiguration( val renderSeverity: Boolean = true ) : AbstractCodeMetaInfoRenderConfiguration() { - override fun asString(codeMetaInfo: ICodeMetaInfo): String { + override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is HighlightingCodeMetaInfo) return "" return getTag() + if (renderParams) "(${getParamsString(codeMetaInfo)})" else "" } - private fun getTag(): String { - return "HIGHLIGHTING" - } + fun getTag() = "HIGHLIGHTING" private fun getParamsString(highlightingCodeMetaInfo: HighlightingCodeMetaInfo): String { val params = mutableListOf() if (renderSeverity) - params.add("severity='${getSeverity(highlightingCodeMetaInfo.highlightingInfo)}'") + params.add("severity='${highlightingCodeMetaInfo.highlightingInfo.severity}'") if (renderDescription) params.add("descr='${sanitizeLineBreaks(highlightingCodeMetaInfo.highlightingInfo.description)}'") if (renderTextAttributesKey) params.add("textAttributesKey='${highlightingCodeMetaInfo.highlightingInfo.forcedTextAttributesKey}'") - params.add(getAdditionalTags(highlightingCodeMetaInfo)) + params.add(getAdditionalParams(highlightingCodeMetaInfo)) return params.filter { it.isNotEmpty() }.joinToString("; ") } - - private fun getSeverity(highlightingInfo: HighlightInfo): String { - return if (highlightingInfo.severity == HighlightSeverity.INFORMATION) "info" else highlightingInfo.severity.toString() - .toLowerCase() - } } \ No newline at end of file From 0e7e657657cc58cc1825f3a8603d1b027c9cd990 Mon Sep 17 00:00:00 2001 From: Alexander Dudinsky Date: Sat, 10 Oct 2020 10:07:31 +0300 Subject: [PATCH 012/554] Migrate `MultiModuleLineMarkerTest` to the new CodeMetaInfo test infrastructure --- .../checkers/diagnostics/TextDiagnostic.kt | 2 +- .../dependencies.txt | 4 ++++ .../jvm/jvm.kt | 2 +- .../actualDerived/common/common.kt | 4 ++-- .../actualDerived/dependencies.txt | 4 ++++ .../actualEnumEntries/dependencies.txt | 4 ++++ .../actualEnumEntries/jvm/jvm.kt | 8 +++---- .../dependencies.txt | 4 ++++ .../actualEnumEntriesInOneLine/jvm/jvm.kt | 2 +- .../actualWithOverload/dependencies.txt | 4 ++++ .../common/common.kt | 6 ++--- .../dependencies.txt | 4 ++++ .../expectEnumEntries/common/common.kt | 8 +++---- .../expectEnumEntries/dependencies.txt | 4 ++++ .../common/common.kt | 2 +- .../dependencies.txt | 4 ++++ .../common/common.kt | 4 ++-- .../dependencies.txt | 4 ++++ .../common/common.kt | 6 ++--- .../dependencies.txt | 1 + .../expectWithOverload/dependencies.txt | 4 ++++ .../fromActualAnnotation/dependencies.txt | 4 ++++ .../fromActualAnnotation/jvm/jvm.kt | 6 ++--- .../dependencies.txt | 4 ++++ .../jvm/jvm.kt | 6 ++--- .../fromActualCompanion/dependencies.txt | 4 ++++ .../fromActualCompanion/jvm/jvm.kt | 4 ++-- .../dependencies.txt | 4 ++++ .../fromActualPrimaryConstructor/jvm/jvm.kt | 4 ++-- .../fromActualSealedClass/dependencies.txt | 4 ++++ .../fromActualSealedClass/jvm/jvm.kt | 10 ++++---- .../dependencies.txt | 4 ++++ .../fromActualSecondaryConstructor/jvm/jvm.kt | 4 ++-- .../fromActualTypeAlias/dependencies.txt | 4 ++++ .../fromActualTypeAlias/jvm/jvm.kt | 2 +- .../fromClassToAlias/common/common.kt | 2 +- .../fromClassToAlias/dependencies.txt | 4 ++++ .../dependencies.txt | 4 ++++ .../fromClassToJavaAliasInTest/jvm/empty.kt | 2 +- .../fromCommonToJvmHeader/common/common.kt | 10 ++++---- .../fromCommonToJvmHeader/dependencies.txt | 4 ++++ .../fromCommonToJvmImpl/dependencies.txt | 4 ++++ .../fromCommonToJvmImpl/jvm/jvm.kt | 10 ++++---- .../fromExpectCompanion/common/common.kt | 4 ++-- .../fromExpectCompanion/dependencies.txt | 4 ++++ .../fromExpectedAnnotation/common/common.kt | 6 ++--- .../fromExpectedAnnotation/dependencies.txt | 4 ++++ .../common/common.kt | 4 ++-- .../dependencies.txt | 4 ++++ .../fromExpectedSealedClass/common/common.kt | 10 ++++---- .../fromExpectedSealedClass/dependencies.txt | 4 ++++ .../common/common.kt | 4 ++-- .../dependencies.txt | 4 ++++ .../fromExpectedTypeAlias/common/common.kt | 2 +- .../fromExpectedTypeAlias/dependencies.txt | 4 ++++ .../common/common.kt | 20 ++++++++-------- .../dependencies.txt | 4 ++++ .../common/common.kt | 20 ++++++++-------- .../dependencies.txt | 4 ++++ .../dependencies.txt | 4 ++++ .../jvm/jvm.kt | 10 ++++---- .../common/common.kt | 4 ++-- .../dependencies.txt | 6 +++++ .../dependencies.txt | 4 ++++ .../transitive/base_common/common.kt | 2 +- .../transitive/dependencies.txt | 6 +++++ .../user.kt | 0 .../transitiveCommon/dependencies.txt | 6 +++++ .../user.kt | 0 .../transitiveCommon/user_jvm/jvm.kt | 3 +++ .../user_jvm_dep(base-common)/jvm.kt | 3 --- .../withOverloads/common/common.kt | 4 ++-- .../withOverloads/dependencies.txt | 4 ++++ .../AbstractMultiModuleLineMarkerTest.kt | 16 ++----------- .../codeMetaInfo/AbstractCodeMetaInfoTest.kt | 20 +++++++++++----- ...AbstractCodeMetaInfoRenderConfiguration.kt | 23 ++++++++++++------- 76 files changed, 278 insertions(+), 128 deletions(-) create mode 100644 idea/testData/multiModuleLineMarker/actualConstructorWithProperties/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/actualDerived/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/actualEnumEntries/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/actualWithOverload/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/expectConstructorWithProperties/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/expectEnumEntries/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/expectWithActualInSameModule/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/expectWithOverload/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualAnnotation/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualCompanion/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualSealedClass/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromActualTypeAlias/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromClassToAlias/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromExpectCompanion/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromExpectedAnnotation/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromExpectedSealedClass/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/topLevelFunWithKotlinTest/dependencies.txt create mode 100644 idea/testData/multiModuleLineMarker/transitive/dependencies.txt rename idea/testData/multiModuleLineMarker/transitive/{user_jvm_dep(base-jvm)_dep(base-common) => user_jvm}/user.kt (100%) create mode 100644 idea/testData/multiModuleLineMarker/transitiveCommon/dependencies.txt rename idea/testData/multiModuleLineMarker/transitiveCommon/{user_common_dep(base-common) => user_common}/user.kt (100%) create mode 100644 idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm/jvm.kt delete mode 100644 idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm_dep(base-common)/jvm.kt create mode 100644 idea/testData/multiModuleLineMarker/withOverloads/dependencies.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/checkers/diagnostics/TextDiagnostic.kt b/compiler/frontend/src/org/jetbrains/kotlin/checkers/diagnostics/TextDiagnostic.kt index 327c76c341a..10b44a4f9c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/checkers/diagnostics/TextDiagnostic.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/checkers/diagnostics/TextDiagnostic.kt @@ -107,7 +107,7 @@ class TextDiagnostic( extractDataBefore(matcher.group(2), ":") val name = matcher.group(3) - val parameters = matcher.group(4) ?: return TextDiagnostic( + val parameters = matcher.group(5) ?: return TextDiagnostic( name, platform, null, diff --git a/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/dependencies.txt b/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/jvm/jvm.kt index 463d99ff1d1..6751687e89c 100644 --- a/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/actualConstructorWithProperties/jvm/jvm.kt @@ -1,4 +1,4 @@ -actual class WithConstructor actual constructor(actual val x: Int, actual val s: String) +actual class WithConstructor actual constructor(actual val x: Int, actual val s: String) /* LINEMARKER: Has declaration in common module diff --git a/idea/testData/multiModuleLineMarker/actualDerived/common/common.kt b/idea/testData/multiModuleLineMarker/actualDerived/common/common.kt index 13b3b1fe791..0dfc7338f67 100644 --- a/idea/testData/multiModuleLineMarker/actualDerived/common/common.kt +++ b/idea/testData/multiModuleLineMarker/actualDerived/common/common.kt @@ -1,6 +1,6 @@ -open class ExpectedChild [testModule_Common]
    ExpectedChild [testModule_JVM]
    SimpleChild
Click or press Ctrl+Alt+B to navigate
">SimpleParent
+open class SimpleParent -expect class ExpectedChild : SimpleParent +expect class ExpectedChild : SimpleParent class SimpleChild : SimpleParent() \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/actualDerived/dependencies.txt b/idea/testData/multiModuleLineMarker/actualDerived/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/actualDerived/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/actualEnumEntries/dependencies.txt b/idea/testData/multiModuleLineMarker/actualEnumEntries/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/actualEnumEntries/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/actualEnumEntries/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/actualEnumEntries/jvm/jvm.kt index c7848f8b937..0fb926b4985 100644 --- a/idea/testData/multiModuleLineMarker/actualEnumEntries/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/actualEnumEntries/jvm/jvm.kt @@ -1,8 +1,8 @@ package test -actual enum class Enum { - A, - B, - C, +actual enum class Enum { + A, + B, + C, D } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/dependencies.txt b/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/jvm/jvm.kt index 0c6e2c14140..35b3db6102e 100644 --- a/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/actualEnumEntriesInOneLine/jvm/jvm.kt @@ -1,6 +1,6 @@ package test -actual enum class Enum { A, B, C } +actual enum class Enum { A, B, C } /* LINEMARKER: Has declaration in common module diff --git a/idea/testData/multiModuleLineMarker/actualWithOverload/dependencies.txt b/idea/testData/multiModuleLineMarker/actualWithOverload/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/actualWithOverload/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/common/common.kt b/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/common/common.kt index 7a5e725d644..2b5478c0768 100644 --- a/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/common/common.kt +++ b/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/common/common.kt @@ -1,5 +1,5 @@ -expect class WithConstructor(x: Int, s: String) { - val x: Int +expect class WithConstructor(x: Int, s: String) { + val x: Int - val s: String + val s: String } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/dependencies.txt b/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/expectConstructorWithProperties/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectEnumEntries/common/common.kt b/idea/testData/multiModuleLineMarker/expectEnumEntries/common/common.kt index 299bd98f447..0ed0bf85630 100644 --- a/idea/testData/multiModuleLineMarker/expectEnumEntries/common/common.kt +++ b/idea/testData/multiModuleLineMarker/expectEnumEntries/common/common.kt @@ -1,7 +1,7 @@ package test -expect enum class Enum { - A, - B, - C +expect enum class Enum { + A, + B, + C } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectEnumEntries/dependencies.txt b/idea/testData/multiModuleLineMarker/expectEnumEntries/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/expectEnumEntries/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/common/common.kt b/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/common/common.kt index 065dd8f0523..cbf5dcf0675 100644 --- a/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/common/common.kt +++ b/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/common/common.kt @@ -1,6 +1,6 @@ package test -expect enum class Enum { A, B, C, D } +expect enum class Enum { A, B, C, D } /* LINEMARKER: Has actuals in JVM diff --git a/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/dependencies.txt b/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/expectEnumEntriesInOneLine/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/common/common.kt b/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/common/common.kt index 6c0f30ab284..d66935c2213 100644 --- a/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/common/common.kt +++ b/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/common/common.kt @@ -1,7 +1,7 @@ package test -expect enum class Enum { - A, B, C, D +expect enum class Enum { + A, B, C, D } /* diff --git a/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/dependencies.txt b/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/expectEnumWithEnumEntriesInOneLine/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/common/common.kt b/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/common/common.kt index fa233eae1d0..53282e881ae 100644 --- a/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/common/common.kt +++ b/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/common/common.kt @@ -1,9 +1,9 @@ package sample -expect fun sameFile() +expect fun sameFile() -actual fun sameFile() = Unit +actual fun sameFile() = Unit -expect fun sameModule() +expect fun sameModule() fun noExpectActualDeclaration() = Unit \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/dependencies.txt b/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/dependencies.txt new file mode 100644 index 00000000000..8da128002e5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/expectWithActualInSameModule/dependencies.txt @@ -0,0 +1 @@ +MODULE common { platform=[JVM, JS, Native] } diff --git a/idea/testData/multiModuleLineMarker/expectWithOverload/dependencies.txt b/idea/testData/multiModuleLineMarker/expectWithOverload/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/expectWithOverload/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualAnnotation/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualAnnotation/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualAnnotation/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualAnnotation/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualAnnotation/jvm/jvm.kt index 6e2612c3fda..c8e65651448 100644 --- a/idea/testData/multiModuleLineMarker/fromActualAnnotation/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualAnnotation/jvm/jvm.kt @@ -1,4 +1,4 @@ -actual annotation class Ann actual constructor( - actual val x: Int, - actual val y: String +actual annotation class Ann actual constructor( + actual val x: Int, + actual val y: String ) diff --git a/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/jvm/jvm.kt index e44371c8b76..5abadf3d27d 100644 --- a/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualAnnotationWithParametersInOneLine/jvm/jvm.kt @@ -1,6 +1,6 @@ -actual annotation class Ann( - actual val x: Int, actual val y: String, - actual val z: Double, actual val b: Boolean +actual annotation class Ann( + actual val x: Int, actual val y: String, + actual val z: Double, actual val b: Boolean ) /* diff --git a/idea/testData/multiModuleLineMarker/fromActualCompanion/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualCompanion/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualCompanion/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualCompanion/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualCompanion/jvm/jvm.kt index ec3badfc50f..91f4d34938c 100644 --- a/idea/testData/multiModuleLineMarker/fromActualCompanion/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualCompanion/jvm/jvm.kt @@ -1,5 +1,5 @@ -actual class WithCompanion { - actual companion object { +actual class WithCompanion { + actual companion object { } } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/jvm/jvm.kt index 604846fad0f..960c0b31601 100644 --- a/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualPrimaryConstructor/jvm/jvm.kt @@ -1,5 +1,5 @@ -actual class NoConstructor2(name: String) { +actual class NoConstructor2(name: String) { val myName = name - actual fun extraFun() {} + actual fun extraFun() {} } diff --git a/idea/testData/multiModuleLineMarker/fromActualSealedClass/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualSealedClass/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualSealedClass/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualSealedClass/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualSealedClass/jvm/jvm.kt index 87cd13f446e..56128a1ab2a 100644 --- a/idea/testData/multiModuleLineMarker/fromActualSealedClass/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualSealedClass/jvm/jvm.kt @@ -1,10 +1,10 @@ -actual sealed class Sealed { +actual sealed class Sealed { - actual object Sealed1 : Sealed() + actual object Sealed1 : Sealed() - actual class Sealed2 : Sealed() { - actual val x = 42 - actual fun foo() = "" + actual class Sealed2 : Sealed() { + actual val x = 42 + actual fun foo() = "" } } diff --git a/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/jvm/jvm.kt index bb6ef41c824..b7e0b67ea7b 100644 --- a/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualSecondaryConstructor/jvm/jvm.kt @@ -1,5 +1,5 @@ -actual class SecondaryConstructor { - actual constructor(name: String, surname: String) {} +actual class SecondaryConstructor { + actual constructor(name: String, surname: String) {} } diff --git a/idea/testData/multiModuleLineMarker/fromActualTypeAlias/dependencies.txt b/idea/testData/multiModuleLineMarker/fromActualTypeAlias/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromActualTypeAlias/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromActualTypeAlias/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromActualTypeAlias/jvm/jvm.kt index 7ae6035b463..a727af437aa 100644 --- a/idea/testData/multiModuleLineMarker/fromActualTypeAlias/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromActualTypeAlias/jvm/jvm.kt @@ -2,5 +2,5 @@ class Some { val x: String = "Some" } -actual typealias TypeAlias = Some +actual typealias TypeAlias = Some diff --git a/idea/testData/multiModuleLineMarker/fromClassToAlias/common/common.kt b/idea/testData/multiModuleLineMarker/fromClassToAlias/common/common.kt index 7a8fcddc333..9ff4aa951af 100644 --- a/idea/testData/multiModuleLineMarker/fromClassToAlias/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromClassToAlias/common/common.kt @@ -1,4 +1,4 @@ -expect class Header { +expect class Header { } diff --git a/idea/testData/multiModuleLineMarker/fromClassToAlias/dependencies.txt b/idea/testData/multiModuleLineMarker/fromClassToAlias/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromClassToAlias/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/dependencies.txt b/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/jvm/empty.kt b/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/jvm/empty.kt index 41cf458d099..680c20354e8 100644 --- a/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/jvm/empty.kt +++ b/idea/testData/multiModuleLineMarker/fromClassToJavaAliasInTest/jvm/empty.kt @@ -1 +1 @@ -actual typealias Expected = ExpectedImpl \ No newline at end of file +actual typealias Expected = ExpectedImpl \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/common/common.kt b/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/common/common.kt index 6477429372c..0144f6531ec 100644 --- a/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/common/common.kt @@ -1,11 +1,11 @@ -expect class Header { - fun foo(): Int +expect class Header { + fun foo(): Int } -expect class Incomplete { +expect class Incomplete { fun foo(): Int } -expect fun foo(arg: Int): String +expect fun foo(arg: Int): String -expect val flag: Boolean +expect val flag: Boolean diff --git a/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/dependencies.txt b/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromCommonToJvmHeader/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/dependencies.txt b/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/jvm/jvm.kt index 6b880d726aa..dcbf99a22d2 100644 --- a/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/fromCommonToJvmImpl/jvm/jvm.kt @@ -1,11 +1,11 @@ -actual class Header { - actual fun foo() = 42 +actual class Header { + actual fun foo() = 42 } -actual class Incomplete +actual class Incomplete -actual fun foo(arg: Int) = arg.toString() +actual fun foo(arg: Int) = arg.toString() -actual val flag = true +actual val flag = true diff --git a/idea/testData/multiModuleLineMarker/fromExpectCompanion/common/common.kt b/idea/testData/multiModuleLineMarker/fromExpectCompanion/common/common.kt index c33599807b5..eebedf407a3 100644 --- a/idea/testData/multiModuleLineMarker/fromExpectCompanion/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromExpectCompanion/common/common.kt @@ -1,5 +1,5 @@ -expect class WithCompanion { - companion object { +expect class WithCompanion { + companion object { } } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectCompanion/dependencies.txt b/idea/testData/multiModuleLineMarker/fromExpectCompanion/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromExpectCompanion/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/common/common.kt b/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/common/common.kt index cd7bdf8b692..99190697843 100644 --- a/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/common/common.kt @@ -1,4 +1,4 @@ -expect annotation class Ann( - val x: Int, - val y: String +expect annotation class Ann( + val x: Int, + val y: String ) \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/dependencies.txt b/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromExpectedAnnotation/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/common/common.kt b/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/common/common.kt index d5eeccb138e..cbf70367676 100644 --- a/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/common/common.kt @@ -1,3 +1,3 @@ -expect class NoConstructor2 { - fun extraFun() +expect class NoConstructor2 { + fun extraFun() } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/dependencies.txt b/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromExpectedPrimaryConstructor/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/common/common.kt b/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/common/common.kt index 94ca21d39a9..b1a37cd2667 100644 --- a/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/common/common.kt @@ -1,9 +1,9 @@ -expect sealed class Sealed { +expect sealed class Sealed { - object Sealed1 : Sealed + object Sealed1 : Sealed - class Sealed2 : Sealed { - val x: Int - fun foo(): String + class Sealed2 : Sealed { + val x: Int + fun foo(): String } } diff --git a/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/dependencies.txt b/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromExpectedSealedClass/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/common/common.kt b/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/common/common.kt index f20aba4ec3c..9fed52110ad 100644 --- a/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/common/common.kt @@ -1,3 +1,3 @@ -expect class SecondaryConstructor{ - constructor(name: String, surname: String) +expect class SecondaryConstructor{ + constructor(name: String, surname: String) } diff --git a/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/dependencies.txt b/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromExpectedSecondaryConstructor/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/common/common.kt b/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/common/common.kt index c19aa8bb8a1..8615ed4a5d5 100644 --- a/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/common/common.kt +++ b/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/common/common.kt @@ -1,3 +1,3 @@ -expect class TypeAlias { +expect class TypeAlias { val x: String } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/dependencies.txt b/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/fromExpectedTypeAlias/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/common/common.kt b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/common/common.kt index 26251a07f1f..1d9bd2cc5c1 100644 --- a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/common/common.kt +++ b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/common/common.kt @@ -1,21 +1,21 @@ package test -open class SimpleParent { - open fun foo(n: Int) {} - open val bar: Int get() = 1 +open class SimpleParent { + open fun foo(n: Int) {} + open val bar: Int get() = 1 } -expect open class ExpectedChild : SimpleParent { - override fun foo(n: Int) - override val bar: Int +expect open class ExpectedChild : SimpleParent { + override fun foo(n: Int) + override val bar: Int } class ExpectedChildChild : ExpectedChild() { - override fun foo(n: Int) {} - override val bar: Int get() = 1 + override fun foo(n: Int) {} + override val bar: Int get() = 1 } class SimpleChild : SimpleParent() { - override fun foo(n: Int) {} - override val bar: Int get() = 1 + override fun foo(n: Int) {} + override val bar: Int get() = 1 } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/dependencies.txt b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSide/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/common/common.kt b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/common/common.kt index c5fb5905f01..5443d3b24bb 100644 --- a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/common/common.kt +++ b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/common/common.kt @@ -1,21 +1,21 @@ package test -open class SimpleParent { - open fun `foo fun`(n: Int) {} - open val `bar fun`: Int get() = 1 +open class SimpleParent { + open fun `foo fun`(n: Int) {} + open val `bar fun`: Int get() = 1 } -expect open class ExpectedChild : SimpleParent { - override fun `foo fun`(n: Int) - override val `bar fun`: Int +expect open class ExpectedChild : SimpleParent { + override fun `foo fun`(n: Int) + override val `bar fun`: Int } class ExpectedChildChild : ExpectedChild() { - override fun `foo fun`(n: Int) {} - override val `bar fun`: Int get() = 1 + override fun `foo fun`(n: Int) {} + override val `bar fun`: Int get() = 1 } class SimpleChild : SimpleParent() { - override fun `foo fun`(n: Int) {} - override val `bar fun`: Int get() = 1 + override fun `foo fun`(n: Int) {} + override val `bar fun`: Int get() = 1 } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/dependencies.txt b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassCommonSideNonJavaIds/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/dependencies.txt b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/jvm/jvm.kt b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/jvm/jvm.kt index 490d72915ea..4111f1ed22a 100644 --- a/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/jvm/jvm.kt +++ b/idea/testData/multiModuleLineMarker/hierarchyWithExpectClassPlatformSide/jvm/jvm.kt @@ -1,11 +1,11 @@ package test -actual open class ExpectedChild : SimpleParent() { - actual override fun foo(n: Int) {} - actual override val bar: Int get() = 1 +actual open class ExpectedChild : SimpleParent() { + actual override fun foo(n: Int) {} + actual override val bar: Int get() = 1 } class ExpectedChildChildJvm : ExpectedChild() { - override fun foo(n: Int) {} - override val bar: Int get() = 1 + override fun foo(n: Int) {} + override val bar: Int get() = 1 } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/common/common.kt b/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/common/common.kt index dd5b060371c..418f4218b61 100644 --- a/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/common/common.kt +++ b/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/common/common.kt @@ -1,5 +1,5 @@ -interface I { - suspend fun foo(s: String) +interface I { + suspend fun foo(s: String) } /* diff --git a/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/dependencies.txt b/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/dependencies.txt new file mode 100644 index 00000000000..5820c9936e0 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/suspendImplInPlatformModules/dependencies.txt @@ -0,0 +1,6 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } +MODULE js { platform=[JS] } + +jvm -> common { kind=DEPENDS_ON } +js -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/topLevelFunWithKotlinTest/dependencies.txt b/idea/testData/multiModuleLineMarker/topLevelFunWithKotlinTest/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/topLevelFunWithKotlinTest/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/transitive/base_common/common.kt b/idea/testData/multiModuleLineMarker/transitive/base_common/common.kt index cc1c972043c..2c6611d4048 100644 --- a/idea/testData/multiModuleLineMarker/transitive/base_common/common.kt +++ b/idea/testData/multiModuleLineMarker/transitive/base_common/common.kt @@ -1 +1 @@ -expect fun foo(): Int \ No newline at end of file +expect fun foo(): Int \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/transitive/dependencies.txt b/idea/testData/multiModuleLineMarker/transitive/dependencies.txt new file mode 100644 index 00000000000..b2fde8faed7 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/transitive/dependencies.txt @@ -0,0 +1,6 @@ +MODULE base_common { platform=[JVM, JS, Native] } +MODULE base_jvm { platform=[JVM] } +MODULE user_jvm { platform=[JVM] } + +base_jvm -> base_common { kind=DEPENDS_ON } +user_jvm -> base_common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/transitive/user_jvm_dep(base-jvm)_dep(base-common)/user.kt b/idea/testData/multiModuleLineMarker/transitive/user_jvm/user.kt similarity index 100% rename from idea/testData/multiModuleLineMarker/transitive/user_jvm_dep(base-jvm)_dep(base-common)/user.kt rename to idea/testData/multiModuleLineMarker/transitive/user_jvm/user.kt diff --git a/idea/testData/multiModuleLineMarker/transitiveCommon/dependencies.txt b/idea/testData/multiModuleLineMarker/transitiveCommon/dependencies.txt new file mode 100644 index 00000000000..0249f83a26e --- /dev/null +++ b/idea/testData/multiModuleLineMarker/transitiveCommon/dependencies.txt @@ -0,0 +1,6 @@ +MODULE base_common { platform=[JVM, JS, Native] } +MODULE user_common { platform=[JVM, JS, Native] } +MODULE user_jvm { platform=[JVM] } + +user_common -> base_common { kind=DEPENDS_ON } +user_jvm -> user_common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/transitiveCommon/user_common_dep(base-common)/user.kt b/idea/testData/multiModuleLineMarker/transitiveCommon/user_common/user.kt similarity index 100% rename from idea/testData/multiModuleLineMarker/transitiveCommon/user_common_dep(base-common)/user.kt rename to idea/testData/multiModuleLineMarker/transitiveCommon/user_common/user.kt diff --git a/idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm/jvm.kt b/idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm/jvm.kt new file mode 100644 index 00000000000..07b1da0e710 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm/jvm.kt @@ -0,0 +1,3 @@ +actual class Expected { + actual val some = Some() +} \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm_dep(base-common)/jvm.kt b/idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm_dep(base-common)/jvm.kt deleted file mode 100644 index 68715f9470e..00000000000 --- a/idea/testData/multiModuleLineMarker/transitiveCommon/user_jvm_dep(base-common)/jvm.kt +++ /dev/null @@ -1,3 +0,0 @@ -actual class Expected { - actual val some = Some() -} \ No newline at end of file diff --git a/idea/testData/multiModuleLineMarker/withOverloads/common/common.kt b/idea/testData/multiModuleLineMarker/withOverloads/common/common.kt index a1965111cc2..ad60efb0710 100644 --- a/idea/testData/multiModuleLineMarker/withOverloads/common/common.kt +++ b/idea/testData/multiModuleLineMarker/withOverloads/common/common.kt @@ -1,3 +1,3 @@ -expect fun foo(): Int +expect fun foo(): Int -expect fun foo(arg: Int): Int +expect fun foo(arg: Int): Int diff --git a/idea/testData/multiModuleLineMarker/withOverloads/dependencies.txt b/idea/testData/multiModuleLineMarker/withOverloads/dependencies.txt new file mode 100644 index 00000000000..549b0097cf5 --- /dev/null +++ b/idea/testData/multiModuleLineMarker/withOverloads/dependencies.txt @@ -0,0 +1,4 @@ +MODULE common { platform=[JVM, JS, Native] } +MODULE jvm { platform=[JVM] } + +jvm -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleLineMarkerTest.kt b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleLineMarkerTest.kt index 3e104408702..6ed47dac6c9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleLineMarkerTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/AbstractMultiModuleLineMarkerTest.kt @@ -5,22 +5,10 @@ package org.jetbrains.kotlin.idea.caches.resolve -import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure +import org.jetbrains.kotlin.idea.codeMetaInfo.AbstractLineMarkerCodeMetaInfoTest import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import java.io.File -abstract class AbstractMultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() { +abstract class AbstractMultiModuleLineMarkerTest : AbstractLineMarkerCodeMetaInfoTest() { override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/multiModuleLineMarker/" - - override val shouldCheckLineMarkers = true - - override val shouldCheckResult = false - - override fun doTestLineMarkers() = true - - protected fun doTest(path: String) { - setupMppProjectFromDirStructure(File(path)) - checkLineMarkersInProject() - } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt index b82e39a2f52..b7f5bf28cd6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt @@ -29,7 +29,9 @@ import com.intellij.testFramework.runInEdtAndWait import com.intellij.util.io.exists import gnu.trove.TIntArrayList import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest +import org.jetbrains.kotlin.checkers.diagnostics.DebugInfoDiagnostic import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic +import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory0 import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil import org.jetbrains.kotlin.checkers.utils.DiagnosticsRenderingConfiguration import org.jetbrains.kotlin.daemon.common.OSKind @@ -49,9 +51,11 @@ import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.util.sourceRoots import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.KotlinTestUtils +import org.junit.Ignore import java.io.File import java.nio.file.Paths +@Ignore class CodeMetaInfoTestCase( val codeMetaInfoTypes: Collection, val checkNoDiagnosticError: Boolean = false @@ -158,12 +162,11 @@ class CodeMetaInfoTestCase( codeMetaInfo.platforms.add(OSKind.current.toString()) } } - if (parsedMetaInfo.isNotEmpty()) - parsedMetaInfo.forEach { - if (it.platforms.isNotEmpty() && OSKind.current.toString() !in it.platforms) codeMetaInfoForCheck.add( - it - ) - } + parsedMetaInfo.forEach { + if (it.platforms.isNotEmpty() && OSKind.current.toString() !in it.platforms) codeMetaInfoForCheck.add( + it + ) + } val textWithCodeMetaInfo = CodeMetaInfoRenderer.renderTagsToText(codeMetaInfoForCheck, myEditor.document.text) KotlinTestUtils.assertEqualsToFile( expectedFile, @@ -199,6 +202,11 @@ class CodeMetaInfoTestCase( val diagnostic: AbstractDiagnostic<*> = diagnosticCodeMetaInfo.diagnostic diagnostic.factory.toString() in (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description } + is DebugInfoDiagnostic -> { + val diagnostic: DebugInfoDiagnostic = diagnosticCodeMetaInfo.diagnostic + diagnostic.factory == DebugInfoDiagnosticFactory0.MISSING_UNRESOLVED && + "[DEBUG] Reference is not resolved to anything, but is not marked unresolved" in (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description + } else -> throw java.lang.IllegalArgumentException("Unknown diagnostic type: ${diagnosticCodeMetaInfo.diagnostic}") } }, diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt index efb82bb2380..2a27efcce1e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt @@ -17,14 +17,17 @@ import org.jetbrains.kotlin.idea.codeMetaInfo.models.LineMarkerCodeMetaInfo abstract class AbstractCodeMetaInfoRenderConfiguration(var renderParams: Boolean = true) { - + private val clickOrPressRegex = "Click or press (.*)to navigate".toRegex() //We have different hotkeys on different platforms open fun asString(codeMetaInfo: CodeMetaInfo) = codeMetaInfo.getTag() + getPlatformsString(codeMetaInfo) open fun getAdditionalParams(codeMetaInfo: CodeMetaInfo) = "" protected fun sanitizeLineMarkerTooltip(originalText: String?): String { if (originalText == null) return "null" - val noHtmlTags = StringUtil.removeHtmlTags(originalText).replace(" ", "") + val noHtmlTags = StringUtil.removeHtmlTags(originalText) + .replace(" ", "") + .replace(clickOrPressRegex, "") + .trim() return sanitizeLineBreaks(noHtmlTags) } @@ -79,15 +82,16 @@ open class DiagnosticCodeMetaInfoRenderConfiguration( } } -open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { +open class LineMarkerRenderConfiguration(var renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is LineMarkerCodeMetaInfo) return "" - return getTag() + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "" + return getTag() + getParamsString(codeMetaInfo) } fun getTag() = "LINE_MARKER" private fun getParamsString(lineMarkerCodeMetaInfo: LineMarkerCodeMetaInfo): String { + if (!renderParams) return "" val params = mutableListOf() if (renderDescription) @@ -95,7 +99,8 @@ open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) params.add(getAdditionalParams(lineMarkerCodeMetaInfo)) - return params.filter { it.isNotEmpty() }.joinToString("; ") + val paramsString = params.filter { it.isNotEmpty() }.joinToString("; ") + return if (paramsString.isEmpty()) "" else "(\"$paramsString\")" } } @@ -107,14 +112,15 @@ open class HighlightingRenderConfiguration( override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is HighlightingCodeMetaInfo) return "" - return getTag() + if (renderParams) "(${getParamsString(codeMetaInfo)})" else "" + return getTag() + getParamsString(codeMetaInfo) } fun getTag() = "HIGHLIGHTING" private fun getParamsString(highlightingCodeMetaInfo: HighlightingCodeMetaInfo): String { - val params = mutableListOf() + if (!renderParams) return "" + val params = mutableListOf() if (renderSeverity) params.add("severity='${highlightingCodeMetaInfo.highlightingInfo.severity}'") if (renderDescription) @@ -123,7 +129,8 @@ open class HighlightingRenderConfiguration( params.add("textAttributesKey='${highlightingCodeMetaInfo.highlightingInfo.forcedTextAttributesKey}'") params.add(getAdditionalParams(highlightingCodeMetaInfo)) + val paramsString = params.filter { it.isNotEmpty() }.joinToString("; ") - return params.filter { it.isNotEmpty() }.joinToString("; ") + return if (paramsString.isEmpty()) "" else "(\"$paramsString\")" } } \ No newline at end of file From bb2e9e2d5621b3397e06d4923c11908ef596b9cf Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 23 Oct 2020 12:06:47 +0300 Subject: [PATCH 013/554] Extract new method from the publicly used interface for compatibility Note that we can't just use ``@JvmDefault` annotation as the main change is in the `core` module which targets Java 6 #KT-42259 Fixed --- .../IncrementalPackageFragmentProvider.kt | 4 ++-- ...tionalAnnotationPackageFragmentProvider.kt | 2 +- .../analyzer/AbstractResolverForProject.kt | 8 +++---- .../kotlin/resolve/lazy/ResolveSession.java | 2 +- .../lazy/LazyJavaPackageFragmentProvider.kt | 4 ++-- .../descriptors/PackageFragmentProvider.kt | 24 ++++++++++++------- .../PackageFragmentProviderImpl.kt | 2 +- .../impl/CompositePackageFragmentProvider.kt | 8 ++++--- ...ractDeserializedPackageFragmentProvider.kt | 4 ++-- .../DeserializerForDecompilerBase.kt | 3 ++- .../CommonizedPackageFragmentProvider.kt | 3 ++- ...AndroidPackageFragmentProviderExtension.kt | 3 ++- 12 files changed, 39 insertions(+), 28 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt index 86a43e6f6aa..dbe5acafa61 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.load.kotlin.incremental import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder @@ -49,7 +49,7 @@ class IncrementalPackageFragmentProvider( val incrementalCache: IncrementalCache, val target: TargetId, private val kotlinClassFinder: KotlinClassFinder -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { private val fqNameToPackageFragment = PackagePartClassUtils.getFilesWithCallables(sourceFiles) .mapTo(hashSetOf()) { it.packageFqName } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt index 0c63bf74b17..b766d67aa14 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt @@ -33,7 +33,7 @@ class OptionalAnnotationPackageFragmentProvider( notFoundClasses: NotFoundClasses, languageVersionSettings: LanguageVersionSettings, packagePartProvider: PackagePartProvider, -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { val packages: Map by storageManager.createLazyValue p@{ // We call getAllOptionalAnnotationClasses under lazy value only because IncrementalPackagePartProvider requires // deserializationConfiguration to be injected. diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt index 89b626ffefa..864bbef9735 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt @@ -8,9 +8,7 @@ package org.jetbrains.kotlin.analyzer import com.intellij.openapi.util.ModificationTracker import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.context.ProjectContext -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -238,7 +236,7 @@ private class DelegatingPackageFragmentProvider( private val module: ModuleDescriptor, moduleContent: ModuleContent, private val packageOracle: PackageOracle -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { private val syntheticFilePackages = moduleContent.syntheticFiles.map { it.packageFqName }.toSet() override fun getPackageFragments(fqName: FqName): List { @@ -250,7 +248,7 @@ private class DelegatingPackageFragmentProvider( override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) { if (certainlyDoesNotExist(fqName)) return - resolverForProject.resolverForModuleDescriptor(module).packageFragmentProvider.collectPackageFragments(fqName, packageFragments) + resolverForProject.resolverForModuleDescriptor(module).packageFragmentProvider.collectPackageFragmentsOptimizedIfPossible(fqName, packageFragments) } override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java index 7f38d196fa5..a4ea5c5269f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java @@ -179,7 +179,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { this.declarationProviderFactory = declarationProviderFactory; - this.packageFragmentProvider = new PackageFragmentProvider() { + this.packageFragmentProvider = new PackageFragmentProviderOptimized() { @Override public void collectPackageFragments( @NotNull FqName fqName, @NotNull Collection packageFragments diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt index d33fa57941f..7abdd88f83c 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.load.java.lazy import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull class LazyJavaPackageFragmentProvider( components: JavaResolverComponents -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY, lazyOf(null)) diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProvider.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProvider.kt index 64a15597ec7..49312860164 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProvider.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProvider.kt @@ -20,27 +20,35 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name interface PackageFragmentProvider { - fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) { - // default implementation is provided only for BWC - packageFragments.addAll(getPackageFragments(fqName)) - } - @Deprecated("for usages use #packageFragments(FqName) at final point, for impl use #collectPackageFragments(FqName, MutableCollection)") fun getPackageFragments(fqName: FqName): List fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection object Empty : PackageFragmentProvider { - override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) {} - override fun getPackageFragments(fqName: FqName) = emptyList() override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean) = emptySet() } } +interface PackageFragmentProviderOptimized : PackageFragmentProvider { + fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) +} + fun PackageFragmentProvider.packageFragments(fqName: FqName): List { val packageFragments = mutableListOf() - collectPackageFragments(fqName, packageFragments) + collectPackageFragmentsOptimizedIfPossible(fqName, packageFragments) return packageFragments } + +fun PackageFragmentProvider.collectPackageFragmentsOptimizedIfPossible( + fqName: FqName, + packageFragments: MutableCollection +) { + when (this) { + is PackageFragmentProviderOptimized -> collectPackageFragments(fqName, packageFragments) + else -> packageFragments.addAll(getPackageFragments(fqName)) + } +} + diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProviderImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProviderImpl.kt index dc822c6b217..de18cfd7766 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProviderImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PackageFragmentProviderImpl.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.name.Name class PackageFragmentProviderImpl( private val packageFragments: Collection -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) { this.packageFragments.filterTo(packageFragments) { it.fqName == fqName } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/CompositePackageFragmentProvider.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/CompositePackageFragmentProvider.kt index b2cfc935b2d..3b2dab2ef0d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/CompositePackageFragmentProvider.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/CompositePackageFragmentProvider.kt @@ -18,13 +18,15 @@ package org.jetbrains.kotlin.descriptors.impl import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized +import org.jetbrains.kotlin.descriptors.collectPackageFragmentsOptimizedIfPossible import org.jetbrains.kotlin.name.FqName import java.util.* import org.jetbrains.kotlin.name.Name class CompositePackageFragmentProvider(// can be modified from outside private val providers: List -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { init { assert(providers.size == providers.toSet().size) { @@ -35,14 +37,14 @@ class CompositePackageFragmentProvider(// can be modified from outside override fun getPackageFragments(fqName: FqName): List { val result = ArrayList() for (provider in providers) { - provider.collectPackageFragments(fqName, result) + provider.collectPackageFragmentsOptimizedIfPossible(fqName, result) } return result.toList() } override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) { for (provider in providers) { - provider.collectPackageFragments(fqName, packageFragments) + provider.collectPackageFragmentsOptimizedIfPossible(fqName, packageFragments) } } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractDeserializedPackageFragmentProvider.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractDeserializedPackageFragmentProvider.kt index 7780b4a1cce..48f3b14e273 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractDeserializedPackageFragmentProvider.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AbstractDeserializedPackageFragmentProvider.kt @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.serialization.deserialization import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.storage.StorageManager @@ -28,7 +28,7 @@ abstract class AbstractDeserializedPackageFragmentProvider( protected val storageManager: StorageManager, protected val finder: KotlinMetadataFinder, protected val moduleDescriptor: ModuleDescriptor -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { protected lateinit var components: DeserializationComponents private val fragments = storageManager.createMemoizedFunctionWithNullableValues { fqName -> diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompilerBase.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompilerBase.kt index f6e38226811..9a3b3d551c9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompilerBase.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompilerBase.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.decompiler.textBuilder import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor import org.jetbrains.kotlin.name.ClassId @@ -28,7 +29,7 @@ abstract class DeserializerForDecompilerBase(val directoryPackageFqName: FqName) protected val moduleDescriptor: ModuleDescriptorImpl = createDummyModule("module for building decompiled sources") - protected val packageFragmentProvider: PackageFragmentProvider = object : PackageFragmentProvider { + protected val packageFragmentProvider: PackageFragmentProvider = object : PackageFragmentProviderOptimized { override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) { packageFragments.add(createDummyPackageFragment(fqName)) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedPackageFragmentProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedPackageFragmentProvider.kt index c6be0379a67..1da0bb061d4 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedPackageFragmentProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedPackageFragmentProvider.kt @@ -7,10 +7,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -internal class CommonizedPackageFragmentProvider : PackageFragmentProvider { +internal class CommonizedPackageFragmentProvider : PackageFragmentProviderOptimized { private val packageFragments = ArrayList() operator fun plusAssign(packageFragment: PackageFragmentDescriptor) { diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/res/AndroidPackageFragmentProviderExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/res/AndroidPackageFragmentProviderExtension.kt index 0be3714c4b3..13eef39532d 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/res/AndroidPackageFragmentProviderExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/res/AndroidPackageFragmentProviderExtension.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.android.synthetic.forEachUntilLast import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.PackageFragmentProviderOptimized import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -132,7 +133,7 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider class AndroidSyntheticPackageFragmentProvider( val packages: Map PackageFragmentDescriptor> -) : PackageFragmentProvider { +) : PackageFragmentProviderOptimized { override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection) = packageFragments.addIfNotNull(packages[fqName]?.invoke()) From e6edb62911930201ac0d40d9959c0986c51363f3 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 27 Oct 2020 12:10:49 +0300 Subject: [PATCH 014/554] [Gradle, JS] Fix for IDEA import with dukat binaries ^KT-42954 fixed --- .../targets/js/dukat/DukatCompilationResolverPlugin.kt | 6 ++++-- .../kotlin/gradle/targets/js/dukat/DukatExecutor.kt | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt index c4fc3f51bc5..00c8e6f723f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt @@ -89,7 +89,9 @@ internal class DukatCompilationResolverPlugin( val target = compilation.target val externalsOutputFormat = compilation.externalsOutputFormat - if (target is KotlinJsTarget && externalsOutputFormat == ExternalsOutputFormat.SOURCE) { + val legacyTargetReuseIrTask = + target is KotlinJsTarget && (target.irTarget != null && externalsOutputFormat == ExternalsOutputFormat.SOURCE) + if (legacyTargetReuseIrTask) { return } @@ -105,7 +107,7 @@ internal class DukatCompilationResolverPlugin( } companion object { - const val VERSION = "2" + const val VERSION = "3" } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt index 32ac555e611..0984b51efd4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt @@ -40,7 +40,7 @@ class DukatExecutor( versionFile.delete() npmProject.externalsDirRoot.mkdirs() - val inputs = typeDefinitions.joinToString("\n") { it.inputKey } + val inputs = "$externalsOutputFormat: " + typeDefinitions.joinToString("\n") { it.inputKey } if (!compareInputs || !inputsFile.isFile || inputsFile.readText() != inputs) { // delete file to run visit on error even without package.json updates From a72cdeabb4f7a8d3beb5097c1480d0dd3b977afd Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Tue, 27 Oct 2020 18:56:35 +0700 Subject: [PATCH 015/554] fix testData ^KT-40861 --- .../addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt index bf56f1bf186..c14b4754ce8 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaUpperBound.before.Main.kt @@ -1,4 +1,5 @@ // "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" +// ACTION: Convert to secondary constructor // ACTION: Create test // ACTION: Enable a trailing comma by default in the formatter // ACTION: Inline type parameter From 21521aa397e9419272ed98bebae2e67ad30d994b Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 27 Oct 2020 09:55:32 +0100 Subject: [PATCH 016/554] Deprecate protected constructors call from public inline function #KT-21177 --- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++++ .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../resolve/calls/checkers/InlineChecker.kt | 17 +++++++++---- .../diagnostics/tests/inline/kt15410.kt | 2 +- .../diagnostics/tests/inline/kt21177.fir.kt | 18 +++++++++++++ .../diagnostics/tests/inline/kt21177.kt | 18 +++++++++++++ .../diagnostics/tests/inline/kt21177.txt | 25 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 ++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++++ 10 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inline/kt21177.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inline/kt21177.kt create mode 100644 compiler/testData/diagnostics/tests/inline/kt21177.txt 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 7cad9d0b1ba..f25811e0fa1 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 @@ -12386,6 +12386,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inline/kt19679.kt"); } + @TestMetadata("kt21177.kt") + public void testKt21177() throws Exception { + runTest("compiler/testData/diagnostics/tests/inline/kt21177.kt"); + } + @TestMetadata("kt4869.kt") public void testKt4869() throws Exception { runTest("compiler/testData/diagnostics/tests/inline/kt4869.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index d8f128127ca..4ab63010616 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -1130,6 +1130,7 @@ public interface Errors { DiagnosticFactory0 INLINE_PROPERTY_WITH_BACKING_FIELD = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 NON_INTERNAL_PUBLISHED_API = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 PROTECTED_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory1.create(WARNING); + DiagnosticFactory1 PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory1.create(WARNING); DiagnosticFactory1 PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR = DiagnosticFactory1.create(ERROR); DiagnosticFactory2 INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE = DiagnosticFactory2.create(ERROR); DiagnosticFactory2 NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE = DiagnosticFactory2.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index fb09ce2e121..93ac7c86915 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -1018,6 +1018,7 @@ public class DefaultErrorMessages { MAP.put(INLINE_PROPERTY_WITH_BACKING_FIELD, "Inline property cannot have backing field"); MAP.put(NON_INTERNAL_PUBLISHED_API, "@PublishedApi annotation is only applicable for internal declaration"); MAP.put(PROTECTED_CALL_FROM_PUBLIC_INLINE, "Protected function call from public-API inline function is deprecated", NAME); + MAP.put(PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE, "Protected constructor call from public-API inline function is deprecated", NAME); MAP.put(PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR, "Protected function call from public-API inline function is prohibited", NAME); MAP.put(INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, "Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES); MAP.put(NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE, "Usage of inline parameter ''{0}'' in default value for another inline parameter is not supported", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.kt index 3d7d92f250a..37bb400e12e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.kt @@ -265,14 +265,21 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC checkPrivateClassMemberAccess(calledDescriptor, expression, context) } - if (calledDescriptor !is ConstructorDescriptor && + val isConstructorCall = calledDescriptor is ConstructorDescriptor + if ((!isConstructorCall || expression !is KtConstructorCalleeExpression) && isInlineFunPublicOrPublishedApi && inlineFunEffectiveVisibility.toVisibility() !== Visibilities.Protected && calledFunEffectiveVisibility.toVisibility() === Visibilities.Protected) { - if (prohibitProtectedCallFromInline) { - context.trace.report(PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR.on(expression, calledDescriptor)) - } else { - context.trace.report(PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor)) + when { + isConstructorCall -> { + context.trace.report(PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor)) + } + prohibitProtectedCallFromInline -> { + context.trace.report(PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR.on(expression, calledDescriptor)) + } + else -> { + context.trace.report(PROTECTED_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor)) + } } } } diff --git a/compiler/testData/diagnostics/tests/inline/kt15410.kt b/compiler/testData/diagnostics/tests/inline/kt15410.kt index 1bfe158cd71..f2421a1319f 100644 --- a/compiler/testData/diagnostics/tests/inline/kt15410.kt +++ b/compiler/testData/diagnostics/tests/inline/kt15410.kt @@ -6,5 +6,5 @@ open class Foo protected constructor() inline fun foo(f: () -> Unit) = object: Foo() {} class A : Foo() { - inline fun foo(f: () -> Unit) = Foo() + inline fun foo(f: () -> Unit) = Foo() } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/kt21177.fir.kt b/compiler/testData/diagnostics/tests/inline/kt21177.fir.kt new file mode 100644 index 00000000000..45412c060c0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/kt21177.fir.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class SomeContainer { + protected class Limit + + protected fun makeLimit(): Limit = TODO() + + public inline fun foo(f: () -> Unit) { + Limit() + makeLimit() + } +} + +open class A protected constructor() { + inline fun foo(f: () -> Unit) { + A() + } +} diff --git a/compiler/testData/diagnostics/tests/inline/kt21177.kt b/compiler/testData/diagnostics/tests/inline/kt21177.kt new file mode 100644 index 00000000000..9d8dcdd28a1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/kt21177.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class SomeContainer { + protected class Limit + + protected fun makeLimit(): Limit = TODO() + + public inline fun foo(f: () -> Unit) { + Limit() + makeLimit() + } +} + +open class A protected constructor() { + inline fun foo(f: () -> Unit) { + A() + } +} diff --git a/compiler/testData/diagnostics/tests/inline/kt21177.txt b/compiler/testData/diagnostics/tests/inline/kt21177.txt new file mode 100644 index 00000000000..dfe110aad4e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/kt21177.txt @@ -0,0 +1,25 @@ +package + +public open class A { + protected constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final inline fun foo(/*0*/ f: () -> kotlin.Unit): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class SomeContainer { + public constructor SomeContainer() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final inline fun foo(/*0*/ f: () -> kotlin.Unit): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + protected final fun makeLimit(): SomeContainer.Limit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + protected final class Limit { + public constructor Limit() + 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/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 6ff186956b4..290b35dd7da 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12393,6 +12393,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inline/kt19679.kt"); } + @TestMetadata("kt21177.kt") + public void testKt21177() throws Exception { + runTest("compiler/testData/diagnostics/tests/inline/kt21177.kt"); + } + @TestMetadata("kt4869.kt") public void testKt4869() throws Exception { runTest("compiler/testData/diagnostics/tests/inline/kt4869.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 0c013339bac..573adcf8980 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -12388,6 +12388,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inline/kt19679.kt"); } + @TestMetadata("kt21177.kt") + public void testKt21177() throws Exception { + runTest("compiler/testData/diagnostics/tests/inline/kt21177.kt"); + } + @TestMetadata("kt4869.kt") public void testKt4869() throws Exception { runTest("compiler/testData/diagnostics/tests/inline/kt4869.kt"); From 3386b930093101f492e8bef297b6bee02adcc0ac Mon Sep 17 00:00:00 2001 From: Yaroslav Chernyshev Date: Tue, 27 Oct 2020 16:21:48 +0300 Subject: [PATCH 017/554] [Gradle, Cocoapods] Added `useLibraries()` to allow static library pods #KT-42531 fixed --- .../org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt | 10 ++++++++++ .../targets/native/cocoapods/CocoapodsExtension.kt | 10 ++++++++++ .../targets/native/cocoapods/KotlinCocoapodsPlugin.kt | 1 + .../targets/native/tasks/AdvancedCocoapodsTasks.kt | 4 ++++ 4 files changed, 25 insertions(+) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt index 9c8f6120eed..3682b4629fc 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/CocoaPodsIT.kt @@ -64,6 +64,7 @@ class CocoaPodsIT : BaseGradleIT() { private val defaultPodRepo = "https://github.com/AFNetworking/AFNetworking" private val defaultPodName = "AFNetworking" + private val defaultLibraryPodName = "YandexMapKit" private val downloadUrlPodName = "podspecWithFilesExample" private val downloadUrlRepoName = "https://github.com/alozhkin/podspecWithFilesExample/raw/master" private val defaultTarget = "IOS" @@ -729,6 +730,15 @@ class CocoaPodsIT : BaseGradleIT() { } } + @Test + fun testUseLibrariesMode() { + with(project) { + gradleBuildScript().appendToCocoapodsBlock("useLibraries()") + gradleBuildScript().addPod(defaultLibraryPodName) + testImport() + } + } + // paths private fun CompiledProject.url() = externalSources().resolve("url") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt index 26cc026f4d7..00639d9740d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/CocoapodsExtension.kt @@ -45,6 +45,16 @@ open class CocoapodsExtension(private val project: Project) { needPodspec = false } + /** + * Setup cocoapods-generate to produce xcodeproj compatible with static libraries + */ + fun useLibraries() { + useLibraries = true + } + + @get:Input + internal var useLibraries: Boolean = false + /** * Configure license of the pod built from this project. */ diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt index 5f16b71783b..4cfe5839173 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt @@ -407,6 +407,7 @@ open class KotlinCocoapodsPlugin : Plugin { project.tasks.register(family.toPodGenTaskName, PodGenTask::class.java) { it.description = "Сreates a synthetic Xcode project to retrieve CocoaPods dependencies" it.podspec = podspecTaskProvider.map { task -> task.outputFileProvider.get() } + it.useLibraries = project.provider { cocoapodsExtension.useLibraries } it.specRepos = project.provider { cocoapodsExtension.specRepos } it.family = family it.pods.set(cocoapodsExtension.pods) 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 5f9c75392de..b86fcd5385f 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 @@ -352,6 +352,9 @@ open class PodGenTask : DefaultTask() { @get:InputFile internal lateinit var podspec: Provider + @get:Input + internal lateinit var useLibraries: Provider + @get:Internal lateinit var family: Family @@ -379,6 +382,7 @@ open class PodGenTask : DefaultTask() { val podGenProcessArgs = listOfNotNull( "pod", "gen", + "--use-libraries".takeIf { useLibraries.get() }, "--platforms=${family.platformLiteral}", "--gen-directory=${syntheticDir.absolutePath}", localPodspecPaths.takeIf { it.isNotEmpty() }?.joinToString(separator = ",")?.let { "--local-sources=$it" }, From 9faf91f55d887f97066562e3a07b42d4e30ff58e Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 27 Oct 2020 17:49:02 +0900 Subject: [PATCH 018/554] Fix Parcelize settings serialization (KT-42958) --- idea/resources/META-INF/parcelize.xml | 4 +++ .../parcelize/parcelize-ide/build.gradle.kts | 1 + .../parcelize/ide/ParcelizeAvailability.kt | 2 +- .../ide/ParcelizeProjectResolverExtension.kt | 25 ++++++++++++++----- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/idea/resources/META-INF/parcelize.xml b/idea/resources/META-INF/parcelize.xml index 9e47ccce9c9..17927db032c 100644 --- a/idea/resources/META-INF/parcelize.xml +++ b/idea/resources/META-INF/parcelize.xml @@ -10,6 +10,10 @@ + + + + diff --git a/plugins/parcelize/parcelize-ide/build.gradle.kts b/plugins/parcelize/parcelize-ide/build.gradle.kts index eab842eaefe..7db699163ff 100644 --- a/plugins/parcelize/parcelize-ide/build.gradle.kts +++ b/plugins/parcelize/parcelize-ide/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { compile(project(":compiler:frontend.java")) compile(project(":compiler:light-classes")) compile(project(":idea")) + compile(project(":idea:idea-gradle")) compile(project(":plugins:parcelize:parcelize-compiler")) compile(project(":plugins:parcelize:parcelize-runtime")) diff --git a/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeAvailability.kt b/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeAvailability.kt index aeada03a410..6cba9bbdd1e 100644 --- a/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeAvailability.kt +++ b/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeAvailability.kt @@ -32,6 +32,6 @@ object ParcelizeAvailability { val path = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return false val externalProjectInfo = ExternalSystemUtil.getExternalProjectInfo(module.project, GradleConstants.SYSTEM_ID, path) ?: return false val moduleData = GradleProjectResolverUtil.findModule(externalProjectInfo.externalProjectStructure, path) ?: return false - return moduleData.getCopyableUserData(ParcelizeProjectResolverExtension.KEY)?.isEnabled ?: false + return ExternalSystemApiUtil.find(moduleData, ParcelizeIdeModel.KEY)?.data?.isEnabled ?: false } } \ No newline at end of file diff --git a/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeProjectResolverExtension.kt b/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeProjectResolverExtension.kt index 9a7f0aaa272..fe2ce61898e 100644 --- a/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeProjectResolverExtension.kt +++ b/plugins/parcelize/parcelize-ide/src/org/jetbrains/kotlin/parcelize/ide/ParcelizeProjectResolverExtension.kt @@ -6,17 +6,30 @@ package org.jetbrains.kotlin.parcelize.ide import com.intellij.openapi.externalSystem.model.DataNode +import com.intellij.openapi.externalSystem.model.Key +import com.intellij.openapi.externalSystem.model.ProjectKeys +import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData import com.intellij.openapi.externalSystem.model.project.ModuleData -import com.intellij.openapi.util.Key +import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService +import com.intellij.serialization.PropertyMapping import org.gradle.tooling.model.idea.IdeaModule import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension +import org.jetbrains.plugins.gradle.util.GradleConstants + +class ParcelizeIdeModel @PropertyMapping("isEnabled") constructor( + val isEnabled: Boolean +) : AbstractExternalEntityData(GradleConstants.SYSTEM_ID) { + companion object { + val KEY = Key.create(ParcelizeIdeModel::class.java, ProjectKeys.CONTENT_ROOT.processingWeight + 1) + } +} + +class ParcelizeIdeModelDataService : AbstractProjectDataService() { + override fun getTargetDataKey() = ParcelizeIdeModel.KEY +} @Suppress("unused") class ParcelizeProjectResolverExtension : AbstractProjectResolverExtension() { - companion object { - val KEY = Key("ParcelizeModel") - } - override fun getExtraProjectModelClasses() = setOf(ParcelizeGradleModel::class.java) override fun getToolingExtensionsClasses() = setOf(ParcelizeModelBuilderService::class.java, Unit::class.java) @@ -24,7 +37,7 @@ class ParcelizeProjectResolverExtension : AbstractProjectResolverExtension() { val parcelizeModel = resolverCtx.getExtraProject(gradleModule, ParcelizeGradleModel::class.java) if (parcelizeModel != null && parcelizeModel.isEnabled) { - ideModule.putCopyableUserData(KEY, ParcelizeGradleModelImpl(isEnabled = parcelizeModel.isEnabled)) + ideModule.createChild(ParcelizeIdeModel.KEY, ParcelizeIdeModel(isEnabled = parcelizeModel.isEnabled)) } super.populateModuleExtraModels(gradleModule, ideModule) From 008da87160c3704846dab2b18c0c9055dbab95cc Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Wed, 28 Oct 2020 00:42:16 +0900 Subject: [PATCH 019/554] Minor: Update Android Extensions deprecation message in relevant test --- .../jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt index 3566ad7ba73..afd41ffa90c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt @@ -681,7 +681,7 @@ fun getSomething() = 10 project.build("assembleDebug", options = options) { assertSuccessful() - assertContains("'kotlin-android-extensions' plugin is deprecated") + assertContains("The 'kotlin-android-extensions' Gradle plugin is deprecated") } } From 03cc0bf6aa99033249e85b58040d33f3247cf76c Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 17 Apr 2020 09:56:52 -0700 Subject: [PATCH 020/554] Add java.nio.Path extensions to stdlib-jdk7 This PR adds most extensions on `java.io.File` in `kotlin.io` to `java.nio.Path`. This includes extensions from `FileReadWrite.kt`, `Utils.kt`, and `FileTreeWalk.kt`. I attempted to keep the implementations, documentation, and tests as similar as possible to the existing implementations. I am happy to add, remove, or move to separate PRs any of the functions of this PR. ### `File` extensions that were not added to `Path` ##### `createTempDir`, `createTempFile` These functions have no `File` parameters, so can't be overloaded. Equivalents exist as `Files.createTempFile()` and `Files.createTempDirectory()`. ##### `startsWith`, `endsWith`, `normalize`, `resolve`, `resolveSibling` These exist as member functions on `Path` ##### `relativeTo`, `relativeToOrNull`, `relativeToOrSelf`, `toRelativeString`, `toRelativeStringOrNull` This functionality exists as the `Path.relativize` member function, which is equivalent to `relativeTo`, but with the receiver and parameter flipped. `foo.relativeTo(bar)` is equivalent to `bar.relativize(foo)`. We could potentially add a `relativizeOrNull` extension to make that pattern simpler. ##### `isRooted` `Path` has a `root` method, so `isRooted` is equivalent to `root != null` ### New extensions All of the simple boolean attribute checks from `java.nio.Files` were added as extensions on `Path`. These extensions are used commonly enough that it seems worth supporting them. This functionality for `File` is implemented as member methods. The following `Path` extensions were added: - `exists` - `isDirectory` - `isExecutable` - `isFile` - `isHidden` - `isReadable` - `isSameFile` - `isSymbolicLink` - `isWritable` Some of these extensions take options that are forwarded to their `Files` method, so all of the extensions were implemented as functions rather than properties for consistency. Additionally, `Path.listFiles` was added to match the `File.listFiles` method. One motivation for its addition was that it's used several times in the implementation of other file extensions. The way to list directory contents with `java.nio` is via `Files.newDirectoryStream()`, which returns an iterable object that must be closed to avoid leaking resources. It's difficult to use correctly with functions like `map` and `filter`, so this extension was added as a simpler, less error-prone alternative. ### Other changes I added overloads of several of the read-write that take `OpenOptions` to expose the greater control that `java.nio` introduces. For example, you can use `printWriter(APPEND)` to create a `PrintWriter` that doesn't delete the contents of an existing file. All the new extensions throw exceptions (such as `NoSuchFileException`) from `java.nio` rather than the copies from `kotlin.io`. The `kotlin.io` copies take `File` objects as parameters, and so aren't compatible with `Path`s. ### Address review comments - Move varargs parameters to the last position - Remove PathTreeWalk #KT-19192 --- libraries/stdlib/jdk7/java9/module-info.java | 1 + .../jdk7/src/kotlin/io/PathReadWrite.kt | 487 ++++++++++++++++++ .../stdlib/jdk7/src/kotlin/io/PathUtils.kt | 220 ++++++++ .../stdlib/jdk7/test/PathExtensionsTest.kt | 215 ++++++++ .../stdlib/jdk7/test/PathReadWriteTest.kt | 80 +++ 5 files changed, 1003 insertions(+) create mode 100644 libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt create mode 100644 libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt create mode 100644 libraries/stdlib/jdk7/test/PathExtensionsTest.kt create mode 100644 libraries/stdlib/jdk7/test/PathReadWriteTest.kt diff --git a/libraries/stdlib/jdk7/java9/module-info.java b/libraries/stdlib/jdk7/java9/module-info.java index b786aa09f83..103cb93e9d9 100644 --- a/libraries/stdlib/jdk7/java9/module-info.java +++ b/libraries/stdlib/jdk7/java9/module-info.java @@ -3,6 +3,7 @@ module kotlin.stdlib.jdk7 { requires transitive kotlin.stdlib; exports kotlin.jdk7; + exports kotlin.io.jdk7; exports kotlin.internal.jdk7 to kotlin.stdlib.jdk8; opens kotlin.internal.jdk7 to kotlin.stdlib; diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt new file mode 100644 index 00000000000..7fa4044910c --- /dev/null +++ b/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt @@ -0,0 +1,487 @@ +/* + * 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:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "RedundantVisibilityModifier", "RedundantUnitReturnType", "SameParameterValue") +@file:JvmMultifileClass +@file:JvmName("PathsKt") +@file:kotlin.jvm.JvmPackageName("kotlin.io.jdk7") + +package kotlin.io + +import java.io.* +import java.nio.charset.Charset +import java.nio.file.Files +import java.nio.file.OpenOption +import java.nio.file.Path +import java.nio.file.StandardOpenOption + +/** + * The default block size for forEachBlock(). + */ +private const val DEFAULT_BLOCK_SIZE: Int = 4096 + +/** + * The minimum block size for forEachBlock(). + */ +private const val MINIMUM_BLOCK_SIZE: Int = 512 + +/** + * Returns a new [InputStreamReader] for reading the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.reader(charset: Charset = Charsets.UTF_8): InputStreamReader { + return inputStream().reader(charset) +} + +/** + * Returns a new [InputStreamReader] for reading the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.reader(vararg options: OpenOption): InputStreamReader { + return inputStream(*options).reader() +} + +/** + * Returns a new [InputStreamReader] for reading the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.reader(charset: Charset, vararg options: OpenOption): InputStreamReader { + return inputStream(*options).reader(charset) +} + +/** + * Returns a new [BufferedReader] for reading the content of this file. + * + * @param charset character set to use. + * @param bufferSize necessary size of the buffer. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedReader(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedReader { + return reader(charset).buffered(bufferSize) +} + +/** + * Returns a new [BufferedReader] for reading the content of this file. + * + * @param options options to determine how the file is opened + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedReader(vararg options: OpenOption): BufferedReader { + return reader(*options).buffered() +} + +/** + * Returns a new [BufferedReader] for reading the content of this file. + * + * @param bufferSize necessary size of the buffer. + * @param options options to determine how the file is opened + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedReader(bufferSize: Int, vararg options: OpenOption): BufferedReader { + return reader(*options).buffered(bufferSize) +} + +/** + * Returns a new [BufferedReader] for reading the content of this file. + * + * @param charset character set to use. + * @param options options to determine how the file is opened + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedReader(charset: Charset, vararg options: OpenOption): BufferedReader { + return reader(charset, *options).buffered() +} + +/** + * Returns a new [BufferedReader] for reading the content of this file. + * + * @param charset character set to use. + * @param bufferSize necessary size of the buffer. + * @param options options to determine how the file is opened + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedReader(charset: Charset, bufferSize: Int, vararg options: OpenOption): BufferedReader { + return reader(charset, *options).buffered(bufferSize) +} + +/** + * Returns a new [OutputStreamWriter] for writing the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.writer(charset: Charset = Charsets.UTF_8): OutputStreamWriter { + return outputStream().writer(charset) +} + +/** + * Returns a new [OutputStreamWriter] for writing the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.writer(vararg options: OpenOption): OutputStreamWriter { + return outputStream(*options).writer() +} + +/** + * Returns a new [OutputStreamWriter] for writing the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.writer(charset: Charset, vararg options: OpenOption): OutputStreamWriter { + return outputStream(*options).writer(charset) +} + +/** + * Returns a new [BufferedWriter] for writing the content of this file. + * + * @param charset character set to use. + * @param bufferSize necessary size of the buffer. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedWriter(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedWriter { + return writer(charset).buffered(bufferSize) +} + +/** + * Returns a new [BufferedWriter] for writing the content of this file. + * + * @param options options to determine how the file is opened. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedWriter(vararg options: OpenOption): BufferedWriter { + return writer(*options).buffered() +} + +/** + * Returns a new [BufferedWriter] for writing the content of this file. + * + * @param charset character set to use. + * @param options options to determine how the file is opened. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedWriter(charset: Charset, vararg options: OpenOption): BufferedWriter { + return writer(charset, *options).buffered() +} + +/** + * Returns a new [BufferedWriter] for writing the content of this file. + * + * @param bufferSize necessary size of the buffer. + * @param options options to determine how the file is opened. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedWriter(bufferSize: Int, vararg options: OpenOption): BufferedWriter { + return writer(*options).buffered(bufferSize) +} + +/** + * Returns a new [BufferedWriter] for writing the content of this file. + * + * @param charset character set to use. + * @param bufferSize necessary size of the buffer. + * @param options options to determine how the file is opened. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.bufferedWriter(charset: Charset, bufferSize: Int, vararg options: OpenOption): BufferedWriter { + return writer(charset, *options).buffered(bufferSize) +} + +/** + * Returns a new [PrintWriter] for writing the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.printWriter(charset: Charset = Charsets.UTF_8): PrintWriter { + return PrintWriter(bufferedWriter(charset)) +} + +/** + * Returns a new [PrintWriter] for writing the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.printWriter(vararg options: OpenOption): PrintWriter { + return PrintWriter(bufferedWriter(*options)) +} + +/** + * Returns a new [PrintWriter] for writing the content of this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.printWriter(charset: Charset, vararg options: OpenOption): PrintWriter { + return PrintWriter(bufferedWriter(charset, *options)) +} + +/** + * Gets the entire content of this file as a byte array. + * + * This method is not recommended on huge files. It has an internal limitation of 2 GB byte array size. + * + * @return the entire content of this file as a byte array. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.readBytes(): ByteArray { + return Files.readAllBytes(this) +} + +/** + * Write an [array] of bytes to this file. + * + * By default, the file will be overwritten if it already exists, but you can control this behavior + * with [options]. + * + * @param array byte array to write into this file. + * @param options options to determine how the file is opened. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.writeBytes(array: ByteArray, vararg options: OpenOption): Unit { + Files.write(this, array, *options) +} + +/** + * Appends an [array] of bytes to the content of this file. + * + * @param array byte array to append to this file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.appendBytes(array: ByteArray): Unit { + writeBytes(array, StandardOpenOption.APPEND) +} + +/** + * Gets the entire content of this file as a String using UTF-8 or specified [charset]. + * + * This method is not recommended on huge files. It has an internal limitation of 2 GB file size. + * + * @param charset character set to use. + * @return the entire content of this file as a String. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset) + +/** + * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. + * + * By default, the file will be overwritten if it already exists, but you can control this behavior + * with [options]. + * + * @param text text to write into file. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.writeText(text: String, vararg options: OpenOption): Unit { + writeBytes(text.toByteArray(), *options) +} + +/** + * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. + * + * By default, the file will be overwritten if it already exists, but you can control this behavior + * with [options]. + * + * @param text text to write into file. + * @param charset character set to use. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.writeText(text: String, charset: Charset, vararg options: OpenOption): Unit { + writeBytes(text.toByteArray(charset), *options) +} + + +/** + * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. + * If this file exists, it becomes overwritten. + * + * @param text text to write into file. + * @param charset character set to use. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8): Unit { + writeBytes(text.toByteArray(charset)) +} + + +/** + * Appends [text] to the content of this file using UTF-8 or the specified [charset]. + * + * @param text text to append to file. + * @param charset character set to use. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit { + writeText(text, charset, StandardOpenOption.APPEND) +} + +/** + * Reads file by byte blocks and calls [action] for each block read. + * Block has default size which is implementation-dependent. + * This function passes the byte array and amount of bytes in the array to the [action] function. + * + * You can use this function for huge files. + * + * @param action function to process file blocks. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.forEachBlock(action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit = forEachBlock(DEFAULT_BLOCK_SIZE, action) + +/** + * Reads file by byte blocks and calls [action] for each block read. + * This functions passes the byte array and amount of bytes in the array to the [action] function. + * + * You can use this function for huge files. + * + * @param action function to process file blocks. + * @param blockSize size of a block, replaced by 512 if it's less, 4096 by default. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.forEachBlock(blockSize: Int, action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit { + val arr = ByteArray(blockSize.coerceAtLeast(MINIMUM_BLOCK_SIZE)) + + inputStream().use { input -> + do { + val size = input.read(arr) + if (size <= 0) { + break + } else { + action(arr, size) + } + } while (true) + } +} + +/** + * Reads this file line by line using the specified [charset] and calls [action] for each line. + * Default charset is UTF-8. + * + * You may use this function on huge files. + * + * @param options options to determine how the file is opened. + * @param charset character set to use. + * @param action function to process file lines. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.forEachLine(vararg options: OpenOption, charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit { + // Note: close is called at forEachLine + bufferedReader(charset, *options).forEachLine(action) +} + +/** + * Reads this file line by line using the specified [charset] and calls [action] for each line. + * Default charset is UTF-8. + * + * You may use this function on huge files. + * + * @param charset character set to use. + * @param action function to process file lines. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit { + // Note: close is called at forEachLine + bufferedReader(charset = charset).forEachLine(action) +} + +/** + * Constructs a new InputStream of this path and returns it as a result. + * + * The [options] parameter determines how the file is opened. If no options are present then it is + * equivalent to opening the file with the [READ][StandardOpenOption.READ] option. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.inputStream(vararg options: OpenOption): InputStream { + return Files.newInputStream(this, *options) +} + +/** + * Constructs a new OutputStream of this file and returns it as a result. + * + * The [options] parameter determines how the file is opened. If no options are present then it is + * equivalent to opening the file with the [CREATE][StandardOpenOption.CREATE], + * [TRUNCATE_EXISTING][StandardOpenOption.TRUNCATE_EXISTING], and [WRITE][StandardOpenOption.WRITE] + * option. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.outputStream(vararg options: OpenOption): OutputStream { + return Files.newOutputStream(this, *options) +} + +/** + * Reads the file content as a list of lines. + * + * Do not use this function for huge files. + * + * @param charset character set to use. By default uses UTF-8 charset. + * @return list of file lines. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List { + return Files.readAllLines(this, charset) +} + +/** + * Calls the [block] callback giving it a sequence of all the lines in this file and closes the reader once + * the processing is complete. + + * @param charset character set to use. By default uses UTF-8 charset. + * @return the value returned by [block]. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence) -> T): T { + return bufferedReader(charset).use { block(it.lineSequence()) } +} diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt new file mode 100644 index 00000000000..e427bab2a2d --- /dev/null +++ b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt @@ -0,0 +1,220 @@ +/* + * 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:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "RedundantVisibilityModifier") +@file:JvmMultifileClass +@file:JvmName("PathsKt") +@file:kotlin.jvm.JvmPackageName("kotlin.io.jdk7") + +package kotlin.io + +import java.io.File +import java.io.IOException +import java.nio.channels.FileChannel +import java.nio.file.* +import java.nio.file.FileAlreadyExistsException +import java.nio.file.NoSuchFileException + +/** + * Returns the extension of this file (not including the dot), or an empty string if it doesn't have one. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public val Path.extension: String + get() = fileName.toString().substringAfterLast('.', "") + +/** + * Returns [path][File.path] of this File using the invariant separator '/' to + * separate the names in the name sequence. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public val Path.invariantSeparatorsPath: String + get() { + val separator = fileSystem.separator + return if (separator != "/") toString().replace(separator, "/") else toString() + } + +/** + * Returns file's name without an extension. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public val Path.nameWithoutExtension: String + get() = fileName.toString().substringBeforeLast(".") + + +/** + * Copies this path to the given [target] path. + * + * If some directories on a way to the [target] are missing, then they will be created. + * If the [target] path already exists, this function will fail unless [overwrite] argument is set to `true`. + * + * When [overwrite] is `true` and [target] is a directory, it is replaced only if it is empty. + * + * If this file is a directory, it is copied without its content, i.e. an empty [target] directory is created. + * If you want to copy directory including its contents, use [copyRecursively]. + * + * The operation doesn't preserve copied file attributes such as creation/modification date, permissions, etc. + * + * @param overwrite `true` if destination overwrite is allowed. + * @return the [target] file. + * @throws NoSuchFileException if the source file doesn't exist. + * @throws FileAlreadyExistsException if the destination file already exists and [overwrite] argument is set to `false`. + * @throws IOException if any errors occur while copying. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { + val options = if (overwrite) arrayOf(StandardCopyOption.REPLACE_EXISTING) else emptyArray() + return copyTo(target, *options) +} + +/** + * Copies this path to the given [target] path. + * + * If some directories on a way to the [target] are missing, then they will be created. + * If the [target] path already exists, this function will fail unless the + * [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is option is used. + * + * When [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is used and [target] is a directory, + * it is replaced only if it is empty. + * + * If this file is a directory, it is copied without its content, i.e. an empty [target] directory is created. + * If you want to copy directory including its contents, use [copyRecursively]. + * + * The operation doesn't preserve copied file attributes such as creation/modification date, + * permissions, etc. unless [COPY_ATTRIBUTES][StandardCopyOption.COPY_ATTRIBUTES] is used. + * + * @param options options to control how the path is copied. + * @return the [target] file. + * @throws NoSuchFileException if the source file doesn't exist. + * @throws FileAlreadyExistsException if the destination file already exists and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is not used. + * @throws IOException if any errors occur while copying. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { + if (!this.exists()) { + throw NoSuchFileException(toString(), null, "The source file doesn't exist.") + } + + if (target.exists() && StandardCopyOption.REPLACE_EXISTING !in options) { + throw FileAlreadyExistsException(toString(), null, "The destination file already exists.") + } + + if (this.isDirectory()) { + if (target.isDirectory() && Files.newDirectoryStream(target).use { it.firstOrNull() } != null) { + throw FileAlreadyExistsException(toString(), null, "The destination file already exists.") + } + try { + Files.createDirectories(target) + } catch (_: FileAlreadyExistsException) { + // File already exists and is not a directory + Files.delete(target) + Files.createDirectories(target) + } + } else { + target.parent?.let { Files.createDirectories(it) } + Files.copy(this, target, *options) + } + + return target +} + +/** + * Check if this file exists. + * + * @param options Options to control how symbolic links are handled. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options) + +/** + * Check if this path is a file. + * + * @param options Options to control how symbolic links are handled. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options) + +/** + * Check if this path is a directory. + * + * By default, symbolic links in the path are followed. + * + * @param options Options to control how symbolic links are handled. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(this, *options) + +/** + * Check if this path exists and is a symbolic link. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this) + +/** + * Check if this path exists and is executable. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this) + +/** + * Check if this path is considered hidden. + * + * This check is dependant on the current filesystem. For example, on UNIX-like operating systems, a + * path is considered hidden if its name begins with a dot. On Windows, file attributes are checked. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isHidden(): Boolean = Files.isHidden(this) + +/** + * Check if this path exists and is readable. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isReadable(): Boolean = Files.isReadable(this) + +/** + * Check that this path exists and is writable. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isWritable(): Boolean = Files.isWritable(this) + +/** + * Check if this path points to the same file or directory as [other]. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, other) + +/** + * Return a list of the files and directories in this directory. + * + * @throws NotDirectoryException If this path does not refer to a directory + * @throws IOException If an I/O error occurs + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.listFiles(): List { + return Files.newDirectoryStream(this).use { it.toList() } +} diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt new file mode 100644 index 00000000000..1ff78d990ca --- /dev/null +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -0,0 +1,215 @@ +/* + * Copyright 2010-2018 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.jdk7.test + +import java.nio.file.* +import kotlin.test.* + +class PathExtensionsTest { + + @Test + fun extension() { + assertEquals("bbb", Paths.get("aaa.bbb").extension) + assertEquals("", Paths.get("aaa").extension) + assertEquals("", Paths.get("aaa.").extension) + // maybe we should think that such files have name .bbb and no extension + assertEquals("bbb", Paths.get(".bbb").extension) + assertEquals("", Paths.get("/my.dir/log").extension) + } + + @Test + fun nameWithoutExtension() { + assertEquals("aaa", Paths.get("aaa.bbb").nameWithoutExtension) + assertEquals("aaa", Paths.get("aaa").nameWithoutExtension) + assertEquals("aaa", Paths.get("aaa.").nameWithoutExtension) + assertEquals("", Paths.get(".bbb").nameWithoutExtension) + assertEquals("log", Paths.get("/my.dir/log").nameWithoutExtension) + } + + @Test + fun testCopyTo() { + val srcFile = Files.createTempFile(null, null) + val dstFile = Files.createTempFile(null, null) + try { + srcFile.writeText("Hello, World!") + assertFailsWith(FileAlreadyExistsException::class, "copy do not overwrite existing file") { + srcFile.copyTo(dstFile) + } + + var dst = srcFile.copyTo(dstFile, overwrite = true) + assertSame(dst, dstFile) + compareFiles(srcFile, dst, "copy with overwrite over existing file") + + assertTrue(Files.deleteIfExists(dstFile)) + dst = srcFile.copyTo(dstFile) + compareFiles(srcFile, dst, "copy to new file") + + assertTrue(Files.deleteIfExists(dstFile)) + Files.createDirectory(dstFile) + val child = dstFile.resolve("child") + Files.createFile(child) + assertFailsWith(DirectoryNotEmptyException::class, "copy with overwrite do not overwrite non-empty dir") { + srcFile.copyTo(dstFile, overwrite = true) + } + Files.delete(child) + + srcFile.copyTo(dstFile, overwrite = true) + assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir") + + assertTrue(Files.deleteIfExists(srcFile)) + assertTrue(Files.deleteIfExists(dstFile)) + + assertFailsWith(NoSuchFileException::class) { + srcFile.copyTo(dstFile) + } + + Files.createDirectory(srcFile) + srcFile.resolve("somefile").writeText("some content") + dstFile.writeText("") + assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite file") { + srcFile.copyTo(dstFile) + } + srcFile.copyTo(dstFile, overwrite = true) + assertTrue(dstFile.isDirectory()) + assertTrue(dstFile.listFiles().isEmpty(), "only directory is copied, but not its content") + + assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite dir") { + srcFile.copyTo(dstFile) + } + + srcFile.copyTo(dstFile, overwrite = true) + assertTrue(dstFile.isDirectory()) + assertTrue(dstFile.listFiles().isEmpty(), "only directory is copied, but not its content") + + dstFile.resolve("somefile2").writeText("some content2") + assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite non-empty dir") { + srcFile.copyTo(dstFile, overwrite = true) + } + } finally { + srcFile.toFile().deleteRecursively() + dstFile.toFile().deleteRecursively() + } + } + + @Test + fun copyToNameWithoutParent() { + val currentDir = Paths.get("").toAbsolutePath() + val srcFile = Files.createTempFile(null, null) + val dstFile = Files.createTempFile(currentDir, null, null) + try { + srcFile.writeText("Hello, World!", Charsets.UTF_8) + Files.delete(dstFile) + + val dstRelative = Paths.get(dstFile.fileName.toString()) + + srcFile.copyTo(dstRelative) + + assertEquals(srcFile.readText(), dstFile.readText()) + } finally { + Files.delete(dstFile) + Files.delete(srcFile) + } + } + + private fun compareFiles(src: Path, dst: Path, message: String? = null) { + assertTrue(dst.exists()) + assertEquals(src.isFile(), dst.isFile(), message) + if (dst.isFile()) { + assertTrue(src.readBytes().contentEquals(dst.readBytes()), message) + } + } + + @Test + fun testBufferedReader() { + val file = Files.createTempFile(null, null) + val lines = listOf("line1", "line2") + Files.write(file, lines) + + assertEquals(file.bufferedReader().use { it.readLines() }, lines) + assertEquals(file.bufferedReader(StandardOpenOption.READ).use { it.readLines() }, lines) + assertEquals(file.bufferedReader(1024, StandardOpenOption.READ).use { it.readLines() }, lines) + assertEquals(file.bufferedReader(Charsets.UTF_8, StandardOpenOption.READ).use { it.readLines() }, lines) + assertEquals(file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() }, lines) + } + + @Test + fun testBufferedWriter() { + val file = Files.createTempFile(null, null) + + file.bufferedWriter().use { it.write("line1\n") } + file.bufferedWriter(StandardOpenOption.APPEND).use { it.write("line2\n") } + file.bufferedWriter(Charsets.UTF_8, StandardOpenOption.APPEND).use { it.write("line3\n") } + file.bufferedWriter(1024, StandardOpenOption.APPEND).use { it.write("line4\n") } + file.bufferedWriter(Charsets.UTF_8, 1024, StandardOpenOption.APPEND).use { it.write("line5\n") } + + assertEquals(Files.readAllLines(file), listOf("line1", "line2", "line3", "line4", "line5")) + } + + @Test + fun testPrintWriter() { + val file = Files.createTempFile(null, null) + + val writer = file.printWriter() + val str1 = "Hello, world!" + val str2 = "Everything is wonderful!" + writer.println(str1) + writer.println(str2) + writer.close() + + val writer2 = file.printWriter(StandardOpenOption.APPEND) + val str3 = "Hello again!" + writer2.println(str3) + writer2.close() + + val writer3 = file.printWriter(Charsets.UTF_8, StandardOpenOption.APPEND) + val str4 = "Hello one last time!" + writer3.println(str4) + writer3.close() + + val reader = file.bufferedReader() + assertEquals(str1, reader.readLine()) + assertEquals(str2, reader.readLine()) + assertEquals(str3, reader.readLine()) + assertEquals(str4, reader.readLine()) + } + + @Test + fun testWriteBytes() { + val file = Files.createTempFile(null, null) + file.writeBytes("Hello".encodeToByteArray()) + file.appendBytes(" world!".encodeToByteArray()) + assertEquals(file.readText(), "Hello world!") + } + + @Test + fun testAttributeGetters() { + val file = Files.createTempFile(null, null) + assertTrue(file.exists()) + assertTrue(file.isFile()) + assertFalse(file.isDirectory()) + assertFalse(file.isSymbolicLink()) + assertTrue(file.isReadable()) + assertTrue(file.isWritable()) + assertTrue(file.isSameFile(file)) + + // The default value of these depends on the current operating system, so just check that + // they don't throw an exception. + file.isExecutable() + file.isHidden() + } + + @Test + fun testListFiles() { + val dir = Files.createTempDirectory(null) + assertEquals(dir.listFiles().size, 0) + + val file = dir.resolve("f1") + Files.createFile(file) + assertEquals(dir.listFiles().size, 1) + + assertFailsWith { file.listFiles() } + } +} diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt new file mode 100644 index 00000000000..772a0e7926c --- /dev/null +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2018 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.jdk7.test + +import java.nio.file.Files +import java.nio.file.StandardOpenOption +import java.util.* +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class PathReadWriteTest { + @Test + fun testAppendText() { + val file = Files.createTempFile(null, null) + file.writeText("Hello\n") + file.appendText("World\n") + file.appendText("Again") + + assertEquals("Hello\nWorld\nAgain", file.readText()) + assertEquals(listOf("Hello", "World", "Again"), file.readLines(Charsets.UTF_8)) + file.toFile().deleteOnExit() + } + + @Test + fun file() { + val file = Files.createTempFile(null, null) + val writer = file.outputStream().writer().buffered() + + writer.write("Hello") + writer.newLine() + writer.write("World") + writer.close() + + file.forEachBlock { arr: ByteArray, size: Int -> + assertTrue(size in 11..12, size.toString()) + assertTrue(arr.contains('W'.toByte())) + } + val list = ArrayList() + file.forEachLine(StandardOpenOption.READ, charset = Charsets.UTF_8) { + list.add(it) + } + assertEquals(arrayListOf("Hello", "World"), list) + + assertEquals(arrayListOf("Hello", "World"), file.readLines()) + + file.useLines { + assertEquals(arrayListOf("Hello", "World"), it.toList()) + } + + val text = file.inputStream().reader().readText() + assertTrue(text.contains("Hello")) + assertTrue(text.contains("World")) + + file.writeText("") + var c = 0 + file.forEachLine { c++ } + assertEquals(0, c) + + file.writeText(" ") + file.forEachLine { c++ } + assertEquals(1, c) + + file.writeText(" \n") + c = 0 + file.forEachLine { c++ } + assertEquals(1, c) + + file.writeText(" \n ") + c = 0 + file.forEachLine { c++ } + assertEquals(2, c) + + file.toFile().deleteOnExit() + } +} + From b3a87356bd2be3229b828d0ea9f6f9c5fdcc2d77 Mon Sep 17 00:00:00 2001 From: AJ Date: Mon, 28 Sep 2020 14:58:37 -0700 Subject: [PATCH 021/554] Add java.nio.Path extensions to stdlib-jdk7: part 2 - Add notExists - Rename isFile to isRegularFile - Remove forEachBlock - Rename listFiles - Add relativeTo extensions - Remove extra overloads - Update doc comments - Address review comments #KT-19192 --- .../jdk7/src/kotlin/io/PathReadWrite.kt | 286 ++---------------- .../stdlib/jdk7/src/kotlin/io/PathUtils.kt | 121 ++++++-- .../stdlib/jdk7/test/PathExtensionsTest.kt | 269 +++++++++++----- .../stdlib/jdk7/test/PathReadWriteTest.kt | 81 ++++- 4 files changed, 378 insertions(+), 379 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt index 7fa4044910c..ebd950dd38a 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt @@ -17,43 +17,13 @@ import java.nio.file.OpenOption import java.nio.file.Path import java.nio.file.StandardOpenOption -/** - * The default block size for forEachBlock(). - */ -private const val DEFAULT_BLOCK_SIZE: Int = 4096 - -/** - * The minimum block size for forEachBlock(). - */ -private const val MINIMUM_BLOCK_SIZE: Int = 512 - /** * Returns a new [InputStreamReader] for reading the content of this file. */ @SinceKotlin("1.4") @ExperimentalStdlibApi @kotlin.internal.InlineOnly -public inline fun Path.reader(charset: Charset = Charsets.UTF_8): InputStreamReader { - return inputStream().reader(charset) -} - -/** - * Returns a new [InputStreamReader] for reading the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.reader(vararg options: OpenOption): InputStreamReader { - return inputStream(*options).reader() -} - -/** - * Returns a new [InputStreamReader] for reading the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.reader(charset: Charset, vararg options: OpenOption): InputStreamReader { +public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): InputStreamReader { return inputStream(*options).reader(charset) } @@ -62,63 +32,16 @@ public inline fun Path.reader(charset: Charset, vararg options: OpenOption): Inp * * @param charset character set to use. * @param bufferSize necessary size of the buffer. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedReader(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedReader { - return reader(charset).buffered(bufferSize) -} - -/** - * Returns a new [BufferedReader] for reading the content of this file. - * * @param options options to determine how the file is opened */ @SinceKotlin("1.4") @ExperimentalStdlibApi @kotlin.internal.InlineOnly -public inline fun Path.bufferedReader(vararg options: OpenOption): BufferedReader { - return reader(*options).buffered() -} - -/** - * Returns a new [BufferedReader] for reading the content of this file. - * - * @param bufferSize necessary size of the buffer. - * @param options options to determine how the file is opened - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedReader(bufferSize: Int, vararg options: OpenOption): BufferedReader { - return reader(*options).buffered(bufferSize) -} - -/** - * Returns a new [BufferedReader] for reading the content of this file. - * - * @param charset character set to use. - * @param options options to determine how the file is opened - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedReader(charset: Charset, vararg options: OpenOption): BufferedReader { - return reader(charset, *options).buffered() -} - -/** - * Returns a new [BufferedReader] for reading the content of this file. - * - * @param charset character set to use. - * @param bufferSize necessary size of the buffer. - * @param options options to determine how the file is opened - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedReader(charset: Charset, bufferSize: Int, vararg options: OpenOption): BufferedReader { +public inline fun Path.bufferedReader( + charset: Charset = Charsets.UTF_8, + bufferSize: Int = DEFAULT_BUFFER_SIZE, + vararg options: OpenOption +): BufferedReader { return reader(charset, *options).buffered(bufferSize) } @@ -128,27 +51,7 @@ public inline fun Path.bufferedReader(charset: Charset, bufferSize: Int, vararg @SinceKotlin("1.4") @ExperimentalStdlibApi @kotlin.internal.InlineOnly -public inline fun Path.writer(charset: Charset = Charsets.UTF_8): OutputStreamWriter { - return outputStream().writer(charset) -} - -/** - * Returns a new [OutputStreamWriter] for writing the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.writer(vararg options: OpenOption): OutputStreamWriter { - return outputStream(*options).writer() -} - -/** - * Returns a new [OutputStreamWriter] for writing the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.writer(charset: Charset, vararg options: OpenOption): OutputStreamWriter { +public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): OutputStreamWriter { return outputStream(*options).writer(charset) } @@ -157,63 +60,16 @@ public inline fun Path.writer(charset: Charset, vararg options: OpenOption): Out * * @param charset character set to use. * @param bufferSize necessary size of the buffer. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedWriter(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedWriter { - return writer(charset).buffered(bufferSize) -} - -/** - * Returns a new [BufferedWriter] for writing the content of this file. - * * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") @ExperimentalStdlibApi @kotlin.internal.InlineOnly -public inline fun Path.bufferedWriter(vararg options: OpenOption): BufferedWriter { - return writer(*options).buffered() -} - -/** - * Returns a new [BufferedWriter] for writing the content of this file. - * - * @param charset character set to use. - * @param options options to determine how the file is opened. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedWriter(charset: Charset, vararg options: OpenOption): BufferedWriter { - return writer(charset, *options).buffered() -} - -/** - * Returns a new [BufferedWriter] for writing the content of this file. - * - * @param bufferSize necessary size of the buffer. - * @param options options to determine how the file is opened. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedWriter(bufferSize: Int, vararg options: OpenOption): BufferedWriter { - return writer(*options).buffered(bufferSize) -} - -/** - * Returns a new [BufferedWriter] for writing the content of this file. - * - * @param charset character set to use. - * @param bufferSize necessary size of the buffer. - * @param options options to determine how the file is opened. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.bufferedWriter(charset: Charset, bufferSize: Int, vararg options: OpenOption): BufferedWriter { +public inline fun Path.bufferedWriter( + charset: Charset = Charsets.UTF_8, + bufferSize: Int = DEFAULT_BUFFER_SIZE, + vararg options: OpenOption +): BufferedWriter { return writer(charset, *options).buffered(bufferSize) } @@ -223,28 +79,8 @@ public inline fun Path.bufferedWriter(charset: Charset, bufferSize: Int, vararg @SinceKotlin("1.4") @ExperimentalStdlibApi @kotlin.internal.InlineOnly -public inline fun Path.printWriter(charset: Charset = Charsets.UTF_8): PrintWriter { - return PrintWriter(bufferedWriter(charset)) -} - -/** - * Returns a new [PrintWriter] for writing the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.printWriter(vararg options: OpenOption): PrintWriter { - return PrintWriter(bufferedWriter(*options)) -} - -/** - * Returns a new [PrintWriter] for writing the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -@kotlin.internal.InlineOnly -public inline fun Path.printWriter(charset: Charset, vararg options: OpenOption): PrintWriter { - return PrintWriter(bufferedWriter(charset, *options)) +public inline fun Path.printWriter(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): PrintWriter { + return PrintWriter(bufferedWriter(charset, options = options)) } /** @@ -301,20 +137,6 @@ public inline fun Path.appendBytes(array: ByteArray): Unit { @ExperimentalStdlibApi public fun Path.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset) -/** - * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. - * - * By default, the file will be overwritten if it already exists, but you can control this behavior - * with [options]. - * - * @param text text to write into file. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -public fun Path.writeText(text: String, vararg options: OpenOption): Unit { - writeBytes(text.toByteArray(), *options) -} - /** * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. * @@ -326,25 +148,10 @@ public fun Path.writeText(text: String, vararg options: OpenOption): Unit { */ @SinceKotlin("1.4") @ExperimentalStdlibApi -public fun Path.writeText(text: String, charset: Charset, vararg options: OpenOption): Unit { +public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Unit { writeBytes(text.toByteArray(charset), *options) } - -/** - * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. - * If this file exists, it becomes overwritten. - * - * @param text text to write into file. - * @param charset character set to use. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8): Unit { - writeBytes(text.toByteArray(charset)) -} - - /** * Appends [text] to the content of this file using UTF-8 or the specified [charset]. * @@ -357,45 +164,6 @@ public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Uni writeText(text, charset, StandardOpenOption.APPEND) } -/** - * Reads file by byte blocks and calls [action] for each block read. - * Block has default size which is implementation-dependent. - * This function passes the byte array and amount of bytes in the array to the [action] function. - * - * You can use this function for huge files. - * - * @param action function to process file blocks. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -public fun Path.forEachBlock(action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit = forEachBlock(DEFAULT_BLOCK_SIZE, action) - -/** - * Reads file by byte blocks and calls [action] for each block read. - * This functions passes the byte array and amount of bytes in the array to the [action] function. - * - * You can use this function for huge files. - * - * @param action function to process file blocks. - * @param blockSize size of a block, replaced by 512 if it's less, 4096 by default. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -public fun Path.forEachBlock(blockSize: Int, action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit { - val arr = ByteArray(blockSize.coerceAtLeast(MINIMUM_BLOCK_SIZE)) - - inputStream().use { input -> - do { - val size = input.read(arr) - if (size <= 0) { - break - } else { - action(arr, size) - } - } while (true) - } -} - /** * Reads this file line by line using the specified [charset] and calls [action] for each line. * Default charset is UTF-8. @@ -408,29 +176,13 @@ public fun Path.forEachBlock(blockSize: Int, action: (buffer: ByteArray, bytesRe */ @SinceKotlin("1.4") @ExperimentalStdlibApi -public fun Path.forEachLine(vararg options: OpenOption, charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit { +public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, vararg options: OpenOption, action: (line: String) -> Unit): Unit { // Note: close is called at forEachLine - bufferedReader(charset, *options).forEachLine(action) + bufferedReader(charset, options = options).forEachLine(action) } /** - * Reads this file line by line using the specified [charset] and calls [action] for each line. - * Default charset is UTF-8. - * - * You may use this function on huge files. - * - * @param charset character set to use. - * @param action function to process file lines. - */ -@SinceKotlin("1.4") -@ExperimentalStdlibApi -public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit { - // Note: close is called at forEachLine - bufferedReader(charset = charset).forEachLine(action) -} - -/** - * Constructs a new InputStream of this path and returns it as a result. + * Constructs a new InputStream of this file and returns it as a result. * * The [options] parameter determines how the file is opened. If no options are present then it is * equivalent to opening the file with the [READ][StandardOpenOption.READ] option. @@ -448,7 +200,7 @@ public inline fun Path.inputStream(vararg options: OpenOption): InputStream { * The [options] parameter determines how the file is opened. If no options are present then it is * equivalent to opening the file with the [CREATE][StandardOpenOption.CREATE], * [TRUNCATE_EXISTING][StandardOpenOption.TRUNCATE_EXISTING], and [WRITE][StandardOpenOption.WRITE] - * option. + * options. */ @SinceKotlin("1.4") @ExperimentalStdlibApi diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt index e427bab2a2d..2d34729e147 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt @@ -10,23 +10,21 @@ package kotlin.io -import java.io.File import java.io.IOException -import java.nio.channels.FileChannel import java.nio.file.* import java.nio.file.FileAlreadyExistsException import java.nio.file.NoSuchFileException /** - * Returns the extension of this file (not including the dot), or an empty string if it doesn't have one. + * Returns the extension of this path (not including the dot), or an empty string if it doesn't have one. */ @SinceKotlin("1.4") @ExperimentalStdlibApi public val Path.extension: String - get() = fileName.toString().substringAfterLast('.', "") + get() = fileName?.toString()?.substringAfterLast('.', "") ?: "" /** - * Returns [path][File.path] of this File using the invariant separator '/' to + * Returns this path as a [String] using the invariant separator '/' to * separate the names in the name sequence. */ @SinceKotlin("1.4") @@ -38,13 +36,55 @@ public val Path.invariantSeparatorsPath: String } /** - * Returns file's name without an extension. + * Returns this path's [fileName][Path.getFileName] without an extension, or an empty string if + * this path has zero elements. */ @SinceKotlin("1.4") @ExperimentalStdlibApi public val Path.nameWithoutExtension: String - get() = fileName.toString().substringBeforeLast(".") + get() = fileName?.toString()?.substringBeforeLast(".") ?: "" +/** + * Calculates the relative path for this path from a [base] path. + * Note that the [base] path is treated as a directory. + * If this path matches the [base] path, then a [Path] with an empty path will be returned. + * + * @return Path with relative path from [base] to this. + * + * @throws IllegalArgumentException if this and base paths have different roots. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.relativeTo(base: Path): Path = base.relativize(this) + +/** + * Calculates the relative path for this path from a [base] path. + * Note that the [base] path is treated as a directory. + * If this path matches the [base] path, then a [Path] with an empty path will be returned. + * + * @return Path with relative path from [base] to this, or `this` if this and base paths have different roots. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.relativeToOrSelf(base: Path): Path = + relativeToOrNull(base) ?: this + +/** + * Calculates the relative path for this path from a [base] path. + * Note that the [base] path is treated as a directory. + * If this path matches the [base] path, then a [Path] with an empty path will be returned. + * + * @return Path with relative path from [base] to this, or `null` if this and base paths have different roots. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.relativeToOrNull(base: Path): Path? { + return try { + base.relativize(this) + } catch (e: IllegalArgumentException) { + null + } +} /** * Copies this path to the given [target] path. @@ -54,15 +94,15 @@ public val Path.nameWithoutExtension: String * * When [overwrite] is `true` and [target] is a directory, it is replaced only if it is empty. * - * If this file is a directory, it is copied without its content, i.e. an empty [target] directory is created. + * If this path is a directory, it is copied without its content, i.e. an empty [target] directory is created. * If you want to copy directory including its contents, use [copyRecursively]. * * The operation doesn't preserve copied file attributes such as creation/modification date, permissions, etc. * * @param overwrite `true` if destination overwrite is allowed. - * @return the [target] file. - * @throws NoSuchFileException if the source file doesn't exist. - * @throws FileAlreadyExistsException if the destination file already exists and [overwrite] argument is set to `false`. + * @return the [target] path. + * @throws NoSuchFileException if the source path doesn't exist. + * @throws FileAlreadyExistsException if the destination path already exists and [overwrite] argument is set to `false`. * @throws IOException if any errors occur while copying. */ @SinceKotlin("1.4") @@ -82,32 +122,32 @@ public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { * When [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is used and [target] is a directory, * it is replaced only if it is empty. * - * If this file is a directory, it is copied without its content, i.e. an empty [target] directory is created. + * If this path is a directory, it is copied without its content, i.e. an empty [target] directory is created. * If you want to copy directory including its contents, use [copyRecursively]. * * The operation doesn't preserve copied file attributes such as creation/modification date, * permissions, etc. unless [COPY_ATTRIBUTES][StandardCopyOption.COPY_ATTRIBUTES] is used. * * @param options options to control how the path is copied. - * @return the [target] file. - * @throws NoSuchFileException if the source file doesn't exist. - * @throws FileAlreadyExistsException if the destination file already exists and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is not used. + * @return the [target] path. + * @throws NoSuchFileException if the source path doesn't exist. + * @throws FileAlreadyExistsException if the destination path already exists and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is not used. * @throws IOException if any errors occur while copying. */ @SinceKotlin("1.4") @ExperimentalStdlibApi public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { - if (!this.exists()) { - throw NoSuchFileException(toString(), null, "The source file doesn't exist.") + if (this.notExists()) { + throw NoSuchFileException(toString(), null, "The source path doesn't exist.") } if (target.exists() && StandardCopyOption.REPLACE_EXISTING !in options) { - throw FileAlreadyExistsException(toString(), null, "The destination file already exists.") + throw FileAlreadyExistsException(toString(), null, "The destination path already exists.") } if (this.isDirectory()) { if (target.isDirectory() && Files.newDirectoryStream(target).use { it.firstOrNull() } != null) { - throw FileAlreadyExistsException(toString(), null, "The destination file already exists.") + throw FileAlreadyExistsException(toString(), null, "The destination path already exists.") } try { Files.createDirectories(target) @@ -125,7 +165,7 @@ public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { } /** - * Check if this file exists. + * Check if this path exists. * * @param options Options to control how symbolic links are handled. */ @@ -134,6 +174,16 @@ public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { @kotlin.internal.InlineOnly public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options) +/** + * Check if this path does not exist. + * + * @param options Options to control how symbolic links are handled. + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.notExists(this, *options) + /** * Check if this path is a file. * @@ -142,7 +192,7 @@ public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exist @SinceKotlin("1.4") @ExperimentalStdlibApi @kotlin.internal.InlineOnly -public inline fun Path.isFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options) +public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options) /** * Check if this path is a directory. @@ -208,13 +258,38 @@ public inline fun Path.isWritable(): Boolean = Files.isWritable(this) public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, other) /** - * Return a list of the files and directories in this directory. + * Return a list of the entries in this directory. * * @throws NotDirectoryException If this path does not refer to a directory * @throws IOException If an I/O error occurs */ @SinceKotlin("1.4") @ExperimentalStdlibApi -public fun Path.listFiles(): List { +public fun Path.listDirectoryEntries(): List { return Files.newDirectoryStream(this).use { it.toList() } } + +/** + * Call the [block] callback with a sequence of all entries in this directory. + * + * @throws NotDirectoryException If this path does not refer to a directory + * @throws IOException If an I/O error occurs + * @return the value returned by [block] + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.useDirectoryEntries(block: (Sequence) -> T): T { + return Files.newDirectoryStream(this).use { block(it.asSequence()) } +} + +/** + * Perform the given [action] on each entry in this directory. + * + * @throws NotDirectoryException If this path does not refer to a directory + * @throws IOException If an I/O error occurs + */ +@SinceKotlin("1.4") +@ExperimentalStdlibApi +public fun Path.forEachDirectoryEntry(action: (Path) -> Unit) { + return Files.newDirectoryStream(this).use { it.forEach(action) } +} diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 1ff78d990ca..2a3ed420bee 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -1,23 +1,26 @@ /* - * 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.jdk7.test +import java.io.IOException import java.nio.file.* import kotlin.test.* class PathExtensionsTest { + private val isCaseInsensitiveFileSystem = Paths.get("C:/") == Paths.get("c:/") + private val isBackslashSeparator = FileSystems.getDefault().separator == "\\" @Test fun extension() { assertEquals("bbb", Paths.get("aaa.bbb").extension) assertEquals("", Paths.get("aaa").extension) assertEquals("", Paths.get("aaa.").extension) - // maybe we should think that such files have name .bbb and no extension assertEquals("bbb", Paths.get(".bbb").extension) assertEquals("", Paths.get("/my.dir/log").extension) + assertEquals("", Paths.get("/").extension) } @Test @@ -27,6 +30,8 @@ class PathExtensionsTest { assertEquals("aaa", Paths.get("aaa.").nameWithoutExtension) assertEquals("", Paths.get(".bbb").nameWithoutExtension) assertEquals("log", Paths.get("/my.dir/log").nameWithoutExtension) + assertEquals("", Paths.get("").nameWithoutExtension) + assertEquals("", Paths.get("/").nameWithoutExtension) } @Test @@ -74,7 +79,7 @@ class PathExtensionsTest { } srcFile.copyTo(dstFile, overwrite = true) assertTrue(dstFile.isDirectory()) - assertTrue(dstFile.listFiles().isEmpty(), "only directory is copied, but not its content") + assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite dir") { srcFile.copyTo(dstFile) @@ -82,7 +87,7 @@ class PathExtensionsTest { srcFile.copyTo(dstFile, overwrite = true) assertTrue(dstFile.isDirectory()) - assertTrue(dstFile.listFiles().isEmpty(), "only directory is copied, but not its content") + assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") dstFile.resolve("somefile2").writeText("some content2") assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite non-empty dir") { @@ -116,79 +121,18 @@ class PathExtensionsTest { private fun compareFiles(src: Path, dst: Path, message: String? = null) { assertTrue(dst.exists()) - assertEquals(src.isFile(), dst.isFile(), message) - if (dst.isFile()) { + assertEquals(src.isRegularFile(), dst.isRegularFile(), message) + if (dst.isRegularFile()) { assertTrue(src.readBytes().contentEquals(dst.readBytes()), message) } } @Test - fun testBufferedReader() { - val file = Files.createTempFile(null, null) - val lines = listOf("line1", "line2") - Files.write(file, lines) - - assertEquals(file.bufferedReader().use { it.readLines() }, lines) - assertEquals(file.bufferedReader(StandardOpenOption.READ).use { it.readLines() }, lines) - assertEquals(file.bufferedReader(1024, StandardOpenOption.READ).use { it.readLines() }, lines) - assertEquals(file.bufferedReader(Charsets.UTF_8, StandardOpenOption.READ).use { it.readLines() }, lines) - assertEquals(file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() }, lines) - } - - @Test - fun testBufferedWriter() { - val file = Files.createTempFile(null, null) - - file.bufferedWriter().use { it.write("line1\n") } - file.bufferedWriter(StandardOpenOption.APPEND).use { it.write("line2\n") } - file.bufferedWriter(Charsets.UTF_8, StandardOpenOption.APPEND).use { it.write("line3\n") } - file.bufferedWriter(1024, StandardOpenOption.APPEND).use { it.write("line4\n") } - file.bufferedWriter(Charsets.UTF_8, 1024, StandardOpenOption.APPEND).use { it.write("line5\n") } - - assertEquals(Files.readAllLines(file), listOf("line1", "line2", "line3", "line4", "line5")) - } - - @Test - fun testPrintWriter() { - val file = Files.createTempFile(null, null) - - val writer = file.printWriter() - val str1 = "Hello, world!" - val str2 = "Everything is wonderful!" - writer.println(str1) - writer.println(str2) - writer.close() - - val writer2 = file.printWriter(StandardOpenOption.APPEND) - val str3 = "Hello again!" - writer2.println(str3) - writer2.close() - - val writer3 = file.printWriter(Charsets.UTF_8, StandardOpenOption.APPEND) - val str4 = "Hello one last time!" - writer3.println(str4) - writer3.close() - - val reader = file.bufferedReader() - assertEquals(str1, reader.readLine()) - assertEquals(str2, reader.readLine()) - assertEquals(str3, reader.readLine()) - assertEquals(str4, reader.readLine()) - } - - @Test - fun testWriteBytes() { - val file = Files.createTempFile(null, null) - file.writeBytes("Hello".encodeToByteArray()) - file.appendBytes(" world!".encodeToByteArray()) - assertEquals(file.readText(), "Hello world!") - } - - @Test - fun testAttributeGetters() { + fun testAttributeGettersOnFile() { val file = Files.createTempFile(null, null) assertTrue(file.exists()) - assertTrue(file.isFile()) + assertFalse(file.notExists()) + assertTrue(file.isRegularFile()) assertFalse(file.isDirectory()) assertFalse(file.isSymbolicLink()) assertTrue(file.isReadable()) @@ -202,14 +146,191 @@ class PathExtensionsTest { } @Test - fun testListFiles() { + fun testAttributeGettersOnDirectory() { + val file = Files.createTempDirectory(null) + assertTrue(file.exists()) + assertFalse(file.notExists()) + assertFalse(file.isRegularFile()) + assertTrue(file.isDirectory()) + assertFalse(file.isSymbolicLink()) + assertTrue(file.isReadable()) + assertTrue(file.isWritable()) + assertTrue(file.isSameFile(file)) + + file.isExecutable() + file.isHidden() + } + + @Test + fun testAttributeGettersOnNonExistentPath() { + val file = Files.createTempDirectory(null).resolve("foo") + assertFalse(file.exists()) + assertTrue(file.notExists()) + assertFalse(file.isRegularFile()) + assertFalse(file.isDirectory()) + assertFalse(file.isSymbolicLink()) + assertFalse(file.isReadable()) + assertFalse(file.isWritable()) + assertTrue(file.isSameFile(file)) + + file.isExecutable() + // This function will either throw an exception or return false, + // depending on the operating system. + try { + assertFalse(file.isHidden()) + } catch (e: IOException) { + } + } + + @Test + fun testListDirectoryEntries() { val dir = Files.createTempDirectory(null) - assertEquals(dir.listFiles().size, 0) + assertEquals(0, dir.listDirectoryEntries().size) val file = dir.resolve("f1") Files.createFile(file) - assertEquals(dir.listFiles().size, 1) + assertEquals(listOf(file), dir.listDirectoryEntries()) - assertFailsWith { file.listFiles() } + assertFailsWith { file.listDirectoryEntries() } + } + + @Test + fun testUseDirectoryEntries() { + val dir = Files.createTempDirectory(null) + assertEquals(0, dir.useDirectoryEntries { it.toList() }.size) + + val file = dir.resolve("f1") + Files.createFile(file) + assertEquals(listOf(file), dir.useDirectoryEntries { it.toList() }) + + assertFailsWith { file.useDirectoryEntries { it.toList() } } + } + + @Test + fun testForEachDirectoryEntry() { + val dir = Files.createTempDirectory(null) + val entries = mutableListOf() + + dir.forEachDirectoryEntry { entries.add(it) } + assertTrue(entries.isEmpty()) + + val file = dir.resolve("f1") + Files.createFile(file) + dir.forEachDirectoryEntry { entries.add(it) } + assertEquals(listOf(file), entries) + + assertFailsWith { file.forEachDirectoryEntry { } } + } + + @Test + fun relativeToRooted() { + val file1 = Paths.get("/foo/bar/baz") + val file2 = Paths.get("/foo/baa/ghoo") + + assertEquals("../../bar/baz", file1.relativeTo(file2).invariantSeparatorsPath) + + val file3 = Paths.get("/foo/bar") + + assertEquals("baz", file1.relativeTo(file3).toString()) + assertEquals("..", file3.relativeTo(file1).toString()) + + val file4 = Paths.get("/foo/bar/") + + assertEquals("baz", file1.relativeTo(file4).toString()) + assertEquals("..", file4.relativeTo(file1).toString()) + assertEquals("", file3.relativeTo(file4).toString()) + assertEquals("", file4.relativeTo(file3).toString()) + + val file5 = Paths.get("/foo/baran") + + assertEquals("../bar", file3.relativeTo(file5).invariantSeparatorsPath) + assertEquals("../baran", file5.relativeTo(file3).invariantSeparatorsPath) + assertEquals("../bar", file4.relativeTo(file5).invariantSeparatorsPath) + assertEquals("../baran", file5.relativeTo(file4).invariantSeparatorsPath) + + if (isBackslashSeparator) { + val file6 = Paths.get("C:\\Users\\Me") + val file7 = Paths.get("C:\\Users\\Me\\Documents") + + assertEquals("..", file6.relativeTo(file7).toString()) + assertEquals("Documents", file7.relativeTo(file6).toString()) + + val file8 = Paths.get("""\\my.host\home/user/documents/vip""") + val file9 = Paths.get("""\\my.host\home/other/images/nice""") + + assertEquals("../../../user/documents/vip", file8.relativeTo(file9).invariantSeparatorsPath) + assertEquals("../../../other/images/nice", file9.relativeTo(file8).invariantSeparatorsPath) + } + + if (isCaseInsensitiveFileSystem) { + assertEquals("bar", Paths.get("C:/bar").relativeTo(Paths.get("c:/")).toString()) + } + } + + @Test + fun relativeToRelative() { + val nested = Paths.get("foo/bar") + val base = Paths.get("foo") + + assertEquals("bar", nested.relativeTo(base).toString()) + assertEquals("..", base.relativeTo(nested).toString()) + + val current = Paths.get(".") + val parent = Paths.get("..") + val outOfRoot = Paths.get("../bar") + + assertEquals(Paths.get("../../bar"), outOfRoot.relativeTo(base)) + assertEquals("bar", outOfRoot.relativeTo(parent).toString()) + assertEquals("..", parent.relativeTo(outOfRoot).toString()) + + val root = Paths.get("/root") + val files = listOf(nested, base, outOfRoot, current, parent) + val bases = listOf(nested, base, current) + + for (file in files) + assertEquals("", file.relativeTo(file).toString(), "file should have empty path relative to itself: $file") + + for (file in files) { + @Suppress("NAME_SHADOWING") + for (base in bases) { + val rootedFile = root.resolve(file) + val rootedBase = root.resolve(base) + assertEquals(file.relativeTo(base), rootedFile.relativeTo(rootedBase), "nested: $file, base: $base") + } + } + } + + @Test + fun relativeToFails() { + val absolute = Paths.get("/foo/bar/baz") + val relative = Paths.get("foo/bar") + val networkShare1 = Paths.get("""\\my.host\share1/folder""") + val networkShare2 = Paths.get("""\\my.host\share2\folder""") + + fun assertFailsRelativeTo(file: Path, base: Path) { + val e = assertFailsWith("file: $file, base: $base") { file.relativeTo(base) } + assertNotNull(e.message) + } + + val allFiles = listOf(absolute, relative) + if (isBackslashSeparator) listOf(networkShare1, networkShare2) else emptyList() + for (file in allFiles) { + for (base in allFiles) { + if (file != base) assertFailsRelativeTo(file, base) + } + } + + if (isBackslashSeparator) { + val fileOnC = Paths.get("C:/dir1") + val fileOnD = Paths.get("D:/dir2") + assertFailsRelativeTo(fileOnC, fileOnD) + } + } + + @Test + fun relativeTo() { + assertEquals("kotlin", Paths.get("src/kotlin").relativeTo(Paths.get("src")).toString()) + assertEquals("", Paths.get("dir").relativeTo(Paths.get("dir")).toString()) + assertEquals("..", Paths.get("dir").relativeTo(Paths.get("dir/subdir")).toString()) + assertEquals(Paths.get("../../test"), Paths.get("test").relativeTo(Paths.get("dir/dir"))) } } diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt index 772a0e7926c..bbfa8406486 100644 --- a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.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,9 +8,7 @@ package kotlin.jdk7.test import java.nio.file.Files import java.nio.file.StandardOpenOption import java.util.* -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue +import kotlin.test.* class PathReadWriteTest { @Test @@ -18,7 +16,7 @@ class PathReadWriteTest { val file = Files.createTempFile(null, null) file.writeText("Hello\n") file.appendText("World\n") - file.appendText("Again") + file.writeText("Again", Charsets.US_ASCII, StandardOpenOption.APPEND) assertEquals("Hello\nWorld\nAgain", file.readText()) assertEquals(listOf("Hello", "World", "Again"), file.readLines(Charsets.UTF_8)) @@ -35,25 +33,21 @@ class PathReadWriteTest { writer.write("World") writer.close() - file.forEachBlock { arr: ByteArray, size: Int -> - assertTrue(size in 11..12, size.toString()) - assertTrue(arr.contains('W'.toByte())) - } val list = ArrayList() - file.forEachLine(StandardOpenOption.READ, charset = Charsets.UTF_8) { + file.forEachLine(charset = Charsets.UTF_8, options = arrayOf(StandardOpenOption.READ)) { list.add(it) } - assertEquals(arrayListOf("Hello", "World"), list) + assertEquals(listOf("Hello", "World"), list) - assertEquals(arrayListOf("Hello", "World"), file.readLines()) + assertEquals(listOf("Hello", "World"), file.readLines()) file.useLines { - assertEquals(arrayListOf("Hello", "World"), it.toList()) + assertEquals(listOf("Hello", "World"), it.toList()) } val text = file.inputStream().reader().readText() - assertTrue(text.contains("Hello")) - assertTrue(text.contains("World")) + assertTrue("Hello" in text) + assertTrue("World" in text) file.writeText("") var c = 0 @@ -76,5 +70,62 @@ class PathReadWriteTest { file.toFile().deleteOnExit() } + + @Test + fun testBufferedReader() { + val file = Files.createTempFile(null, null) + val lines = listOf("line1", "line2") + Files.write(file, lines, Charsets.UTF_8) + + assertEquals(file.bufferedReader().use { it.readLines() }, lines) + assertEquals(file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() }, lines) + } + + @Test + fun testBufferedWriter() { + val file = Files.createTempFile(null, null) + + file.bufferedWriter().use { it.write("line1\n") } + file.bufferedWriter(Charsets.UTF_8, 1024, StandardOpenOption.APPEND).use { it.write("line2\n") } + + assertEquals(Files.readAllLines(file, Charsets.UTF_8), listOf("line1", "line2")) + } + + @Test + fun testPrintWriter() { + val file = Files.createTempFile(null, null) + + val writer = file.printWriter() + val str1 = "Hello, world!" + val str2 = "Everything is wonderful!" + writer.println(str1) + writer.println(str2) + writer.close() + + val writer2 = file.printWriter(options = arrayOf(StandardOpenOption.APPEND)) + val str3 = "Hello again!" + writer2.println(str3) + writer2.close() + + val writer3 = file.printWriter(Charsets.UTF_8, StandardOpenOption.APPEND) + val str4 = "Hello one last time!" + writer3.println(str4) + writer3.close() + + file.bufferedReader().use { reader -> + assertEquals(str1, reader.readLine()) + assertEquals(str2, reader.readLine()) + assertEquals(str3, reader.readLine()) + assertEquals(str4, reader.readLine()) + } + } + + @Test + fun testWriteBytes() { + val file = Files.createTempFile(null, null) + file.writeBytes("Hello".encodeToByteArray()) + file.appendBytes(" world!".encodeToByteArray()) + assertEquals(file.readText(), "Hello world!") + } } From f6d240020829001ed972d0d37092e731898d60e3 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 6 Oct 2020 21:34:02 +0300 Subject: [PATCH 022/554] Workaround bugs in Path.relativize Also add actual paths to the relativeTo error message. #KT-19192 --- .../stdlib/jdk7/src/kotlin/io/PathUtils.kt | 43 ++++++- .../stdlib/jdk7/test/PathExtensionsTest.kt | 115 +++++++++++------- 2 files changed, 105 insertions(+), 53 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt index 2d34729e147..a28d163a222 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt @@ -55,7 +55,11 @@ public val Path.nameWithoutExtension: String */ @SinceKotlin("1.4") @ExperimentalStdlibApi -public fun Path.relativeTo(base: Path): Path = base.relativize(this) +public fun Path.relativeTo(base: Path): Path = try { + PathRelativizer.tryRelativeTo(this, base) +} catch (e: IllegalArgumentException) { + throw java.lang.IllegalArgumentException(e.message + "\nthis path: $this\nbase path: $base", e) +} /** * Calculates the relative path for this path from a [base] path. @@ -78,11 +82,38 @@ public fun Path.relativeToOrSelf(base: Path): Path = */ @SinceKotlin("1.4") @ExperimentalStdlibApi -public fun Path.relativeToOrNull(base: Path): Path? { - return try { - base.relativize(this) - } catch (e: IllegalArgumentException) { - null +public fun Path.relativeToOrNull(base: Path): Path? = try { + PathRelativizer.tryRelativeTo(this, base) +} catch (e: IllegalArgumentException) { + null +} + +internal object PathRelativizer { + private val emptyPath = Paths.get("") + private val parentPath = Paths.get("..") + + // Workarounds some bugs in Path.relativize that were fixed only in JDK9 + fun tryRelativeTo(path: Path, base: Path): Path { + val bn = base.normalize() + val pn = path.normalize() + val rn = bn.relativize(pn) + // work around https://bugs.openjdk.java.net/browse/JDK-8066943 + for (i in 0 until minOf(bn.nameCount, pn.nameCount)) { + if (bn.getName(i) != parentPath) break + if (pn.getName(i) != parentPath) throw IllegalArgumentException("Unable to compute relative path") + } + // work around https://bugs.openjdk.java.net/browse/JDK-8072495 + val r = if (pn != bn && bn == emptyPath) { + pn + } else { + val rnString = rn.toString() + // drop invalid dangling separator from path string https://bugs.openjdk.java.net/browse/JDK-8140449 + if (rnString.endsWith(rn.fileSystem.separator)) + rn.fileSystem.getPath(rnString.dropLast(rn.fileSystem.separator.length)) + else + rn + } + return r } } diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 2a3ed420bee..82a1ec089b4 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -222,48 +222,68 @@ class PathExtensionsTest { assertFailsWith { file.forEachDirectoryEntry { } } } + + private fun testRelativeTo(expected: String?, path: String, base: String) = + testRelativeTo(expected?.let { Paths.get(it) }, Paths.get(path), Paths.get(base)) + private fun testRelativeTo(expected: String, path: Path, base: Path) = + testRelativeTo(Paths.get(expected), path, base) + + private fun testRelativeTo(expected: Path?, path: Path, base: Path) { + val context = "path: '$path', base: '$base'" + if (expected != null) { + assertEquals(expected, path.relativeTo(base), context) + } else { + val e = assertFailsWith(context) { path.relativeTo(base) } + val message = assertNotNull(e.message) + assertTrue(path.toString() in message, message) + assertTrue(base.toString() in message, message) + } + assertEquals(expected, path.relativeToOrNull(base), context) + assertEquals(expected ?: path, path.relativeToOrSelf(base), context) + } + @Test fun relativeToRooted() { - val file1 = Paths.get("/foo/bar/baz") - val file2 = Paths.get("/foo/baa/ghoo") + val file1 = "/foo/bar/baz" + val file2 = "/foo/baa/ghoo" - assertEquals("../../bar/baz", file1.relativeTo(file2).invariantSeparatorsPath) + testRelativeTo("../../bar/baz", file1, file2) - val file3 = Paths.get("/foo/bar") + val file3 = "/foo/bar" - assertEquals("baz", file1.relativeTo(file3).toString()) - assertEquals("..", file3.relativeTo(file1).toString()) + testRelativeTo("baz", file1, file3) + testRelativeTo("..", file3, file1) - val file4 = Paths.get("/foo/bar/") + val file4 = "/foo/bar/" - assertEquals("baz", file1.relativeTo(file4).toString()) - assertEquals("..", file4.relativeTo(file1).toString()) - assertEquals("", file3.relativeTo(file4).toString()) - assertEquals("", file4.relativeTo(file3).toString()) + testRelativeTo("baz", file1, file4) + testRelativeTo("..", file4, file1) + testRelativeTo("", file3, file4) + testRelativeTo("", file4, file3) - val file5 = Paths.get("/foo/baran") + val file5 = "/foo/baran" - assertEquals("../bar", file3.relativeTo(file5).invariantSeparatorsPath) - assertEquals("../baran", file5.relativeTo(file3).invariantSeparatorsPath) - assertEquals("../bar", file4.relativeTo(file5).invariantSeparatorsPath) - assertEquals("../baran", file5.relativeTo(file4).invariantSeparatorsPath) + testRelativeTo("../bar", file3, file5) + testRelativeTo("../baran", file5, file3) + testRelativeTo("../bar", file4, file5) + testRelativeTo("../baran", file5, file4) if (isBackslashSeparator) { - val file6 = Paths.get("C:\\Users\\Me") - val file7 = Paths.get("C:\\Users\\Me\\Documents") + val file6 = "C:\\Users\\Me" + val file7 = "C:\\Users\\Me\\Documents" - assertEquals("..", file6.relativeTo(file7).toString()) - assertEquals("Documents", file7.relativeTo(file6).toString()) + testRelativeTo("..", file6, file7) + testRelativeTo("Documents", file7, file6) - val file8 = Paths.get("""\\my.host\home/user/documents/vip""") - val file9 = Paths.get("""\\my.host\home/other/images/nice""") + val file8 = """\\my.host\home/user/documents/vip""" + val file9 = """\\my.host\home/other/images/nice""" - assertEquals("../../../user/documents/vip", file8.relativeTo(file9).invariantSeparatorsPath) - assertEquals("../../../other/images/nice", file9.relativeTo(file8).invariantSeparatorsPath) + testRelativeTo("../../../user/documents/vip", file8, file9) + testRelativeTo("../../../other/images/nice", file9, file8) } if (isCaseInsensitiveFileSystem) { - assertEquals("bar", Paths.get("C:/bar").relativeTo(Paths.get("c:/")).toString()) + testRelativeTo("bar", "C:/bar", "c:/") } } @@ -272,30 +292,33 @@ class PathExtensionsTest { val nested = Paths.get("foo/bar") val base = Paths.get("foo") - assertEquals("bar", nested.relativeTo(base).toString()) - assertEquals("..", base.relativeTo(nested).toString()) + testRelativeTo("bar", nested, base) + testRelativeTo("..", base, nested) + val empty = Paths.get("") val current = Paths.get(".") val parent = Paths.get("..") val outOfRoot = Paths.get("../bar") - assertEquals(Paths.get("../../bar"), outOfRoot.relativeTo(base)) - assertEquals("bar", outOfRoot.relativeTo(parent).toString()) - assertEquals("..", parent.relativeTo(outOfRoot).toString()) + testRelativeTo("../bar", outOfRoot, empty) + testRelativeTo("../../bar", outOfRoot, base) + testRelativeTo("bar", outOfRoot, parent) + testRelativeTo("..", parent, outOfRoot) val root = Paths.get("/root") - val files = listOf(nested, base, outOfRoot, current, parent) - val bases = listOf(nested, base, current) + val files = listOf(nested, base, empty, outOfRoot, current, parent) + val bases = listOf(nested, base, empty, current) for (file in files) - assertEquals("", file.relativeTo(file).toString(), "file should have empty path relative to itself: $file") + // file should have empty path relative to itself + testRelativeTo("", file, file) for (file in files) { @Suppress("NAME_SHADOWING") for (base in bases) { val rootedFile = root.resolve(file) val rootedBase = root.resolve(base) - assertEquals(file.relativeTo(base), rootedFile.relativeTo(rootedBase), "nested: $file, base: $base") + assertEquals(rootedFile.relativeTo(rootedBase), file.relativeTo(base), "nested: $file, base: $base") } } } @@ -307,30 +330,28 @@ class PathExtensionsTest { val networkShare1 = Paths.get("""\\my.host\share1/folder""") val networkShare2 = Paths.get("""\\my.host\share2\folder""") - fun assertFailsRelativeTo(file: Path, base: Path) { - val e = assertFailsWith("file: $file, base: $base") { file.relativeTo(base) } - assertNotNull(e.message) - } - val allFiles = listOf(absolute, relative) + if (isBackslashSeparator) listOf(networkShare1, networkShare2) else emptyList() for (file in allFiles) { for (base in allFiles) { - if (file != base) assertFailsRelativeTo(file, base) + if (file != base) testRelativeTo(null, file, base) } } if (isBackslashSeparator) { - val fileOnC = Paths.get("C:/dir1") - val fileOnD = Paths.get("D:/dir2") - assertFailsRelativeTo(fileOnC, fileOnD) + testRelativeTo(null, "C:/dir1", "D:/dir2") } + + testRelativeTo(null, "foo", "..") + testRelativeTo(null, "../foo", "../..") } @Test fun relativeTo() { - assertEquals("kotlin", Paths.get("src/kotlin").relativeTo(Paths.get("src")).toString()) - assertEquals("", Paths.get("dir").relativeTo(Paths.get("dir")).toString()) - assertEquals("..", Paths.get("dir").relativeTo(Paths.get("dir/subdir")).toString()) - assertEquals(Paths.get("../../test"), Paths.get("test").relativeTo(Paths.get("dir/dir"))) + testRelativeTo("kotlin", "src/kotlin", "src") + testRelativeTo("", "dir", "dir") + testRelativeTo("..", "dir", "dir/subdir") + testRelativeTo("../../test", "test", "dir/dir") + testRelativeTo("foo/bar", "../../foo/bar", "../../sub/../.") + testRelativeTo(null, "../../foo/bar", "../../sub/../..") } } From 7d58a5e2f22985396418983240578b0e202da8da Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 8 Oct 2020 16:07:53 +0300 Subject: [PATCH 023/554] Simplify Path.copyTo implementation Delegate most checks to the platform Files.copy. This changes the exception type thrown in one case, so document when it happens. Also 'copyTo' no longer creates target parent directory if it doesn't exist. #KT-19192 --- .../stdlib/jdk7/src/kotlin/io/PathUtils.kt | 48 ++++++++----------- .../stdlib/jdk7/test/PathExtensionsTest.kt | 21 +++++--- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt index a28d163a222..bfb666a8bdf 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt @@ -120,7 +120,12 @@ internal object PathRelativizer { /** * Copies this path to the given [target] path. * - * If some directories on a way to the [target] are missing, then they will be created. + * Unlike `File.copyTo`, if some directories on a way to the [target] are missing, then they won't be created automatically. + * You can use the following approach to ensure that required intermediate directories are created: + * ``` + * sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() }) + * ``` + * * If the [target] path already exists, this function will fail unless [overwrite] argument is set to `true`. * * When [overwrite] is `true` and [target] is a directory, it is replaced only if it is empty. @@ -134,6 +139,8 @@ internal object PathRelativizer { * @return the [target] path. * @throws NoSuchFileException if the source path doesn't exist. * @throws FileAlreadyExistsException if the destination path already exists and [overwrite] argument is set to `false`. + * @throws DirectoryNotEmptyException if the destination path point to an existing directory and [overwrite] argument is `true`, + * when the directory being replaced is not empty. * @throws IOException if any errors occur while copying. */ @SinceKotlin("1.4") @@ -146,15 +153,20 @@ public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { /** * Copies this path to the given [target] path. * - * If some directories on a way to the [target] are missing, then they will be created. + * Unlike `File.copyTo`, if some directories on a way to the [target] are missing, then they won't be created automatically. + * You can use the following approach to ensure that required intermediate directories are created: + * ``` + * sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() }) + * ``` + * * If the [target] path already exists, this function will fail unless the * [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is option is used. * * When [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is used and [target] is a directory, * it is replaced only if it is empty. * - * If this path is a directory, it is copied without its content, i.e. an empty [target] directory is created. - * If you want to copy directory including its contents, use [copyRecursively]. + * If this path is a directory, it is copied *without* its content, i.e. an empty [target] directory is created. + * If you want to copy a directory including its contents, use [copyRecursively]. * * The operation doesn't preserve copied file attributes such as creation/modification date, * permissions, etc. unless [COPY_ATTRIBUTES][StandardCopyOption.COPY_ATTRIBUTES] is used. @@ -163,36 +175,14 @@ public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { * @return the [target] path. * @throws NoSuchFileException if the source path doesn't exist. * @throws FileAlreadyExistsException if the destination path already exists and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is not used. + * @throws DirectoryNotEmptyException if the destination path point to an existing directory and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is used, + * when the directory being replaced is not empty. * @throws IOException if any errors occur while copying. */ @SinceKotlin("1.4") @ExperimentalStdlibApi public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { - if (this.notExists()) { - throw NoSuchFileException(toString(), null, "The source path doesn't exist.") - } - - if (target.exists() && StandardCopyOption.REPLACE_EXISTING !in options) { - throw FileAlreadyExistsException(toString(), null, "The destination path already exists.") - } - - if (this.isDirectory()) { - if (target.isDirectory() && Files.newDirectoryStream(target).use { it.firstOrNull() } != null) { - throw FileAlreadyExistsException(toString(), null, "The destination path already exists.") - } - try { - Files.createDirectories(target) - } catch (_: FileAlreadyExistsException) { - // File already exists and is not a directory - Files.delete(target) - Files.createDirectories(target) - } - } else { - target.parent?.let { Files.createDirectories(it) } - Files.copy(this, target, *options) - } - - return target + return Files.copy(this, target, *options) } /** diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 82a1ec089b4..6540f435ff7 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -40,7 +40,7 @@ class PathExtensionsTest { val dstFile = Files.createTempFile(null, null) try { srcFile.writeText("Hello, World!") - assertFailsWith(FileAlreadyExistsException::class, "copy do not overwrite existing file") { + assertFailsWith("copy do not overwrite existing file") { srcFile.copyTo(dstFile) } @@ -48,15 +48,24 @@ class PathExtensionsTest { assertSame(dst, dstFile) compareFiles(srcFile, dst, "copy with overwrite over existing file") + srcFile.copyTo(srcFile) + srcFile.copyTo(srcFile, overwrite = true) + compareFiles(dst, srcFile, "copying file to itself leaves it intact") + assertTrue(Files.deleteIfExists(dstFile)) dst = srcFile.copyTo(dstFile) compareFiles(srcFile, dst, "copy to new file") + val subDst = dstFile.resolve("foo/bar") + assertFailsWith { srcFile.copyTo(subDst) } + assertFailsWith { srcFile.copyTo(subDst, overwrite = true) } assertTrue(Files.deleteIfExists(dstFile)) + assertFailsWith { srcFile.copyTo(subDst) } + Files.createDirectory(dstFile) val child = dstFile.resolve("child") Files.createFile(child) - assertFailsWith(DirectoryNotEmptyException::class, "copy with overwrite do not overwrite non-empty dir") { + assertFailsWith( "copy with overwrite do not overwrite non-empty dir") { srcFile.copyTo(dstFile, overwrite = true) } Files.delete(child) @@ -67,21 +76,21 @@ class PathExtensionsTest { assertTrue(Files.deleteIfExists(srcFile)) assertTrue(Files.deleteIfExists(dstFile)) - assertFailsWith(NoSuchFileException::class) { + assertFailsWith { srcFile.copyTo(dstFile) } Files.createDirectory(srcFile) srcFile.resolve("somefile").writeText("some content") dstFile.writeText("") - assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite file") { + assertFailsWith("copy dir do not overwrite file") { srcFile.copyTo(dstFile) } srcFile.copyTo(dstFile, overwrite = true) assertTrue(dstFile.isDirectory()) assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") - assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite dir") { + assertFailsWith("copy dir do not overwrite dir") { srcFile.copyTo(dstFile) } @@ -90,7 +99,7 @@ class PathExtensionsTest { assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") dstFile.resolve("somefile2").writeText("some content2") - assertFailsWith(FileAlreadyExistsException::class, "copy dir do not overwrite non-empty dir") { + assertFailsWith("copy dir do not overwrite non-empty dir") { srcFile.copyTo(dstFile, overwrite = true) } } finally { From 997cd35e06a816ac0f3b3c67445d0b2dcda3fbd7 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Mon, 12 Oct 2020 06:04:55 +0300 Subject: [PATCH 024/554] Move Path extensions to the new package kotlin.io.path This avoids the conflict with the existing top-level functions in kotlin.io package. #KT-19192 --- libraries/stdlib/jdk7/java9/module-info.java | 2 +- .../stdlib/jdk7/src/kotlin/io/{ => path}/PathReadWrite.kt | 3 +-- libraries/stdlib/jdk7/src/kotlin/io/{ => path}/PathUtils.kt | 3 +-- libraries/stdlib/jdk7/test/PathExtensionsTest.kt | 1 + libraries/stdlib/jdk7/test/PathReadWriteTest.kt | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) rename libraries/stdlib/jdk7/src/kotlin/io/{ => path}/PathReadWrite.kt (99%) rename libraries/stdlib/jdk7/src/kotlin/io/{ => path}/PathUtils.kt (99%) diff --git a/libraries/stdlib/jdk7/java9/module-info.java b/libraries/stdlib/jdk7/java9/module-info.java index 103cb93e9d9..1741813c0c6 100644 --- a/libraries/stdlib/jdk7/java9/module-info.java +++ b/libraries/stdlib/jdk7/java9/module-info.java @@ -3,7 +3,7 @@ module kotlin.stdlib.jdk7 { requires transitive kotlin.stdlib; exports kotlin.jdk7; - exports kotlin.io.jdk7; + exports kotlin.io.path; exports kotlin.internal.jdk7 to kotlin.stdlib.jdk8; opens kotlin.internal.jdk7 to kotlin.stdlib; diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt similarity index 99% rename from libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt rename to libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt index ebd950dd38a..010d53cb01e 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/PathReadWrite.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt @@ -6,9 +6,8 @@ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "RedundantVisibilityModifier", "RedundantUnitReturnType", "SameParameterValue") @file:JvmMultifileClass @file:JvmName("PathsKt") -@file:kotlin.jvm.JvmPackageName("kotlin.io.jdk7") -package kotlin.io +package kotlin.io.path import java.io.* import java.nio.charset.Charset diff --git a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt similarity index 99% rename from libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt rename to libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt index bfb666a8bdf..8556f3fdc41 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt @@ -6,9 +6,8 @@ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "RedundantVisibilityModifier") @file:JvmMultifileClass @file:JvmName("PathsKt") -@file:kotlin.jvm.JvmPackageName("kotlin.io.jdk7") -package kotlin.io +package kotlin.io.path import java.io.IOException import java.nio.file.* diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 6540f435ff7..254860b1132 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -7,6 +7,7 @@ package kotlin.jdk7.test import java.io.IOException import java.nio.file.* +import kotlin.io.path.* import kotlin.test.* class PathExtensionsTest { diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt index bbfa8406486..042f6e16054 100644 --- a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt @@ -7,7 +7,7 @@ package kotlin.jdk7.test import java.nio.file.Files import java.nio.file.StandardOpenOption -import java.util.* +import kotlin.io.path.* import kotlin.test.* class PathReadWriteTest { From 9f659d74df6a03a64a3f15182d54482b4fa10ed1 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 15 Oct 2020 02:23:02 +0300 Subject: [PATCH 025/554] Introduce dedicated experimental annotation for Path extensions #KT-19192 --- libraries/stdlib/jdk7/build.gradle | 2 + .../src/kotlin/io/path/ExperimentalPathApi.kt | 37 ++++++++++++++++ .../jdk7/src/kotlin/io/path/PathReadWrite.kt | 32 +++++++------- .../jdk7/src/kotlin/io/path/PathUtils.kt | 42 +++++++++---------- libraries/stdlib/jdk8/build.gradle | 1 + 5 files changed, 77 insertions(+), 37 deletions(-) create mode 100644 libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt diff --git a/libraries/stdlib/jdk7/build.gradle b/libraries/stdlib/jdk7/build.gradle index 24b83374380..95f7960d19a 100644 --- a/libraries/stdlib/jdk7/build.gradle +++ b/libraries/stdlib/jdk7/build.gradle @@ -77,6 +77,7 @@ compileKotlin { "-Xmultifile-parts-inherit", "-Xnormalize-constructor-calls=enable", "-module-name", project.name, + "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.contracts.ExperimentalContracts", ] } @@ -88,6 +89,7 @@ compileTestKotlin { "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.ExperimentalUnsignedTypes", "-Xopt-in=kotlin.ExperimentalStdlibApi", + "-Xopt-in=kotlin.io.path.ExperimentalPathApi", ] } diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt new file mode 100644 index 00000000000..67f8f646f28 --- /dev/null +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.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 kotlin.io.path + +import kotlin.annotation.AnnotationTarget.* + +/** + * This annotation marks the extensions and top-level functions for working with [java.nio.file.Path] considered experimental. + * + * > Beware using the annotated API especially if you're developing a library, since your library might become binary incompatible + * with the future versions of the standard library. + * + * Any usage of a declaration annotated with `@ExperimentalPathAPI` must be accepted either by + * annotating that usage with the [OptIn] annotation, e.g. `@OptIn(ExperimentalPathAPI::class)`, + * or by using the compiler argument `-Xopt-in=kotlin.io.path.ExperimentalPathAPI`. + */ +@RequiresOptIn(level = RequiresOptIn.Level.ERROR) +@Retention(AnnotationRetention.BINARY) +@Target( + CLASS, + ANNOTATION_CLASS, + PROPERTY, + FIELD, + LOCAL_VARIABLE, + VALUE_PARAMETER, + CONSTRUCTOR, + FUNCTION, + PROPERTY_GETTER, + PROPERTY_SETTER, + TYPEALIAS +) +@MustBeDocumented +@SinceKotlin("1.3") +public annotation class ExperimentalPathApi diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt index 010d53cb01e..a7781153e8f 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt @@ -20,7 +20,7 @@ import java.nio.file.StandardOpenOption * Returns a new [InputStreamReader] for reading the content of this file. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): InputStreamReader { return inputStream(*options).reader(charset) @@ -34,7 +34,7 @@ public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: * @param options options to determine how the file is opened */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.bufferedReader( charset: Charset = Charsets.UTF_8, @@ -48,7 +48,7 @@ public inline fun Path.bufferedReader( * Returns a new [OutputStreamWriter] for writing the content of this file. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): OutputStreamWriter { return outputStream(*options).writer(charset) @@ -62,7 +62,7 @@ public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.bufferedWriter( charset: Charset = Charsets.UTF_8, @@ -76,7 +76,7 @@ public inline fun Path.bufferedWriter( * Returns a new [PrintWriter] for writing the content of this file. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.printWriter(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): PrintWriter { return PrintWriter(bufferedWriter(charset, options = options)) @@ -90,7 +90,7 @@ public inline fun Path.printWriter(charset: Charset = Charsets.UTF_8, vararg opt * @return the entire content of this file as a byte array. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.readBytes(): ByteArray { return Files.readAllBytes(this) @@ -106,7 +106,7 @@ public inline fun Path.readBytes(): ByteArray { * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.writeBytes(array: ByteArray, vararg options: OpenOption): Unit { Files.write(this, array, *options) @@ -118,7 +118,7 @@ public inline fun Path.writeBytes(array: ByteArray, vararg options: OpenOption): * @param array byte array to append to this file. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.appendBytes(array: ByteArray): Unit { writeBytes(array, StandardOpenOption.APPEND) @@ -133,7 +133,7 @@ public inline fun Path.appendBytes(array: ByteArray): Unit { * @return the entire content of this file as a String. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset) /** @@ -146,7 +146,7 @@ public fun Path.readText(charset: Charset = Charsets.UTF_8): String = readBytes( * @param charset character set to use. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Unit { writeBytes(text.toByteArray(charset), *options) } @@ -158,7 +158,7 @@ public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, varar * @param charset character set to use. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit { writeText(text, charset, StandardOpenOption.APPEND) } @@ -174,7 +174,7 @@ public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Uni * @param action function to process file lines. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, vararg options: OpenOption, action: (line: String) -> Unit): Unit { // Note: close is called at forEachLine bufferedReader(charset, options = options).forEachLine(action) @@ -187,7 +187,7 @@ public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, vararg options: O * equivalent to opening the file with the [READ][StandardOpenOption.READ] option. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.inputStream(vararg options: OpenOption): InputStream { return Files.newInputStream(this, *options) @@ -202,7 +202,7 @@ public inline fun Path.inputStream(vararg options: OpenOption): InputStream { * options. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.outputStream(vararg options: OpenOption): OutputStream { return Files.newOutputStream(this, *options) @@ -217,7 +217,7 @@ public inline fun Path.outputStream(vararg options: OpenOption): OutputStream { * @return list of file lines. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List { return Files.readAllLines(this, charset) @@ -231,7 +231,7 @@ public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence) -> T): T { return bufferedReader(charset).use { block(it.lineSequence()) } diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt index 8556f3fdc41..b28bc0fb580 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt @@ -18,7 +18,7 @@ import java.nio.file.NoSuchFileException * Returns the extension of this path (not including the dot), or an empty string if it doesn't have one. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public val Path.extension: String get() = fileName?.toString()?.substringAfterLast('.', "") ?: "" @@ -27,7 +27,7 @@ public val Path.extension: String * separate the names in the name sequence. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public val Path.invariantSeparatorsPath: String get() { val separator = fileSystem.separator @@ -39,7 +39,7 @@ public val Path.invariantSeparatorsPath: String * this path has zero elements. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public val Path.nameWithoutExtension: String get() = fileName?.toString()?.substringBeforeLast(".") ?: "" @@ -53,7 +53,7 @@ public val Path.nameWithoutExtension: String * @throws IllegalArgumentException if this and base paths have different roots. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.relativeTo(base: Path): Path = try { PathRelativizer.tryRelativeTo(this, base) } catch (e: IllegalArgumentException) { @@ -68,7 +68,7 @@ public fun Path.relativeTo(base: Path): Path = try { * @return Path with relative path from [base] to this, or `this` if this and base paths have different roots. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.relativeToOrSelf(base: Path): Path = relativeToOrNull(base) ?: this @@ -80,7 +80,7 @@ public fun Path.relativeToOrSelf(base: Path): Path = * @return Path with relative path from [base] to this, or `null` if this and base paths have different roots. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.relativeToOrNull(base: Path): Path? = try { PathRelativizer.tryRelativeTo(this, base) } catch (e: IllegalArgumentException) { @@ -143,7 +143,7 @@ internal object PathRelativizer { * @throws IOException if any errors occur while copying. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { val options = if (overwrite) arrayOf(StandardCopyOption.REPLACE_EXISTING) else emptyArray() return copyTo(target, *options) @@ -179,7 +179,7 @@ public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { * @throws IOException if any errors occur while copying. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { return Files.copy(this, target, *options) } @@ -190,7 +190,7 @@ public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { * @param options Options to control how symbolic links are handled. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options) @@ -200,7 +200,7 @@ public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exist * @param options Options to control how symbolic links are handled. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.notExists(this, *options) @@ -210,7 +210,7 @@ public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.no * @param options Options to control how symbolic links are handled. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options) @@ -222,7 +222,7 @@ public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = File * @param options Options to control how symbolic links are handled. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(this, *options) @@ -230,7 +230,7 @@ public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files. * Check if this path exists and is a symbolic link. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this) @@ -238,7 +238,7 @@ public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this) * Check if this path exists and is executable. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this) @@ -249,7 +249,7 @@ public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this) * path is considered hidden if its name begins with a dot. On Windows, file attributes are checked. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isHidden(): Boolean = Files.isHidden(this) @@ -257,7 +257,7 @@ public inline fun Path.isHidden(): Boolean = Files.isHidden(this) * Check if this path exists and is readable. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isReadable(): Boolean = Files.isReadable(this) @@ -265,7 +265,7 @@ public inline fun Path.isReadable(): Boolean = Files.isReadable(this) * Check that this path exists and is writable. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isWritable(): Boolean = Files.isWritable(this) @@ -273,7 +273,7 @@ public inline fun Path.isWritable(): Boolean = Files.isWritable(this) * Check if this path points to the same file or directory as [other]. */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, other) @@ -284,7 +284,7 @@ public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, * @throws IOException If an I/O error occurs */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.listDirectoryEntries(): List { return Files.newDirectoryStream(this).use { it.toList() } } @@ -297,7 +297,7 @@ public fun Path.listDirectoryEntries(): List { * @return the value returned by [block] */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.useDirectoryEntries(block: (Sequence) -> T): T { return Files.newDirectoryStream(this).use { block(it.asSequence()) } } @@ -309,7 +309,7 @@ public fun Path.useDirectoryEntries(block: (Sequence) -> T): T { * @throws IOException If an I/O error occurs */ @SinceKotlin("1.4") -@ExperimentalStdlibApi +@ExperimentalPathApi public fun Path.forEachDirectoryEntry(action: (Path) -> Unit) { return Files.newDirectoryStream(this).use { it.forEach(action) } } diff --git a/libraries/stdlib/jdk8/build.gradle b/libraries/stdlib/jdk8/build.gradle index f5d7b28e859..12149e33a69 100644 --- a/libraries/stdlib/jdk8/build.gradle +++ b/libraries/stdlib/jdk8/build.gradle @@ -81,6 +81,7 @@ compileTestKotlin { "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.ExperimentalUnsignedTypes", "-Xopt-in=kotlin.ExperimentalStdlibApi", + "-Xopt-in=kotlin.io.path.ExperimentalPathApi", ] } From e7c888a2e6b37abb81d645a5bcd29ab44c037720 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Mon, 19 Oct 2020 06:52:13 +0300 Subject: [PATCH 026/554] Avoid introducing Path.printWriter #KT-19192 --- .../jdk7/src/kotlin/io/path/PathReadWrite.kt | 10 ------- .../stdlib/jdk7/test/PathReadWriteTest.kt | 29 ------------------- 2 files changed, 39 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt index a7781153e8f..352b3b311f6 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt @@ -72,16 +72,6 @@ public inline fun Path.bufferedWriter( return writer(charset, *options).buffered(bufferSize) } -/** - * Returns a new [PrintWriter] for writing the content of this file. - */ -@SinceKotlin("1.4") -@ExperimentalPathApi -@kotlin.internal.InlineOnly -public inline fun Path.printWriter(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): PrintWriter { - return PrintWriter(bufferedWriter(charset, options = options)) -} - /** * Gets the entire content of this file as a byte array. * diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt index 042f6e16054..87c6a91923f 100644 --- a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt @@ -91,35 +91,6 @@ class PathReadWriteTest { assertEquals(Files.readAllLines(file, Charsets.UTF_8), listOf("line1", "line2")) } - @Test - fun testPrintWriter() { - val file = Files.createTempFile(null, null) - - val writer = file.printWriter() - val str1 = "Hello, world!" - val str2 = "Everything is wonderful!" - writer.println(str1) - writer.println(str2) - writer.close() - - val writer2 = file.printWriter(options = arrayOf(StandardOpenOption.APPEND)) - val str3 = "Hello again!" - writer2.println(str3) - writer2.close() - - val writer3 = file.printWriter(Charsets.UTF_8, StandardOpenOption.APPEND) - val str4 = "Hello one last time!" - writer3.println(str4) - writer3.close() - - file.bufferedReader().use { reader -> - assertEquals(str1, reader.readLine()) - assertEquals(str2, reader.readLine()) - assertEquals(str3, reader.readLine()) - assertEquals(str4, reader.readLine()) - } - } - @Test fun testWriteBytes() { val file = Files.createTempFile(null, null) From 038f1cbd1e5cce00cbf11da64f6192e112f69eae Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 16 Oct 2020 21:36:38 +0300 Subject: [PATCH 027/554] Add glob filtering when listing directory entries #KT-19192 --- .../jdk7/src/kotlin/io/path/PathUtils.kt | 34 ++++++++++++++----- .../stdlib/jdk7/test/PathExtensionsTest.kt | 21 +++++++----- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt index b28bc0fb580..c637f43bbab 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt @@ -278,38 +278,54 @@ public inline fun Path.isWritable(): Boolean = Files.isWritable(this) public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, other) /** - * Return a list of the entries in this directory. + * Return a list of the entries in this directory optionally filtered by matching against the specified [glob] pattern. * + * @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method. + * + * @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid. * @throws NotDirectoryException If this path does not refer to a directory * @throws IOException If an I/O error occurs + * + * @see Files.newDirectoryStream */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.listDirectoryEntries(): List { - return Files.newDirectoryStream(this).use { it.toList() } +public fun Path.listDirectoryEntries(glob: String = "*"): List { + return Files.newDirectoryStream(this, glob).use { it.toList() } } /** - * Call the [block] callback with a sequence of all entries in this directory. + * Call the [block] callback with a sequence of all entries in this directory + * optionally filtered by matching against the specified [glob] pattern. * + * @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method. + * + * @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid. * @throws NotDirectoryException If this path does not refer to a directory * @throws IOException If an I/O error occurs * @return the value returned by [block] + * + * @see Files.newDirectoryStream */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.useDirectoryEntries(block: (Sequence) -> T): T { - return Files.newDirectoryStream(this).use { block(it.asSequence()) } +public fun Path.useDirectoryEntries(glob: String = "*", block: (Sequence) -> T): T { + return Files.newDirectoryStream(this, glob).use { block(it.asSequence()) } } /** - * Perform the given [action] on each entry in this directory. + * Perform the given [action] on each entry in this directory optionally filtered by matching against the specified [glob] pattern. * + * @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method. + * + * @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid. * @throws NotDirectoryException If this path does not refer to a directory * @throws IOException If an I/O error occurs + * + * @see Files.newDirectoryStream */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.forEachDirectoryEntry(action: (Path) -> Unit) { - return Files.newDirectoryStream(this).use { it.forEach(action) } +public fun Path.forEachDirectoryEntry(glob: String = "*", action: (Path) -> Unit) { + return Files.newDirectoryStream(this, glob).use { it.forEach(action) } } diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 254860b1132..582a928079c 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -201,6 +201,9 @@ class PathExtensionsTest { Files.createFile(file) assertEquals(listOf(file), dir.listDirectoryEntries()) + val fileTxt = createTempFile(dir, suffix = ".txt") + assertEquals(listOf(fileTxt), dir.listDirectoryEntries("*.txt")) + assertFailsWith { file.listDirectoryEntries() } } @@ -213,23 +216,25 @@ class PathExtensionsTest { Files.createFile(file) assertEquals(listOf(file), dir.useDirectoryEntries { it.toList() }) - assertFailsWith { file.useDirectoryEntries { it.toList() } } + val fileTxt = createTempFile(dir, suffix = ".txt") + assertEquals(listOf(fileTxt), dir.useDirectoryEntries("*.txt") { it.toList() }) + + assertFailsWith { file.useDirectoryEntries { error("shouldn't get here") } } } @Test fun testForEachDirectoryEntry() { val dir = Files.createTempDirectory(null) - val entries = mutableListOf() - - dir.forEachDirectoryEntry { entries.add(it) } - assertTrue(entries.isEmpty()) + dir.forEachDirectoryEntry { error("shouldn't get here, but received $it") } val file = dir.resolve("f1") Files.createFile(file) - dir.forEachDirectoryEntry { entries.add(it) } - assertEquals(listOf(file), entries) + dir.forEachDirectoryEntry { assertEquals(file, it) } - assertFailsWith { file.forEachDirectoryEntry { } } + val fileTxt = createTempFile(dir, suffix = ".txt") + dir.forEachDirectoryEntry("*.txt") { assertEquals(fileTxt, it) } + + assertFailsWith { file.forEachDirectoryEntry { error("shouldn't get here, but received $it") } } } From a43cc0d1f9f340102db0c6f9514ddb73f5ccd56c Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 9 Oct 2020 02:14:45 +0300 Subject: [PATCH 028/554] Implement additional Path extensions #KT-19192 --- .../jdk7/src/kotlin/io/path/PathReadWrite.kt | 95 ++- .../jdk7/src/kotlin/io/path/PathUtils.kt | 673 ++++++++++++++++-- .../stdlib/jdk7/test/PathExtensionsTest.kt | 355 +++++++-- .../stdlib/jdk7/test/PathReadWriteTest.kt | 52 +- .../kotlin-stdlib-jdk7.txt | 20 + 5 files changed, 1044 insertions(+), 151 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt index 352b3b311f6..6022e323ef8 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt @@ -18,6 +18,9 @@ import java.nio.file.StandardOpenOption /** * Returns a new [InputStreamReader] for reading the content of this file. + * + * @param charset character set to use for reading text, UTF-8 by default. + * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -29,9 +32,9 @@ public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: /** * Returns a new [BufferedReader] for reading the content of this file. * - * @param charset character set to use. + * @param charset character set to use for reading text, UTF-8 by default. * @param bufferSize necessary size of the buffer. - * @param options options to determine how the file is opened + * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -46,6 +49,9 @@ public inline fun Path.bufferedReader( /** * Returns a new [OutputStreamWriter] for writing the content of this file. + * + * @param charset character set to use for writing text, UTF-8 by default. + * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -57,7 +63,7 @@ public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: /** * Returns a new [BufferedWriter] for writing the content of this file. * - * @param charset character set to use. + * @param charset character set to use for writing text, UTF-8 by default. * @param bufferSize necessary size of the buffer. * @param options options to determine how the file is opened. */ @@ -87,7 +93,7 @@ public inline fun Path.readBytes(): ByteArray { } /** - * Write an [array] of bytes to this file. + * Writes an [array] of bytes to this file. * * By default, the file will be overwritten if it already exists, but you can control this behavior * with [options]. @@ -110,30 +116,33 @@ public inline fun Path.writeBytes(array: ByteArray, vararg options: OpenOption): @SinceKotlin("1.4") @ExperimentalPathApi @kotlin.internal.InlineOnly -public inline fun Path.appendBytes(array: ByteArray): Unit { - writeBytes(array, StandardOpenOption.APPEND) +public inline fun Path.appendBytes(array: ByteArray) { + Files.write(this, array, StandardOpenOption.APPEND) } /** - * Gets the entire content of this file as a String using UTF-8 or specified [charset]. + * Gets the entire content of this file as a String using UTF-8 or the specified [charset]. * * This method is not recommended on huge files. It has an internal limitation of 2 GB file size. * - * @param charset character set to use. + * @param charset character set to use for reading text, UTF-8 by default. * @return the entire content of this file as a String. */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset) +@kotlin.internal.InlineOnly +public inline fun Path.readText(charset: Charset = Charsets.UTF_8): String = + readBytes().toString(charset) /** - * Sets the content of this file as [text] encoded using UTF-8 or specified [charset]. + * Sets the content of this file as [text] encoded using UTF-8 or the specified [charset]. * * By default, the file will be overwritten if it already exists, but you can control this behavior * with [options]. * * @param text text to write into file. - * @param charset character set to use. + * @param charset character set to use for writing text, UTF-8 by default. + * @param options options to determine how the file is opened. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -145,7 +154,7 @@ public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, varar * Appends [text] to the content of this file using UTF-8 or the specified [charset]. * * @param text text to append to file. - * @param charset character set to use. + * @param charset character set to use for writing text, UTF-8 by default. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -160,7 +169,7 @@ public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Uni * You may use this function on huge files. * * @param options options to determine how the file is opened. - * @param charset character set to use. + * @param charset character set to use for reading text, UTF-8 by default. * @param action function to process file lines. */ @SinceKotlin("1.4") @@ -203,7 +212,7 @@ public inline fun Path.outputStream(vararg options: OpenOption): OutputStream { * * Do not use this function for huge files. * - * @param charset character set to use. By default uses UTF-8 charset. + * @param charset character set to use for reading text, UTF-8 by default. * @return list of file lines. */ @SinceKotlin("1.4") @@ -217,7 +226,7 @@ public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence) -> T): T { return bufferedReader(charset).use { block(it.lineSequence()) } } + +/** + * Write the specified collection of char sequences [lines] to a file terminating each one with the platform's line separator. + * + * By default, the file will be overwritten if it already exists, but you can control this behavior + * with [options]. + * + * @param charset character set to use for writing text, UTF-8 by default. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.writeLines(lines: Iterable, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Path { + return Files.write(this, lines, charset, *options) +} + +/** + * Write the specified sequence of char sequences [lines] to a file terminating each one with the platform's line separator. + * + * By default, the file will be overwritten if it already exists, but you can control this behavior + * with [options]. + * + * @param charset character set to use for writing text, UTF-8 by default. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.writeLines(lines: Sequence, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Path { + return Files.write(this, lines.asIterable(), charset, *options) +} + +/** + * Appends the specified collection of char sequences [lines] to a file terminating each one with the platform's line separator. + * + * @param charset character set to use for writing text, UTF-8 by default. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.appendLines(lines: Iterable, charset: Charset = Charsets.UTF_8): Path { + return Files.write(this, lines, charset, StandardOpenOption.APPEND) +} + +/** + * Appends the specified sequence of char sequences [lines] to a file terminating each one with the platform's line separator. + * + * @param charset character set to use for writing text, UTF-8 by default. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.appendLines(lines: Sequence, charset: Charset = Charsets.UTF_8): Path { + return Files.write(this, lines.asIterable(), charset, StandardOpenOption.APPEND) +} + + diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt index c637f43bbab..4316fb8ee1b 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathUtils.kt @@ -10,12 +10,33 @@ package kotlin.io.path import java.io.IOException +import java.net.URI import java.nio.file.* import java.nio.file.FileAlreadyExistsException import java.nio.file.NoSuchFileException +import java.nio.file.attribute.* /** - * Returns the extension of this path (not including the dot), or an empty string if it doesn't have one. + * Returns the name of the file or directory denoted by this path as a string, + * or an empty string if this path has zero path elements. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +public val Path.name: String + get() = fileName?.toString().orEmpty() + +/** + * Returns the [name][Path.name] of this file or directory without an extension, + * or an empty string if this path has zero path elements. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +public val Path.nameWithoutExtension: String + get() = fileName?.toString()?.substringBeforeLast(".") ?: "" + +/** + * Returns the extension of this path (not including the dot), + * or an empty string if it doesn't have one. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -34,21 +55,14 @@ public val Path.invariantSeparatorsPath: String return if (separator != "/") toString().replace(separator, "/") else toString() } -/** - * Returns this path's [fileName][Path.getFileName] without an extension, or an empty string if - * this path has zero elements. - */ -@SinceKotlin("1.4") -@ExperimentalPathApi -public val Path.nameWithoutExtension: String - get() = fileName?.toString()?.substringBeforeLast(".") ?: "" /** * Calculates the relative path for this path from a [base] path. + * * Note that the [base] path is treated as a directory. * If this path matches the [base] path, then a [Path] with an empty path will be returned. * - * @return Path with relative path from [base] to this. + * @return the relative path from [base] to this. * * @throws IllegalArgumentException if this and base paths have different roots. */ @@ -57,15 +71,16 @@ public val Path.nameWithoutExtension: String public fun Path.relativeTo(base: Path): Path = try { PathRelativizer.tryRelativeTo(this, base) } catch (e: IllegalArgumentException) { - throw java.lang.IllegalArgumentException(e.message + "\nthis path: $this\nbase path: $base", e) + throw IllegalArgumentException(e.message + "\nthis path: $this\nbase path: $base", e) } /** * Calculates the relative path for this path from a [base] path. + * * Note that the [base] path is treated as a directory. * If this path matches the [base] path, then a [Path] with an empty path will be returned. * - * @return Path with relative path from [base] to this, or `this` if this and base paths have different roots. + * @return the relative path from [base] to this, or `this` if this and base paths have different roots. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -74,10 +89,11 @@ public fun Path.relativeToOrSelf(base: Path): Path = /** * Calculates the relative path for this path from a [base] path. + * * Note that the [base] path is treated as a directory. * If this path matches the [base] path, then a [Path] with an empty path will be returned. * - * @return Path with relative path from [base] to this, or `null` if this and base paths have different roots. + * @return the relative path from [base] to this, or `null` if this and base paths have different roots. */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -87,7 +103,7 @@ public fun Path.relativeToOrNull(base: Path): Path? = try { null } -internal object PathRelativizer { +private object PathRelativizer { private val emptyPath = Paths.get("") private val parentPath = Paths.get("..") @@ -117,9 +133,9 @@ internal object PathRelativizer { } /** - * Copies this path to the given [target] path. + * Copies a file or directory located by this path to the given [target] path. * - * Unlike `File.copyTo`, if some directories on a way to the [target] are missing, then they won't be created automatically. + * Unlike `File.copyTo`, if some directories on the way to the [target] are missing, then they won't be created automatically. * You can use the following approach to ensure that required intermediate directories are created: * ``` * sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() }) @@ -141,18 +157,21 @@ internal object PathRelativizer { * @throws DirectoryNotEmptyException if the destination path point to an existing directory and [overwrite] argument is `true`, * when the directory being replaced is not empty. * @throws IOException if any errors occur while copying. + * + * @see Files.copy */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { - val options = if (overwrite) arrayOf(StandardCopyOption.REPLACE_EXISTING) else emptyArray() - return copyTo(target, *options) +@kotlin.internal.InlineOnly +public inline fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { + val options = if (overwrite) arrayOf(StandardCopyOption.REPLACE_EXISTING) else emptyArray() + return Files.copy(this, target, *options) } /** - * Copies this path to the given [target] path. + * Copies a file or directory located by this path to the given [target] path. * - * Unlike `File.copyTo`, if some directories on a way to the [target] are missing, then they won't be created automatically. + * Unlike `File.copyTo`, if some directories on the way to the [target] are missing, then they won't be created automatically. * You can use the following approach to ensure that required intermediate directories are created: * ``` * sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() }) @@ -177,17 +196,25 @@ public fun Path.copyTo(target: Path, overwrite: Boolean = false): Path { * @throws DirectoryNotEmptyException if the destination path point to an existing directory and [REPLACE_EXISTING][StandardCopyOption.REPLACE_EXISTING] is used, * when the directory being replaced is not empty. * @throws IOException if any errors occur while copying. + * + * @see Files.copy */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { +@kotlin.internal.InlineOnly +public inline fun Path.copyTo(target: Path, vararg options: CopyOption): Path { return Files.copy(this, target, *options) } /** - * Check if this path exists. + * Checks if the file located by this path exists. * - * @param options Options to control how symbolic links are handled. + * @return `true`, if the file definitely exists, `false` otherwise, + * including situations when the existence cannot be determined. + * + * @param options options to control how symbolic links are handled. + * + * @see Files.exists */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -195,9 +222,14 @@ public fun Path.copyTo(target: Path, vararg options: CopyOption): Path { public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options) /** - * Check if this path does not exist. + * Checks if the file located by this path does not exist. * - * @param options Options to control how symbolic links are handled. + * @return `true`, if the file definitely does not exist, `false` otherwise, + * including situations when the existence cannot be determined. + * + * @param options options to control how symbolic links are handled. + * + * @see Files.notExists */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -205,9 +237,11 @@ public inline fun Path.exists(vararg options: LinkOption): Boolean = Files.exist public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.notExists(this, *options) /** - * Check if this path is a file. + * Checks if the file located by this path is a regular file. * - * @param options Options to control how symbolic links are handled. + * @param options options to control how symbolic links are handled. + * + * @see Files.isRegularFile */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -215,11 +249,13 @@ public inline fun Path.notExists(vararg options: LinkOption): Boolean = Files.no public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options) /** - * Check if this path is a directory. + * Checks if the file located by this path is a directory. * * By default, symbolic links in the path are followed. * - * @param options Options to control how symbolic links are handled. + * @param options options to control how symbolic links are handled. + * + * @see Files.isDirectory */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -227,7 +263,9 @@ public inline fun Path.isRegularFile(vararg options: LinkOption): Boolean = File public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(this, *options) /** - * Check if this path exists and is a symbolic link. + * Checks if the file located by this path exists and is a symbolic link. + * + * @see Files.isSymbolicLink */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -235,7 +273,9 @@ public inline fun Path.isDirectory(vararg options: LinkOption): Boolean = Files. public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this) /** - * Check if this path exists and is executable. + * Checks if the file located by this path exists and is executable. + * + * @see Files.isExecutable */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -243,10 +283,12 @@ public inline fun Path.isSymbolicLink(): Boolean = Files.isSymbolicLink(this) public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this) /** - * Check if this path is considered hidden. + * Checks if the file located by this path is considered hidden. * * This check is dependant on the current filesystem. For example, on UNIX-like operating systems, a * path is considered hidden if its name begins with a dot. On Windows, file attributes are checked. + * + * @see Files.isHidden */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -254,7 +296,9 @@ public inline fun Path.isExecutable(): Boolean = Files.isExecutable(this) public inline fun Path.isHidden(): Boolean = Files.isHidden(this) /** - * Check if this path exists and is readable. + * Checks if the file located by this path exists and is readable. + * + * @see Files.isReadable */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -262,7 +306,9 @@ public inline fun Path.isHidden(): Boolean = Files.isHidden(this) public inline fun Path.isReadable(): Boolean = Files.isReadable(this) /** - * Check that this path exists and is writable. + * Checks if the file located by this path exists and is writable. + * + * @see Files.isWritable */ @SinceKotlin("1.4") @ExperimentalPathApi @@ -270,21 +316,23 @@ public inline fun Path.isReadable(): Boolean = Files.isReadable(this) public inline fun Path.isWritable(): Boolean = Files.isWritable(this) /** - * Check if this path points to the same file or directory as [other]. + * Checks if the file located by this path points to the same file or directory as [other]. + * + * @see Files.isSameFile */ @SinceKotlin("1.4") @ExperimentalPathApi @kotlin.internal.InlineOnly -public inline fun Path.isSameFile(other: Path): Boolean = Files.isSameFile(this, other) +public inline fun Path.isSameFileAs(other: Path): Boolean = Files.isSameFile(this, other) /** - * Return a list of the entries in this directory optionally filtered by matching against the specified [glob] pattern. + * Returns a list of the entries in this directory optionally filtered by matching against the specified [glob] pattern. * * @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method. * * @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid. - * @throws NotDirectoryException If this path does not refer to a directory - * @throws IOException If an I/O error occurs + * @throws NotDirectoryException If this path does not refer to a directory. + * @throws IOException If an I/O error occurs. * * @see Files.newDirectoryStream */ @@ -295,37 +343,564 @@ public fun Path.listDirectoryEntries(glob: String = "*"): List { } /** - * Call the [block] callback with a sequence of all entries in this directory + * Calls the [block] callback with a sequence of all entries in this directory * optionally filtered by matching against the specified [glob] pattern. * * @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method. * * @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid. - * @throws NotDirectoryException If this path does not refer to a directory - * @throws IOException If an I/O error occurs - * @return the value returned by [block] + * @throws NotDirectoryException If this path does not refer to a directory. + * @throws IOException If an I/O error occurs. + * @return the value returned by [block]. * * @see Files.newDirectoryStream */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.useDirectoryEntries(glob: String = "*", block: (Sequence) -> T): T { +@kotlin.internal.InlineOnly +public inline fun Path.useDirectoryEntries(glob: String = "*", block: (Sequence) -> T): T { return Files.newDirectoryStream(this, glob).use { block(it.asSequence()) } } /** - * Perform the given [action] on each entry in this directory optionally filtered by matching against the specified [glob] pattern. + * Performs the given [action] on each entry in this directory optionally filtered by matching against the specified [glob] pattern. * * @param glob the globbing pattern. The syntax is specified by the [FileSystem.getPathMatcher] method. * * @throws java.util.regex.PatternSyntaxException if the glob pattern is invalid. - * @throws NotDirectoryException If this path does not refer to a directory - * @throws IOException If an I/O error occurs + * @throws NotDirectoryException If this path does not refer to a directory. + * @throws IOException If an I/O error occurs. * * @see Files.newDirectoryStream */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.forEachDirectoryEntry(glob: String = "*", action: (Path) -> Unit) { +@kotlin.internal.InlineOnly +public inline fun Path.forEachDirectoryEntry(glob: String = "*", action: (Path) -> Unit) { return Files.newDirectoryStream(this, glob).use { it.forEach(action) } } + +/** + * Returns the size of a regular file as a [Long] value of bytes or throws an exception if the file doesn't exist. + * + * @throws IOException if an I/O error occurred. + * @see Files.size + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.fileSize(): Long = + Files.size(this) + +/** + * Deletes the existing file or empty directory specified by this path. + * + * @throws NoSuchFileException if the file or directory does not exist. + * @throws DirectoryNotEmptyException if the directory exists but is not empty. + * + * @see Files.delete + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.deleteExisting() { + Files.delete(this) +} + +/** + * Deletes the file or empty directory specified by this path if it exists. + * + * @return `true` if the existing file was successfully deleted, `false` if the file does not exist. + * + * @throws DirectoryNotEmptyException if the directory exists but is not empty + * + * @see Files.deleteIfExists + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.deleteIfExists() = + Files.deleteIfExists(this) + +/** + * Creates a new directory or throws an exception if there is already a file or directory located by this path. + * + * Note that the parent directory where this directory is going to be created must already exist. + * If you need to create all non-existent parent directories, use [Path.createDirectories]. + * + * @param attributes an optional list of file attributes to set atomically when creating the directory. + * + * @throws FileAlreadyExistsException if there is already a file or directory located by this path + * (optional specific exception, some implementations may throw more general [IOException]). + * @throws IOException if an I/O error occurs or the parent directory does not exist. + * @throws UnsupportedOperationException if the [attributes ]array contains an attribute that cannot be set atomically + * when creating the directory. + * + * @see Files.createDirectory + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.createDirectory(vararg attributes: FileAttribute<*>): Path = + Files.createDirectory(this, *attributes) + +/** + * Creates a directory ensuring that all nonexistent parent directories exist by creating them first. + * + * If the directory already exists, this function does not throw an exception, unlike [Path.createDirectory]. + * + * @param attributes an optional list of file attributes to set atomically when creating the directory. + * + * @throws FileAlreadyExistsException if there is already a file located by this path + * (optional specific exception, some implementations may throw more general [IOException]). + * @throws IOException if an I/O error occurs. + * @throws UnsupportedOperationException if the [attributes ]array contains an attribute that cannot be set atomically + * when creating the directory. + * + * @see Files.createDirectories + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.createDirectories(vararg attributes: FileAttribute<*>): Path = + Files.createDirectories(this, *attributes) + + +/** + * Moves or renames the file located by this path to the [target] path. + * + * @param options options specifying how the move should be done, see [StandardCopyOption], [LinkOption]. + * + * @throws FileAlreadyExistsException if the target file exists but cannot be replaced because the + * [StandardCopyOption.REPLACE_EXISTING] option is not specified (optional specific exception). + * @throws DirectoryNotEmptyException the [StandardCopyOption.REPLACE_EXISTING] option is specified but the file + * cannot be replaced because it is a non-empty directory, or the + * source is a non-empty directory containing entries that would + * be required to be moved (optional specific exception). + * + * @see Files.move + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.moveTo(target: Path, vararg options: CopyOption): Path = + Files.move(this, target, *options) + +/** + * Moves or renames the file located by this path to the [target] path. + * + * @param overwrite allows to overwrite the target if it already exists. + * + * @throws FileAlreadyExistsException if the target file exists but cannot be replaced because the + * `overwrite = true` option is not specified (optional specific exception). + * @throws DirectoryNotEmptyException the `overwrite = true` option is specified but the file + * cannot be replaced because it is a non-empty directory, or the + * source is a non-empty directory containing entries that would + * be required to be moved (optional specific exception). + * + * @see Files.move + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.moveTo(target: Path, overwrite: Boolean = false): Path { + val options = if (overwrite) arrayOf(StandardCopyOption.REPLACE_EXISTING) else emptyArray() + return Files.move(this, target, *options) +} + +/** + * Returns the [FileStore] representing the file store where a file is located. + * + * @see Files.getFileStore + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.fileStore(): FileStore = + Files.getFileStore(this) + +/** + * Reads the value of a file attribute. + * + * The attribute name is specified with the [attribute] parameter optionally prefixed with the attribute view name: + * ``` + * [view_name:]attribute_name + * ``` + * When the view name is not specified, it defaults to `basic`. + * + * @throws UnsupportedOperationException if the attribute view is not supported. + * @throws IllegalArgumentException if the attribute name is not specified or is not recognized. + * @see Files.getAttribute + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.getAttribute(attribute: String, vararg options: LinkOption): Any? = + Files.getAttribute(this, attribute, *options) + +/** + * Sets the value of a file attribute. + * + * The attribute name is specified with the [attribute] parameter optionally prefixed with the attribute view name: + * ``` + * [view_name:]attribute_name + * ``` + * When the view name is not specified, it defaults to `basic`. + * + * @throws UnsupportedOperationException if the attribute view is not supported. + * @throws IllegalArgumentException if the attribute name is not specified or is not recognized, or + * the attribute value is of the correct type but has an inappropriate value. + * @throws ClassCastException if the attribute value is not of the expected type + * @see Files.setAttribute + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.setAttribute(attribute: String, value: Any?, vararg options: LinkOption): Path = + Files.setAttribute(this, attribute, value, *options) + +/** + * Returns a file attributes view of a given type [V] + * or `null` if the requested attribute view type is not available. + * + * The returned view allows to read and optionally to modify attributes of a file. + * + * @param V the reified type of the desired attribute view. + * + * @see Files.getFileAttributeView + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.fileAttributesViewOrNull(vararg options: LinkOption): V? = + Files.getFileAttributeView(this, V::class.java, *options) + +/** + * Returns a file attributes view of a given type [V] + * or throws an [UnsupportedOperationException] if the requested attribute view type is not available.. + * + * The returned view allows to read and optionally to modify attributes of a file. + * + * @param V the reified type of the desired attribute view, a subtype of [FileAttributeView]. + * + * @see Files.getFileAttributeView + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.fileAttributesView(vararg options: LinkOption): V = + Files.getFileAttributeView(this, V::class.java, *options) ?: fileAttributeViewNotAvailable(this, V::class.java) + +@PublishedApi +internal fun fileAttributeViewNotAvailable(path: Path, attributeViewClass: Class<*>): Nothing = + throw UnsupportedOperationException("The desired attribute view type $attributeViewClass is not available for the file $path.") + +/** + * Reads a file's attributes of the specified type [A] in bulk. + * + * @param A the reified type of the desired attributes, a subtype of [BasicFileAttributes]. + * + * @throws UnsupportedOperationException if the given attributes type [A] is not supported. + * @see Files.readAttributes + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.readAttributes(vararg options: LinkOption): A = + Files.readAttributes(this, A::class.java, *options) + +/** + * Reads the specified list of attributes of a file in bulk. + * + * The list of [attributes] to read is specified in the following string form: + * ``` + * [view:]attribute_name1[,attribute_name2...] + * ``` + * So the names are comma-separated and optionally prefixed by the attribute view type name, `basic` by default. + * The special `*` attribute name can be used to read all attributes of the specified view. + * + * @return a [Map][Map] having an entry for an each attribute read, where the key is the attribute name and the value is the attribute value. + * @throws UnsupportedOperationException if the attribute view is not supported. + * @throws IllegalArgumentException if no attributes are specified or an unrecognized attribute is specified. + * @see Files.readAttributes + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.readAttributes(attributes: String, vararg options: LinkOption): Map = + Files.readAttributes(this, attributes, *options) + +/** + * Returns the last modified time of the file located by this path. + * + * If the file system does not support modification timestamps, some implementation-specific default is returned. + * + * @see Files.getLastModifiedTime + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.getLastModifiedTime(vararg options: LinkOption): FileTime = + Files.getLastModifiedTime(this, *options) + +/** + * Sets the last modified time attribute for the file located by this path. + * + * If the file system does not support modification timestamps, the behavior of this method is not defined. + * + * @see Files.setLastModifiedTime + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.setLastModifiedTime(value: FileTime): Path = + Files.setLastModifiedTime(this, value) + +/** + * Returns the owner of a file. + * + * @throws UnsupportedOperationException if the associated file system does not support the [FileOwnerAttributeView]. + * + * @see Files.getOwner + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.getOwner(vararg options: LinkOption): UserPrincipal? = + Files.getOwner(this, *options) + +/** + * Sets the file owner to the specified [value]. + * + * @throws UnsupportedOperationException if the associated file system does not support the [FileOwnerAttributeView]. + * + * @see Files.setOwner + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.setOwner(value: UserPrincipal): Path = + Files.setOwner(this, value) + +/** + * Returns the POSIX file permissions of the file located by this path. + * + * @throws UnsupportedOperationException if the associated file system does not support the [PosixFileAttributeView]. + * + * @see Files.getPosixFilePermissions + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.getPosixFilePermissions(vararg options: LinkOption): Set = + Files.getPosixFilePermissions(this, *options) + +/** + * Sets the POSIX file permissions for the file located by this path. + * + * @throws UnsupportedOperationException if the associated file system does not support the [PosixFileAttributeView]. + * + * @see Files.setPosixFilePermissions + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.setPosixFilePermissions(value: Set): Path = + Files.setPosixFilePermissions(this, value) + +/** + * Creates a new link (directory entry) located by this path for the existing file [target]. + * + * Calling this function may require the process to be started with implementation specific privileges to create hard links + * or to create links to directories. + * + * @throws FileAlreadyExistsException if a file with this name already exists + * (optional specific exception, some implementations may throw a more general one). + * @throws UnsupportedOperationException if the implementation does not support creating a hard link. + * + * @see Files.createLink + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.createLinkPointingTo(target: Path): Path = + Files.createLink(this, target) + +/** + * Creates a new symbolic link located by this path to the given [target]. + * + * Calling this function may require the process to be started with implementation specific privileges to + * create symbolic links. + * + * @throws FileAlreadyExistsException if a file with this name already exists + * (optional specific exception, some implementations may throw a more general one). + * @throws UnsupportedOperationException if the implementation does not support symbolic links or the + * [attributes] array contains an attribute that cannot be set atomically when creating the symbolic link. + * + * @see Files.createSymbolicLink + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.createSymbolicLinkPointingTo(target: Path, vararg attributes: FileAttribute<*>): Path = + Files.createSymbolicLink(this, target, *attributes) + +/** + * Reads the target of a symbolic link located by this path. + * + * @throws UnsupportedOperationException if symbolic links are not supported by this implementation. + * @throws NotLinkException if the target is not a symbolic link + * (optional specific exception, some implementations may throw a more general one). + * + * @see Files.readSymbolicLink + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.readSymbolicLink(): Path = + Files.readSymbolicLink(this) + +/** + * Creates a new and empty file specified by this path, failing if the file already exists. + * + * @param attributes an optional list of file attributes to set atomically when creating the file. + * + * @throws FileAlreadyExistsException if a file specified by this path already exists + * (optional specific exception, some implementations may throw more general [IOException]). + * @throws UnsupportedOperationException if the [attributes] array contains an attribute that cannot be set atomically + * when creating the file. + * + * @see Files.createFile + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path.createFile(vararg attributes: FileAttribute<*>): Path = + Files.createFile(this, *attributes) + +/** + * Creates an empty file in the default temp directory, using + * the given [prefix] and [suffix] to generate its name. + * + * @param attributes an optional list of file attributes to set atomically when creating the file. + * @return the path to the newly created file that did not exist before. + * + * @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically + * when creating the file. + * + * @see Files.createTempFile + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun createTempFile(prefix: String? = null, suffix: String? = null, vararg attributes: FileAttribute<*>): Path = + Files.createTempFile(prefix, suffix, *attributes) + +/** + * Creates an empty file in the specified [directory], using + * the given [prefix] and [suffix] to generate its name. + * + * @param attributes an optional list of file attributes to set atomically when creating the file. + * @return the path to the newly created file that did not exist before. + * + * @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically + * when creating the file. + * + * @see Files.createTempFile + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun createTempFile(directory: Path, prefix: String? = null, suffix: String? = null, vararg attributes: FileAttribute<*>): Path = + Files.createTempFile(directory, prefix, suffix, *attributes) + +/** + * Creates a new directory in the default temp directory, using the given [prefix] to generate its name. + * + * @param attributes an optional list of file attributes to set atomically when creating the directory. + * @return the path to the newly created directory that did not exist before. + * + * @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically + * when creating the directory. + * + * @see Files.createTempDirectory + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun createTempDirectory(prefix: String? = null, vararg attributes: FileAttribute<*>): Path = + Files.createTempDirectory(prefix, *attributes) + +/** + * Creates a new directory in the specified [directory], using the given [prefix] to generate its name. + * + * @param attributes an optional list of file attributes to set atomically when creating the directory. + * @return the path to the newly created directory that did not exist before. + * + * @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically + * when creating the directory. + * + * @see Files.createTempDirectory + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun createTempDirectory(directory: Path, prefix: String? = null, vararg attributes: FileAttribute<*>): Path = + Files.createTempDirectory(directory, prefix, *attributes) + +/** + * Resolves the given [other] path against this path. + * + * This operator is a shortcut for the [Path.resolve] function. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline operator fun Path.div(other: Path): Path = + this.resolve(other) + +/** + * Resolves the given [other] path string against this path. + * + * This operator is a shortcut for the [Path.resolve] function. + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline operator fun Path.div(other: String): Path = + this.resolve(other) + + +/** + * Converts the provided [path] string to a [Path] object of the [default][FileSystems.getDefault] filesystem. + * + * @see Paths.get + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path(path: String): Path = + Paths.get(path) + +/** + * Converts the name sequence specified with the [base] path string and a number of [subpaths] additional names + * to a [Path] object of the [default][FileSystems.getDefault] filesystem. + * + * @see Paths.get + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun Path(base: String, vararg subpaths: String): Path = + Paths.get(base, *subpaths) + +/** + * Converts this URI to a [Path] object. + * + * @see Paths.get + */ +@SinceKotlin("1.4") +@ExperimentalPathApi +@kotlin.internal.InlineOnly +public inline fun URI.toPath(): Path = + Paths.get(this) diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 582a928079c..84c542acc63 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -7,38 +7,62 @@ package kotlin.jdk7.test import java.io.IOException import java.nio.file.* +import java.nio.file.attribute.* import kotlin.io.path.* +import kotlin.random.Random import kotlin.test.* class PathExtensionsTest { - private val isCaseInsensitiveFileSystem = Paths.get("C:/") == Paths.get("c:/") + private val isCaseInsensitiveFileSystem = Path("C:/") == Path("c:/") private val isBackslashSeparator = FileSystems.getDefault().separator == "\\" @Test - fun extension() { - assertEquals("bbb", Paths.get("aaa.bbb").extension) - assertEquals("", Paths.get("aaa").extension) - assertEquals("", Paths.get("aaa.").extension) - assertEquals("bbb", Paths.get(".bbb").extension) - assertEquals("", Paths.get("/my.dir/log").extension) - assertEquals("", Paths.get("/").extension) + fun filenameComponents() { + fun check(path: String, name: String, nameNoExt: String, extension: String) { + val p = Path(path) + assertEquals(name, p.name, "name") + assertEquals(nameNoExt, p.nameWithoutExtension, "nameWithoutExtension") + assertEquals(extension, p.extension, "extension") + } + + check(path = "aaa.bbb", name = "aaa.bbb", nameNoExt = "aaa", extension = "bbb") + check(path = "aaa", name = "aaa", nameNoExt = "aaa", extension = "") + check(path = "aaa.", name = "aaa.", nameNoExt = "aaa", extension = "") + check(path = ".aaa", name = ".aaa", nameNoExt = "", extension = "aaa") + check(path = "/dir.ext/aaa.bbb", name = "aaa.bbb", nameNoExt = "aaa", extension = "bbb") + check(path = "/dir.ext/aaa", name = "aaa", nameNoExt = "aaa", extension = "") + check(path = "/", name = "", nameNoExt = "", extension = "") + check(path = "", name = "", nameNoExt = "", extension = "") } @Test - fun nameWithoutExtension() { - assertEquals("aaa", Paths.get("aaa.bbb").nameWithoutExtension) - assertEquals("aaa", Paths.get("aaa").nameWithoutExtension) - assertEquals("aaa", Paths.get("aaa.").nameWithoutExtension) - assertEquals("", Paths.get(".bbb").nameWithoutExtension) - assertEquals("log", Paths.get("/my.dir/log").nameWithoutExtension) - assertEquals("", Paths.get("").nameWithoutExtension) - assertEquals("", Paths.get("/").nameWithoutExtension) + fun invariantSeparators() { + val path = Path("base") / "nested" / "leaf" + assertEquals("base/nested/leaf", path.invariantSeparatorsPath) + + val path2 = Path("base", "nested", "leaf") + assertEquals("base/nested/leaf", path2.invariantSeparatorsPath) } @Test - fun testCopyTo() { - val srcFile = Files.createTempFile(null, null) - val dstFile = Files.createTempFile(null, null) + fun createNewFile() { + val dir = createTempDirectory() + + val file = dir / "new-file" + + assertTrue(file.notExists()) + + file.createFile() + assertTrue(file.exists()) + assertTrue(file.isRegularFile()) + + assertFailsWith { file.createFile() } + } + + @Test + fun copyTo() { + val srcFile = createTempFile() + val dstFile = createTempFile() try { srcFile.writeText("Hello, World!") assertFailsWith("copy do not overwrite existing file") { @@ -53,35 +77,34 @@ class PathExtensionsTest { srcFile.copyTo(srcFile, overwrite = true) compareFiles(dst, srcFile, "copying file to itself leaves it intact") - assertTrue(Files.deleteIfExists(dstFile)) + assertTrue(dstFile.deleteIfExists()) dst = srcFile.copyTo(dstFile) compareFiles(srcFile, dst, "copy to new file") val subDst = dstFile.resolve("foo/bar") - assertFailsWith { srcFile.copyTo(subDst) } - assertFailsWith { srcFile.copyTo(subDst, overwrite = true) } - assertTrue(Files.deleteIfExists(dstFile)) - assertFailsWith { srcFile.copyTo(subDst) } + assertFailsWith { srcFile.copyTo(subDst) } + assertFailsWith { srcFile.copyTo(subDst, overwrite = true) } + assertTrue(dstFile.deleteIfExists()) + assertFailsWith { srcFile.copyTo(subDst) } - Files.createDirectory(dstFile) - val child = dstFile.resolve("child") - Files.createFile(child) - assertFailsWith( "copy with overwrite do not overwrite non-empty dir") { + dstFile.createDirectory() + val child = dstFile.resolve("child").createFile() + assertFailsWith("copy with overwrite do not overwrite non-empty dir") { srcFile.copyTo(dstFile, overwrite = true) } - Files.delete(child) + child.deleteExisting() srcFile.copyTo(dstFile, overwrite = true) assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir") - assertTrue(Files.deleteIfExists(srcFile)) - assertTrue(Files.deleteIfExists(dstFile)) + assertTrue(srcFile.deleteIfExists()) + assertTrue(dstFile.deleteIfExists()) assertFailsWith { srcFile.copyTo(dstFile) } - Files.createDirectory(srcFile) + srcFile.createDirectory() srcFile.resolve("somefile").writeText("some content") dstFile.writeText("") assertFailsWith("copy dir do not overwrite file") { @@ -111,35 +134,141 @@ class PathExtensionsTest { @Test fun copyToNameWithoutParent() { - val currentDir = Paths.get("").toAbsolutePath() - val srcFile = Files.createTempFile(null, null) - val dstFile = Files.createTempFile(currentDir, null, null) + val currentDir = Path("").toAbsolutePath() + val srcFile = createTempFile() + val dstFile = createTempFile(directory = currentDir) try { srcFile.writeText("Hello, World!", Charsets.UTF_8) - Files.delete(dstFile) + dstFile.deleteExisting() - val dstRelative = Paths.get(dstFile.fileName.toString()) + val dstRelative = Path(dstFile.name) srcFile.copyTo(dstRelative) assertEquals(srcFile.readText(), dstFile.readText()) } finally { - Files.delete(dstFile) - Files.delete(srcFile) + dstFile.deleteExisting() + srcFile.deleteExisting() + } + } + + @Test + fun moveTo() { + val original = createTempFile() + val srcFile = createTempFile() + val dstFile = createTempFile() + fun restoreSrcFile() { original.copyTo(srcFile, overwrite = true) } + try { + original.writeText("Hello, World!") + restoreSrcFile() + + assertFailsWith("do not overwrite existing file") { + srcFile.moveTo(dstFile) + } + + var dst = srcFile.moveTo(dstFile, overwrite = true) + assertSame(dst, dstFile) + compareFiles(original, dst, "move with overwrite over existing file") + assertTrue(srcFile.notExists()) + + restoreSrcFile() + srcFile.moveTo(srcFile) + srcFile.moveTo(srcFile, overwrite = true) + + compareFiles(original, srcFile, "move file to itself leaves it intact") + + assertTrue(dstFile.deleteIfExists()) + dst = srcFile.moveTo(dstFile) + compareFiles(original, dst, "move to new file") + + restoreSrcFile() + val subDst = dstFile.resolve("foo/bar") + assertFailsWith { srcFile.moveTo(subDst) } + assertFailsWith { srcFile.moveTo(subDst, overwrite = true) } + assertTrue(dstFile.deleteIfExists()) + assertFailsWith { srcFile.moveTo(subDst) } + + dstFile.createDirectory() + val child = dstFile.resolve("child").createFile() + assertFailsWith("move with overwrite do not overwrite non-empty dir") { + srcFile.moveTo(dstFile, overwrite = true) + } + child.deleteExisting() + + srcFile.moveTo(dstFile, overwrite = true) + compareFiles(original, dstFile, "move with overwrite over empty dir") + + assertTrue(srcFile.notExists()) + assertTrue(dstFile.deleteIfExists()) + + assertFailsWith { + srcFile.moveTo(dstFile) + } + + srcFile.createDirectory() + srcFile.resolve("somefile").writeText("some content") + dstFile.writeText("") + assertFailsWith("move dir do not overwrite file") { + srcFile.moveTo(dstFile) + } + srcFile.moveTo(dstFile, overwrite = true) + assertTrue(dstFile.isDirectory()) + assertEquals(listOf(dstFile / "somefile"), dstFile.listDirectoryEntries(), "directory is moved with its content") + } finally { + srcFile.toFile().deleteRecursively() + dstFile.toFile().deleteRecursively() } } private fun compareFiles(src: Path, dst: Path, message: String? = null) { assertTrue(dst.exists()) assertEquals(src.isRegularFile(), dst.isRegularFile(), message) + assertEquals(src.isDirectory(), dst.isDirectory(), message) if (dst.isRegularFile()) { assertTrue(src.readBytes().contentEquals(dst.readBytes()), message) } } @Test - fun testAttributeGettersOnFile() { - val file = Files.createTempFile(null, null) + fun fileSize() { + val file = createTempFile() + assertEquals(0, file.fileSize()) + + file.writeBytes(ByteArray(100)) + assertEquals(100, file.fileSize()) + + file.appendText("Hello", Charsets.US_ASCII) + assertEquals(105, file.fileSize()) + + file.deleteExisting() + assertFailsWith { file.fileSize() } + } + + @Test + fun deleteExisting() { + val file = createTempFile() + file.deleteExisting() + assertFailsWith { file.deleteExisting() } + + val dir = createTempDirectory() + dir.deleteExisting() + assertFailsWith { dir.deleteExisting() } + } + + @Test + fun deleteIfExists() { + val file = createTempFile() + assertTrue(file.deleteIfExists()) + assertFalse(file.deleteIfExists()) + + val dir = createTempDirectory() + assertTrue(dir.deleteIfExists()) + assertFalse(dir.deleteIfExists()) + } + + @Test + fun attributeGettersOnFile() { + val file = createTempFile("temp", ".file") assertTrue(file.exists()) assertFalse(file.notExists()) assertTrue(file.isRegularFile()) @@ -147,17 +276,18 @@ class PathExtensionsTest { assertFalse(file.isSymbolicLink()) assertTrue(file.isReadable()) assertTrue(file.isWritable()) - assertTrue(file.isSameFile(file)) + assertTrue(file.isSameFileAs(file)) // The default value of these depends on the current operating system, so just check that // they don't throw an exception. file.isExecutable() file.isHidden() + file.deleteExisting() } @Test - fun testAttributeGettersOnDirectory() { - val file = Files.createTempDirectory(null) + fun attributeGettersOnDirectory() { + val file = createTempDirectory(".tmpdir") assertTrue(file.exists()) assertFalse(file.notExists()) assertFalse(file.isRegularFile()) @@ -165,15 +295,16 @@ class PathExtensionsTest { assertFalse(file.isSymbolicLink()) assertTrue(file.isReadable()) assertTrue(file.isWritable()) - assertTrue(file.isSameFile(file)) + assertTrue(file.isSameFileAs(file)) file.isExecutable() file.isHidden() + file.deleteExisting() } @Test - fun testAttributeGettersOnNonExistentPath() { - val file = Files.createTempDirectory(null).resolve("foo") + fun attributeGettersOnNonExistentPath() { + val file = createTempDirectory().resolve("foo") assertFalse(file.exists()) assertTrue(file.notExists()) assertFalse(file.isRegularFile()) @@ -181,7 +312,7 @@ class PathExtensionsTest { assertFalse(file.isSymbolicLink()) assertFalse(file.isReadable()) assertFalse(file.isWritable()) - assertTrue(file.isSameFile(file)) + assertTrue(file.isSameFileAs(file)) file.isExecutable() // This function will either throw an exception or return false, @@ -190,15 +321,95 @@ class PathExtensionsTest { assertFalse(file.isHidden()) } catch (e: IOException) { } + file.parent.deleteExisting() + } + + private interface SpecialFileAttributesView : FileAttributeView + private interface SpecialFileAttributes : BasicFileAttributes + + @Test + fun readWriteAttributes() { + val file = createTempFile() + val modifiedTime = file.getLastModifiedTime() + assertEquals(modifiedTime, file.getAttribute("lastModifiedTime")) + assertEquals(modifiedTime, file.getAttribute("basic:lastModifiedTime")) + assertEquals(modifiedTime, file.readAttributes().lastModifiedTime()) + assertEquals(modifiedTime, file.readAttributes("basic:lastModifiedTime,creationTime")["lastModifiedTime"]) + assertEquals(modifiedTime, file.readAttributes("*")["lastModifiedTime"]) + + assertFailsWith { file.readAttributes() } + assertFailsWith { file.readAttributes("really_unsupported_view:*") } + assertFailsWith { file.readAttributes("basic:really_unknown_attribute") } + + val newTime1 = FileTime.fromMillis(modifiedTime.toMillis() + 3600_000) + file.setLastModifiedTime(newTime1) + assertEquals(newTime1, file.getLastModifiedTime()) + + val newTime2 = FileTime.fromMillis(modifiedTime.toMillis() + 2 * 3600_000) + file.setAttribute("lastModifiedTime", newTime2) + assertEquals(newTime2, file.getLastModifiedTime()) + + val newTime3 = FileTime.fromMillis(modifiedTime.toMillis() + 3 * 3600_000) + file.fileAttributesView().setTimes(newTime3, null, null) + assertEquals(newTime3, file.getLastModifiedTime()) + + assertFailsWith { file.fileAttributesView() } + assertNull(file.fileAttributesViewOrNull()) + + file.setAttribute("lastModifiedTime", null) + assertEquals(newTime3, file.getLastModifiedTime()) + + file.deleteExisting() } @Test - fun testListDirectoryEntries() { - val dir = Files.createTempDirectory(null) + fun links() { + val dir = createTempDirectory() + val original = createTempFile(dir) + original.writeBytes(Random.nextBytes(100)) + + val link = try { + (dir / ("link-" + original.fileName)).createLinkPointingTo(original) + } catch (e: IOException) { + // may require a privilege + println("Creating a link failed with ${e.stackTraceToString()}") + return + } + + assertTrue(link.isRegularFile()) + assertTrue(link.isRegularFile(LinkOption.NOFOLLOW_LINKS)) + assertTrue(original.isSameFileAs(link)) + compareFiles(original, link) + assertFailsWith { link.readSymbolicLink() } + } + + @Test + fun symlinks() { + val dir = createTempDirectory() + val original = createTempFile(dir) + original.writeBytes(Random.nextBytes(100)) + + val symlink = try { + (dir / ("symlink-" + original.fileName)).createSymbolicLinkPointingTo(original) + } catch (e: IOException) { + // may require a privilege + println("Creating a symlink failed with ${e.stackTraceToString()}") + return + } + + assertTrue(symlink.isRegularFile()) + assertFalse(symlink.isRegularFile(LinkOption.NOFOLLOW_LINKS)) + assertTrue(original.isSameFileAs(symlink)) + compareFiles(original, symlink) + assertEquals(original, symlink.readSymbolicLink()) + } + + @Test + fun directoryEntriesList() { + val dir = createTempDirectory() assertEquals(0, dir.listDirectoryEntries().size) - val file = dir.resolve("f1") - Files.createFile(file) + val file = dir.resolve("f1").createFile() assertEquals(listOf(file), dir.listDirectoryEntries()) val fileTxt = createTempFile(dir, suffix = ".txt") @@ -208,12 +419,11 @@ class PathExtensionsTest { } @Test - fun testUseDirectoryEntries() { - val dir = Files.createTempDirectory(null) + fun directoryEntriesUseSequence() { + val dir = createTempDirectory() assertEquals(0, dir.useDirectoryEntries { it.toList() }.size) - val file = dir.resolve("f1") - Files.createFile(file) + val file = dir.resolve("f1").createFile() assertEquals(listOf(file), dir.useDirectoryEntries { it.toList() }) val fileTxt = createTempFile(dir, suffix = ".txt") @@ -223,12 +433,11 @@ class PathExtensionsTest { } @Test - fun testForEachDirectoryEntry() { - val dir = Files.createTempDirectory(null) + fun directoryEntriesForEach() { + val dir = createTempDirectory() dir.forEachDirectoryEntry { error("shouldn't get here, but received $it") } - val file = dir.resolve("f1") - Files.createFile(file) + val file = createTempFile(dir) dir.forEachDirectoryEntry { assertEquals(file, it) } val fileTxt = createTempFile(dir, suffix = ".txt") @@ -239,9 +448,9 @@ class PathExtensionsTest { private fun testRelativeTo(expected: String?, path: String, base: String) = - testRelativeTo(expected?.let { Paths.get(it) }, Paths.get(path), Paths.get(base)) + testRelativeTo(expected?.let { Path(it) }, Path(path), Path(base)) private fun testRelativeTo(expected: String, path: Path, base: Path) = - testRelativeTo(Paths.get(expected), path, base) + testRelativeTo(Path(expected), path, base) private fun testRelativeTo(expected: Path?, path: Path, base: Path) { val context = "path: '$path', base: '$base'" @@ -304,23 +513,23 @@ class PathExtensionsTest { @Test fun relativeToRelative() { - val nested = Paths.get("foo/bar") - val base = Paths.get("foo") + val nested = Path("foo/bar") + val base = Path("foo") testRelativeTo("bar", nested, base) testRelativeTo("..", base, nested) - val empty = Paths.get("") - val current = Paths.get(".") - val parent = Paths.get("..") - val outOfRoot = Paths.get("../bar") + val empty = Path("") + val current = Path(".") + val parent = Path("..") + val outOfRoot = Path("../bar") testRelativeTo("../bar", outOfRoot, empty) testRelativeTo("../../bar", outOfRoot, base) testRelativeTo("bar", outOfRoot, parent) testRelativeTo("..", parent, outOfRoot) - val root = Paths.get("/root") + val root = Path("/root") val files = listOf(nested, base, empty, outOfRoot, current, parent) val bases = listOf(nested, base, empty, current) @@ -340,10 +549,10 @@ class PathExtensionsTest { @Test fun relativeToFails() { - val absolute = Paths.get("/foo/bar/baz") - val relative = Paths.get("foo/bar") - val networkShare1 = Paths.get("""\\my.host\share1/folder""") - val networkShare2 = Paths.get("""\\my.host\share2\folder""") + val absolute = Path("/foo/bar/baz") + val relative = Path("foo/bar") + val networkShare1 = Path("""\\my.host\share1/folder""") + val networkShare2 = Path("""\\my.host\share2\folder""") val allFiles = listOf(absolute, relative) + if (isBackslashSeparator) listOf(networkShare1, networkShare2) else emptyList() for (file in allFiles) { diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt index 87c6a91923f..058dcc87baf 100644 --- a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt @@ -8,24 +8,25 @@ package kotlin.jdk7.test import java.nio.file.Files import java.nio.file.StandardOpenOption import kotlin.io.path.* +import kotlin.random.Random import kotlin.test.* class PathReadWriteTest { @Test - fun testAppendText() { - val file = Files.createTempFile(null, null) + fun appendText() { + val file = createTempFile() file.writeText("Hello\n") file.appendText("World\n") file.writeText("Again", Charsets.US_ASCII, StandardOpenOption.APPEND) assertEquals("Hello\nWorld\nAgain", file.readText()) assertEquals(listOf("Hello", "World", "Again"), file.readLines(Charsets.UTF_8)) - file.toFile().deleteOnExit() + file.deleteExisting() } @Test fun file() { - val file = Files.createTempFile(null, null) + val file = createTempFile() val writer = file.outputStream().writer().buffered() writer.write("Hello") @@ -72,31 +73,54 @@ class PathReadWriteTest { } @Test - fun testBufferedReader() { - val file = Files.createTempFile(null, null) + fun bufferedReader() { + val file = createTempFile() val lines = listOf("line1", "line2") - Files.write(file, lines, Charsets.UTF_8) + file.writeLines(lines) - assertEquals(file.bufferedReader().use { it.readLines() }, lines) - assertEquals(file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() }, lines) + assertEquals(lines, file.bufferedReader().use { it.readLines() }) + assertEquals(lines, file.bufferedReader(Charsets.UTF_8, 1024, StandardOpenOption.READ).use { it.readLines() }) } @Test - fun testBufferedWriter() { - val file = Files.createTempFile(null, null) + fun bufferedWriter() { + val file = createTempFile() file.bufferedWriter().use { it.write("line1\n") } file.bufferedWriter(Charsets.UTF_8, 1024, StandardOpenOption.APPEND).use { it.write("line2\n") } - assertEquals(Files.readAllLines(file, Charsets.UTF_8), listOf("line1", "line2")) + assertEquals(listOf("line1", "line2"), file.readLines()) } @Test - fun testWriteBytes() { - val file = Files.createTempFile(null, null) + fun writeBytes() { + val file = createTempFile() file.writeBytes("Hello".encodeToByteArray()) file.appendBytes(" world!".encodeToByteArray()) assertEquals(file.readText(), "Hello world!") + + val bytes = Random.nextBytes(100) + file.writeBytes(bytes) + file.appendBytes(bytes) + assertTrue((bytes + bytes) contentEquals file.readBytes()) + } + + @Test + fun writeLines() { + val file = createTempFile() + val lines = listOf("first line", "second line") + file.writeLines(lines) + assertEquals(lines, file.readLines()) + + file.writeLines(lines.asSequence()) + assertEquals(lines, file.readLines()) + + val moreLines = listOf("third line", "the bottom line") + file.appendLines(moreLines) + assertEquals(lines + moreLines, file.readLines()) + + file.appendLines(moreLines.asSequence()) + assertEquals(lines + moreLines + moreLines, file.readLines()) } } diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt index c77b8fc031c..8d3f61a1aa4 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt @@ -1,3 +1,23 @@ +public abstract interface annotation class kotlin/io/path/ExperimentalPathApi : java/lang/annotation/Annotation { +} + +public final class kotlin/io/path/PathsKt { + public static final fun appendText (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;)V + public static synthetic fun appendText$default (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;ILjava/lang/Object;)V + public static final fun fileAttributeViewNotAvailable (Ljava/nio/file/Path;Ljava/lang/Class;)Ljava/lang/Void; + public static final fun getExtension (Ljava/nio/file/Path;)Ljava/lang/String; + public static final fun getInvariantSeparatorsPath (Ljava/nio/file/Path;)Ljava/lang/String; + public static final fun getName (Ljava/nio/file/Path;)Ljava/lang/String; + public static final fun getNameWithoutExtension (Ljava/nio/file/Path;)Ljava/lang/String; + public static final fun listDirectoryEntries (Ljava/nio/file/Path;Ljava/lang/String;)Ljava/util/List; + public static synthetic fun listDirectoryEntries$default (Ljava/nio/file/Path;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/List; + public static final fun relativeTo (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; + public static final fun relativeToOrNull (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; + public static final fun relativeToOrSelf (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; + public static final fun writeText (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;[Ljava/nio/file/OpenOption;)V + public static synthetic fun writeText$default (Ljava/nio/file/Path;Ljava/lang/String;Ljava/nio/charset/Charset;[Ljava/nio/file/OpenOption;ILjava/lang/Object;)V +} + public final class kotlin/jdk7/AutoCloseableKt { public static final fun closeFinally (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V } From fe098ec82120448b1d40993e86feb3ee0a13f8e5 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 15 Oct 2020 02:57:09 +0300 Subject: [PATCH 029/554] Revise functions in PathReadWrite - Adjust implementations to avoid excessive vararg copies - Remove options from forEachLine, it doesn't make much sense and isn't consistent with the other read* functions. - Revise inlineness of functions in PathReadWrite - Compact implementations of those that are remained inline. - Clarify docs of functions for reading the entire file #KT-19192 --- .../jdk7/src/kotlin/io/path/PathReadWrite.kt | 50 ++++++++++++------- .../stdlib/jdk7/test/PathReadWriteTest.kt | 2 +- .../kotlin-stdlib-jdk7.txt | 2 + 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt index 6022e323ef8..4692f8618ae 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathReadWrite.kt @@ -26,7 +26,7 @@ import java.nio.file.StandardOpenOption @ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.reader(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): InputStreamReader { - return inputStream(*options).reader(charset) + return InputStreamReader(Files.newInputStream(this, *options), charset) } /** @@ -44,7 +44,12 @@ public inline fun Path.bufferedReader( bufferSize: Int = DEFAULT_BUFFER_SIZE, vararg options: OpenOption ): BufferedReader { - return reader(charset, *options).buffered(bufferSize) + return BufferedReader( + InputStreamReader( + Files.newInputStream(this, *options), + charset + ), + bufferSize) } /** @@ -57,7 +62,7 @@ public inline fun Path.bufferedReader( @ExperimentalPathApi @kotlin.internal.InlineOnly public inline fun Path.writer(charset: Charset = Charsets.UTF_8, vararg options: OpenOption): OutputStreamWriter { - return outputStream(*options).writer(charset) + return OutputStreamWriter(Files.newOutputStream(this, *options), charset) } /** @@ -75,13 +80,19 @@ public inline fun Path.bufferedWriter( bufferSize: Int = DEFAULT_BUFFER_SIZE, vararg options: OpenOption ): BufferedWriter { - return writer(charset, *options).buffered(bufferSize) + return BufferedWriter( + OutputStreamWriter( + Files.newOutputStream(this, *options), + charset), + bufferSize) } /** * Gets the entire content of this file as a byte array. * - * This method is not recommended on huge files. It has an internal limitation of 2 GB byte array size. + * It's not recommended to use this function on huge files. + * It has an internal limitation of approximately 2 GB byte array size. + * For reading large files or files of unknown size, open an [InputStream][Path.inputStream] and read blocks sequentially. * * @return the entire content of this file as a byte array. */ @@ -123,16 +134,16 @@ public inline fun Path.appendBytes(array: ByteArray) { /** * Gets the entire content of this file as a String using UTF-8 or the specified [charset]. * - * This method is not recommended on huge files. It has an internal limitation of 2 GB file size. + * It's not recommended to use this function on huge files. + * For reading large files or files of unknown size, open a [Reader][Path.reader] and read blocks of text sequentially. * * @param charset character set to use for reading text, UTF-8 by default. * @return the entire content of this file as a String. */ @SinceKotlin("1.4") @ExperimentalPathApi -@kotlin.internal.InlineOnly -public inline fun Path.readText(charset: Charset = Charsets.UTF_8): String = - readBytes().toString(charset) +public fun Path.readText(charset: Charset = Charsets.UTF_8): String = + reader(charset).use { it.readText() } /** * Sets the content of this file as [text] encoded using UTF-8 or the specified [charset]. @@ -146,8 +157,8 @@ public inline fun Path.readText(charset: Charset = Charsets.UTF_8): String = */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, vararg options: OpenOption): Unit { - writeBytes(text.toByteArray(charset), *options) +public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, vararg options: OpenOption) { + Files.newOutputStream(this, *options).writer(charset).use { it.write(text) } } /** @@ -158,8 +169,8 @@ public fun Path.writeText(text: String, charset: Charset = Charsets.UTF_8, varar */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit { - writeText(text, charset, StandardOpenOption.APPEND) +public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8) { + Files.newOutputStream(this, StandardOpenOption.APPEND).writer(charset).use { it.write(text) } } /** @@ -168,15 +179,15 @@ public fun Path.appendText(text: String, charset: Charset = Charsets.UTF_8): Uni * * You may use this function on huge files. * - * @param options options to determine how the file is opened. * @param charset character set to use for reading text, UTF-8 by default. * @param action function to process file lines. */ @SinceKotlin("1.4") @ExperimentalPathApi -public fun Path.forEachLine(charset: Charset = Charsets.UTF_8, vararg options: OpenOption, action: (line: String) -> Unit): Unit { - // Note: close is called at forEachLine - bufferedReader(charset, options = options).forEachLine(action) +@kotlin.internal.InlineOnly +public inline fun Path.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit { + // cannot use non-inline forEachLine + Files.newBufferedReader(this, charset).useLines { it.forEach(action) } } /** @@ -210,7 +221,8 @@ public inline fun Path.outputStream(vararg options: OpenOption): OutputStream { /** * Reads the file content as a list of lines. * - * Do not use this function for huge files. + * It's not recommended to use this function on huge files. + * For reading lines of a large file or a file of unknown size, use [Path.forEachLine] or [Path.useLines]. * * @param charset character set to use for reading text, UTF-8 by default. * @return list of file lines. @@ -233,7 +245,7 @@ public inline fun Path.readLines(charset: Charset = Charsets.UTF_8): List Path.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence) -> T): T { - return bufferedReader(charset).use { block(it.lineSequence()) } + return Files.newBufferedReader(this, charset).use { block(it.lineSequence()) } } /** diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt index 058dcc87baf..f59f1969a6f 100644 --- a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt @@ -35,7 +35,7 @@ class PathReadWriteTest { writer.close() val list = ArrayList() - file.forEachLine(charset = Charsets.UTF_8, options = arrayOf(StandardOpenOption.READ)) { + file.forEachLine(charset = Charsets.UTF_8) { list.add(it) } assertEquals(listOf("Hello", "World"), list) diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt index 8d3f61a1aa4..1ce2284c03b 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jdk7.txt @@ -11,6 +11,8 @@ public final class kotlin/io/path/PathsKt { public static final fun getNameWithoutExtension (Ljava/nio/file/Path;)Ljava/lang/String; public static final fun listDirectoryEntries (Ljava/nio/file/Path;Ljava/lang/String;)Ljava/util/List; public static synthetic fun listDirectoryEntries$default (Ljava/nio/file/Path;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/List; + public static final fun readText (Ljava/nio/file/Path;Ljava/nio/charset/Charset;)Ljava/lang/String; + public static synthetic fun readText$default (Ljava/nio/file/Path;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/lang/String; public static final fun relativeTo (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; public static final fun relativeToOrNull (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; public static final fun relativeToOrSelf (Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/nio/file/Path; From 0fa2cc15de9ffc0248ea9c3275e1dcb637157e95 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 23 Oct 2020 03:00:26 +0300 Subject: [PATCH 030/554] Cleanup more test files and directories after tests #KT-19192 --- .../stdlib/jdk7/test/AbstractPathTest.kt | 34 +++ .../stdlib/jdk7/test/PathExtensionsTest.kt | 286 +++++++++--------- .../stdlib/jdk7/test/PathReadWriteTest.kt | 18 +- 3 files changed, 176 insertions(+), 162 deletions(-) create mode 100644 libraries/stdlib/jdk7/test/AbstractPathTest.kt diff --git a/libraries/stdlib/jdk7/test/AbstractPathTest.kt b/libraries/stdlib/jdk7/test/AbstractPathTest.kt new file mode 100644 index 00000000000..189f874fd81 --- /dev/null +++ b/libraries/stdlib/jdk7/test/AbstractPathTest.kt @@ -0,0 +1,34 @@ +/* + * 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.jdk7.test +import java.nio.file.Path +import kotlin.io.path.deleteIfExists +import kotlin.test.* + +abstract class AbstractPathTest { + private val cleanUpActions = mutableListOf Unit>>() + + fun Path.cleanup(): Path { + cleanUpActions.add(this to { it.deleteIfExists() }) + return this + } + + fun Path.cleanupRecursively(): Path { + cleanUpActions.add(this to { it.toFile().deleteRecursively() }) + return this + } + + @AfterTest + fun cleanUp() { + for ((path, action) in cleanUpActions) { + try { + action(path) + } catch (e: Throwable) { + println("Failed to execute cleanup action for $path") + } + } + } +} diff --git a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt index 84c542acc63..e7fda78b02b 100644 --- a/libraries/stdlib/jdk7/test/PathExtensionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathExtensionsTest.kt @@ -12,7 +12,7 @@ import kotlin.io.path.* import kotlin.random.Random import kotlin.test.* -class PathExtensionsTest { +class PathExtensionsTest : AbstractPathTest() { private val isCaseInsensitiveFileSystem = Path("C:/") == Path("c:/") private val isBackslashSeparator = FileSystems.getDefault().separator == "\\" @@ -46,7 +46,7 @@ class PathExtensionsTest { @Test fun createNewFile() { - val dir = createTempDirectory() + val dir = createTempDirectory().cleanupRecursively() val file = dir / "new-file" @@ -61,163 +61,152 @@ class PathExtensionsTest { @Test fun copyTo() { - val srcFile = createTempFile() - val dstFile = createTempFile() - try { - srcFile.writeText("Hello, World!") - assertFailsWith("copy do not overwrite existing file") { - srcFile.copyTo(dstFile) - } + val root = createTempDirectory("copyTo-root").cleanupRecursively() + val srcFile = createTempFile(root, "src") + val dstFile = createTempFile(root, "dst") - var dst = srcFile.copyTo(dstFile, overwrite = true) - assertSame(dst, dstFile) - compareFiles(srcFile, dst, "copy with overwrite over existing file") + srcFile.writeText("Hello, World!") + assertFailsWith("copy do not overwrite existing file") { + srcFile.copyTo(dstFile) + } - srcFile.copyTo(srcFile) - srcFile.copyTo(srcFile, overwrite = true) - compareFiles(dst, srcFile, "copying file to itself leaves it intact") + var dst = srcFile.copyTo(dstFile, overwrite = true) + assertSame(dst, dstFile) + compareFiles(srcFile, dst, "copy with overwrite over existing file") - assertTrue(dstFile.deleteIfExists()) - dst = srcFile.copyTo(dstFile) - compareFiles(srcFile, dst, "copy to new file") + srcFile.copyTo(srcFile) + srcFile.copyTo(srcFile, overwrite = true) + compareFiles(dst, srcFile, "copying file to itself leaves it intact") - val subDst = dstFile.resolve("foo/bar") - assertFailsWith { srcFile.copyTo(subDst) } - assertFailsWith { srcFile.copyTo(subDst, overwrite = true) } - assertTrue(dstFile.deleteIfExists()) - assertFailsWith { srcFile.copyTo(subDst) } + assertTrue(dstFile.deleteIfExists()) + dst = srcFile.copyTo(dstFile) + compareFiles(srcFile, dst, "copy to new file") - dstFile.createDirectory() - val child = dstFile.resolve("child").createFile() - assertFailsWith("copy with overwrite do not overwrite non-empty dir") { - srcFile.copyTo(dstFile, overwrite = true) - } - child.deleteExisting() + val subDst = dstFile.resolve("foo/bar") + assertFailsWith { srcFile.copyTo(subDst) } + assertFailsWith { srcFile.copyTo(subDst, overwrite = true) } + assertTrue(dstFile.deleteIfExists()) + assertFailsWith { srcFile.copyTo(subDst) } + dstFile.createDirectory() + val child = dstFile.resolve("child").createFile() + assertFailsWith("copy with overwrite do not overwrite non-empty dir") { srcFile.copyTo(dstFile, overwrite = true) - assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir") + } + child.deleteExisting() - assertTrue(srcFile.deleteIfExists()) - assertTrue(dstFile.deleteIfExists()) + srcFile.copyTo(dstFile, overwrite = true) + assertEquals(srcFile.readText(), dstFile.readText(), "copy with overwrite over empty dir") - assertFailsWith { - srcFile.copyTo(dstFile) - } + assertTrue(srcFile.deleteIfExists()) + assertTrue(dstFile.deleteIfExists()) - srcFile.createDirectory() - srcFile.resolve("somefile").writeText("some content") - dstFile.writeText("") - assertFailsWith("copy dir do not overwrite file") { - srcFile.copyTo(dstFile) - } + assertFailsWith { + srcFile.copyTo(dstFile) + } + + srcFile.createDirectory() + srcFile.resolve("somefile").writeText("some content") + dstFile.writeText("") + assertFailsWith("copy dir do not overwrite file") { + srcFile.copyTo(dstFile) + } + srcFile.copyTo(dstFile, overwrite = true) + assertTrue(dstFile.isDirectory()) + assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") + + assertFailsWith("copy dir do not overwrite dir") { + srcFile.copyTo(dstFile) + } + + srcFile.copyTo(dstFile, overwrite = true) + assertTrue(dstFile.isDirectory()) + assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") + + dstFile.resolve("somefile2").writeText("some content2") + assertFailsWith("copy dir do not overwrite non-empty dir") { srcFile.copyTo(dstFile, overwrite = true) - assertTrue(dstFile.isDirectory()) - assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") - - assertFailsWith("copy dir do not overwrite dir") { - srcFile.copyTo(dstFile) - } - - srcFile.copyTo(dstFile, overwrite = true) - assertTrue(dstFile.isDirectory()) - assertTrue(dstFile.listDirectoryEntries().isEmpty(), "only directory is copied, but not its content") - - dstFile.resolve("somefile2").writeText("some content2") - assertFailsWith("copy dir do not overwrite non-empty dir") { - srcFile.copyTo(dstFile, overwrite = true) - } - } finally { - srcFile.toFile().deleteRecursively() - dstFile.toFile().deleteRecursively() } } @Test fun copyToNameWithoutParent() { val currentDir = Path("").toAbsolutePath() - val srcFile = createTempFile() - val dstFile = createTempFile(directory = currentDir) - try { - srcFile.writeText("Hello, World!", Charsets.UTF_8) - dstFile.deleteExisting() + val srcFile = createTempFile().cleanup() + val dstFile = createTempFile(directory = currentDir).cleanup() - val dstRelative = Path(dstFile.name) + srcFile.writeText("Hello, World!", Charsets.UTF_8) + dstFile.deleteExisting() - srcFile.copyTo(dstRelative) + val dstRelative = Path(dstFile.name) - assertEquals(srcFile.readText(), dstFile.readText()) - } finally { - dstFile.deleteExisting() - srcFile.deleteExisting() - } + srcFile.copyTo(dstRelative) + + assertEquals(srcFile.readText(), dstFile.readText()) } @Test fun moveTo() { - val original = createTempFile() - val srcFile = createTempFile() - val dstFile = createTempFile() + val root = createTempDirectory("moveTo-root").cleanupRecursively() + val original = createTempFile(root, "original") + val srcFile = createTempFile(root, "src") + val dstFile = createTempFile(root, "dst") fun restoreSrcFile() { original.copyTo(srcFile, overwrite = true) } - try { - original.writeText("Hello, World!") - restoreSrcFile() + original.writeText("Hello, World!") + restoreSrcFile() - assertFailsWith("do not overwrite existing file") { - srcFile.moveTo(dstFile) - } - - var dst = srcFile.moveTo(dstFile, overwrite = true) - assertSame(dst, dstFile) - compareFiles(original, dst, "move with overwrite over existing file") - assertTrue(srcFile.notExists()) - - restoreSrcFile() - srcFile.moveTo(srcFile) - srcFile.moveTo(srcFile, overwrite = true) - - compareFiles(original, srcFile, "move file to itself leaves it intact") - - assertTrue(dstFile.deleteIfExists()) - dst = srcFile.moveTo(dstFile) - compareFiles(original, dst, "move to new file") - - restoreSrcFile() - val subDst = dstFile.resolve("foo/bar") - assertFailsWith { srcFile.moveTo(subDst) } - assertFailsWith { srcFile.moveTo(subDst, overwrite = true) } - assertTrue(dstFile.deleteIfExists()) - assertFailsWith { srcFile.moveTo(subDst) } - - dstFile.createDirectory() - val child = dstFile.resolve("child").createFile() - assertFailsWith("move with overwrite do not overwrite non-empty dir") { - srcFile.moveTo(dstFile, overwrite = true) - } - child.deleteExisting() - - srcFile.moveTo(dstFile, overwrite = true) - compareFiles(original, dstFile, "move with overwrite over empty dir") - - assertTrue(srcFile.notExists()) - assertTrue(dstFile.deleteIfExists()) - - assertFailsWith { - srcFile.moveTo(dstFile) - } - - srcFile.createDirectory() - srcFile.resolve("somefile").writeText("some content") - dstFile.writeText("") - assertFailsWith("move dir do not overwrite file") { - srcFile.moveTo(dstFile) - } - srcFile.moveTo(dstFile, overwrite = true) - assertTrue(dstFile.isDirectory()) - assertEquals(listOf(dstFile / "somefile"), dstFile.listDirectoryEntries(), "directory is moved with its content") - } finally { - srcFile.toFile().deleteRecursively() - dstFile.toFile().deleteRecursively() + assertFailsWith("do not overwrite existing file") { + srcFile.moveTo(dstFile) } + + var dst = srcFile.moveTo(dstFile, overwrite = true) + assertSame(dst, dstFile) + compareFiles(original, dst, "move with overwrite over existing file") + assertTrue(srcFile.notExists()) + + restoreSrcFile() + srcFile.moveTo(srcFile) + srcFile.moveTo(srcFile, overwrite = true) + + compareFiles(original, srcFile, "move file to itself leaves it intact") + + assertTrue(dstFile.deleteIfExists()) + dst = srcFile.moveTo(dstFile) + compareFiles(original, dst, "move to new file") + + restoreSrcFile() + val subDst = dstFile.resolve("foo/bar") + assertFailsWith { srcFile.moveTo(subDst) } + assertFailsWith { srcFile.moveTo(subDst, overwrite = true) } + assertTrue(dstFile.deleteIfExists()) + assertFailsWith { srcFile.moveTo(subDst) } + + dstFile.createDirectory() + val child = dstFile.resolve("child").createFile() + assertFailsWith("move with overwrite do not overwrite non-empty dir") { + srcFile.moveTo(dstFile, overwrite = true) + } + child.deleteExisting() + + srcFile.moveTo(dstFile, overwrite = true) + compareFiles(original, dstFile, "move with overwrite over empty dir") + + assertTrue(srcFile.notExists()) + assertTrue(dstFile.deleteIfExists()) + + assertFailsWith { + srcFile.moveTo(dstFile) + } + + srcFile.createDirectory() + srcFile.resolve("somefile").writeText("some content") + dstFile.writeText("") + assertFailsWith("move dir do not overwrite file") { + srcFile.moveTo(dstFile) + } + srcFile.moveTo(dstFile, overwrite = true) + assertTrue(dstFile.isDirectory()) + assertEquals(listOf(dstFile / "somefile"), dstFile.listDirectoryEntries(), "directory is moved with its content") } private fun compareFiles(src: Path, dst: Path, message: String? = null) { @@ -231,7 +220,7 @@ class PathExtensionsTest { @Test fun fileSize() { - val file = createTempFile() + val file = createTempFile().cleanup() assertEquals(0, file.fileSize()) file.writeBytes(ByteArray(100)) @@ -246,29 +235,29 @@ class PathExtensionsTest { @Test fun deleteExisting() { - val file = createTempFile() + val file = createTempFile().cleanup() file.deleteExisting() assertFailsWith { file.deleteExisting() } - val dir = createTempDirectory() + val dir = createTempDirectory().cleanup() dir.deleteExisting() assertFailsWith { dir.deleteExisting() } } @Test fun deleteIfExists() { - val file = createTempFile() + val file = createTempFile().cleanup() assertTrue(file.deleteIfExists()) assertFalse(file.deleteIfExists()) - val dir = createTempDirectory() + val dir = createTempDirectory().cleanup() assertTrue(dir.deleteIfExists()) assertFalse(dir.deleteIfExists()) } @Test fun attributeGettersOnFile() { - val file = createTempFile("temp", ".file") + val file = createTempFile("temp", ".file").cleanup() assertTrue(file.exists()) assertFalse(file.notExists()) assertTrue(file.isRegularFile()) @@ -282,12 +271,11 @@ class PathExtensionsTest { // they don't throw an exception. file.isExecutable() file.isHidden() - file.deleteExisting() } @Test fun attributeGettersOnDirectory() { - val file = createTempDirectory(".tmpdir") + val file = createTempDirectory(".tmpdir").cleanup() assertTrue(file.exists()) assertFalse(file.notExists()) assertFalse(file.isRegularFile()) @@ -299,12 +287,11 @@ class PathExtensionsTest { file.isExecutable() file.isHidden() - file.deleteExisting() } @Test fun attributeGettersOnNonExistentPath() { - val file = createTempDirectory().resolve("foo") + val file = createTempDirectory().cleanup().resolve("foo") assertFalse(file.exists()) assertTrue(file.notExists()) assertFalse(file.isRegularFile()) @@ -321,7 +308,6 @@ class PathExtensionsTest { assertFalse(file.isHidden()) } catch (e: IOException) { } - file.parent.deleteExisting() } private interface SpecialFileAttributesView : FileAttributeView @@ -329,7 +315,7 @@ class PathExtensionsTest { @Test fun readWriteAttributes() { - val file = createTempFile() + val file = createTempFile().cleanup() val modifiedTime = file.getLastModifiedTime() assertEquals(modifiedTime, file.getAttribute("lastModifiedTime")) assertEquals(modifiedTime, file.getAttribute("basic:lastModifiedTime")) @@ -358,13 +344,11 @@ class PathExtensionsTest { file.setAttribute("lastModifiedTime", null) assertEquals(newTime3, file.getLastModifiedTime()) - - file.deleteExisting() } @Test fun links() { - val dir = createTempDirectory() + val dir = createTempDirectory().cleanupRecursively() val original = createTempFile(dir) original.writeBytes(Random.nextBytes(100)) @@ -385,7 +369,7 @@ class PathExtensionsTest { @Test fun symlinks() { - val dir = createTempDirectory() + val dir = createTempDirectory().cleanupRecursively() val original = createTempFile(dir) original.writeBytes(Random.nextBytes(100)) @@ -406,7 +390,7 @@ class PathExtensionsTest { @Test fun directoryEntriesList() { - val dir = createTempDirectory() + val dir = createTempDirectory().cleanupRecursively() assertEquals(0, dir.listDirectoryEntries().size) val file = dir.resolve("f1").createFile() @@ -420,7 +404,7 @@ class PathExtensionsTest { @Test fun directoryEntriesUseSequence() { - val dir = createTempDirectory() + val dir = createTempDirectory().cleanupRecursively() assertEquals(0, dir.useDirectoryEntries { it.toList() }.size) val file = dir.resolve("f1").createFile() @@ -434,7 +418,7 @@ class PathExtensionsTest { @Test fun directoryEntriesForEach() { - val dir = createTempDirectory() + val dir = createTempDirectory().cleanupRecursively() dir.forEachDirectoryEntry { error("shouldn't get here, but received $it") } val file = createTempFile(dir) diff --git a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt index f59f1969a6f..d014c86c15d 100644 --- a/libraries/stdlib/jdk7/test/PathReadWriteTest.kt +++ b/libraries/stdlib/jdk7/test/PathReadWriteTest.kt @@ -5,28 +5,26 @@ package kotlin.jdk7.test -import java.nio.file.Files import java.nio.file.StandardOpenOption import kotlin.io.path.* import kotlin.random.Random import kotlin.test.* -class PathReadWriteTest { +class PathReadWriteTest : AbstractPathTest() { @Test fun appendText() { - val file = createTempFile() + val file = createTempFile().cleanup() file.writeText("Hello\n") file.appendText("World\n") file.writeText("Again", Charsets.US_ASCII, StandardOpenOption.APPEND) assertEquals("Hello\nWorld\nAgain", file.readText()) assertEquals(listOf("Hello", "World", "Again"), file.readLines(Charsets.UTF_8)) - file.deleteExisting() } @Test fun file() { - val file = createTempFile() + val file = createTempFile().cleanup() val writer = file.outputStream().writer().buffered() writer.write("Hello") @@ -68,13 +66,11 @@ class PathReadWriteTest { c = 0 file.forEachLine { c++ } assertEquals(2, c) - - file.toFile().deleteOnExit() } @Test fun bufferedReader() { - val file = createTempFile() + val file = createTempFile().cleanup() val lines = listOf("line1", "line2") file.writeLines(lines) @@ -84,7 +80,7 @@ class PathReadWriteTest { @Test fun bufferedWriter() { - val file = createTempFile() + val file = createTempFile().cleanup() file.bufferedWriter().use { it.write("line1\n") } file.bufferedWriter(Charsets.UTF_8, 1024, StandardOpenOption.APPEND).use { it.write("line2\n") } @@ -94,7 +90,7 @@ class PathReadWriteTest { @Test fun writeBytes() { - val file = createTempFile() + val file = createTempFile().cleanup() file.writeBytes("Hello".encodeToByteArray()) file.appendBytes(" world!".encodeToByteArray()) assertEquals(file.readText(), "Hello world!") @@ -107,7 +103,7 @@ class PathReadWriteTest { @Test fun writeLines() { - val file = createTempFile() + val file = createTempFile().cleanup() val lines = listOf("first line", "second line") file.writeLines(lines) assertEquals(lines, file.readLines()) From 995b1aa1ebe7eb7897719482518ee09966acd633 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 7 Oct 2020 16:23:21 +0300 Subject: [PATCH 031/554] FIR: Add FirCallableMemberDeclaration::dispatchReceiverType --- .../kotlin/fir/declarations/FirCallableMemberDeclaration.kt | 2 ++ .../org/jetbrains/kotlin/fir/declarations/FirConstructor.kt | 2 ++ .../org/jetbrains/kotlin/fir/declarations/FirEnumEntry.kt | 2 ++ .../gen/org/jetbrains/kotlin/fir/declarations/FirField.kt | 2 ++ .../org/jetbrains/kotlin/fir/declarations/FirProperty.kt | 2 ++ .../kotlin/fir/declarations/FirPropertyAccessor.kt | 2 ++ .../jetbrains/kotlin/fir/declarations/FirSimpleFunction.kt | 2 ++ .../declarations/builder/FirAbstractConstructorBuilder.kt | 2 ++ .../fir/declarations/builder/FirConstructorBuilder.kt | 3 +++ .../kotlin/fir/declarations/builder/FirEnumEntryBuilder.kt | 3 +++ .../kotlin/fir/declarations/builder/FirFieldBuilder.kt | 3 +++ .../declarations/builder/FirPrimaryConstructorBuilder.kt | 3 +++ .../fir/declarations/builder/FirPropertyAccessorBuilder.kt | 4 ++++ .../kotlin/fir/declarations/builder/FirPropertyBuilder.kt | 4 ++++ .../fir/declarations/builder/FirSimpleFunctionBuilder.kt | 4 ++++ .../kotlin/fir/declarations/impl/FirConstructorImpl.kt | 2 ++ .../kotlin/fir/declarations/impl/FirEnumEntryImpl.kt | 2 ++ .../jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt | 2 ++ .../kotlin/fir/declarations/impl/FirPrimaryConstructor.kt | 2 ++ .../kotlin/fir/declarations/impl/FirPropertyAccessorImpl.kt | 2 ++ .../kotlin/fir/declarations/impl/FirPropertyImpl.kt | 2 ++ .../kotlin/fir/declarations/impl/FirSimpleFunctionImpl.kt | 2 ++ .../fir/declarations/impl/FirDefaultPropertyAccessor.kt | 3 ++- .../fir/declarations/synthetic/FirSyntheticProperty.kt | 6 +++++- .../declarations/synthetic/FirSyntheticPropertyAccessor.kt | 4 ++++ .../jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt | 1 + 26 files changed, 66 insertions(+), 2 deletions(-) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirCallableMemberDeclaration.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirCallableMemberDeclaration.kt index c1dc9ebb7c9..a2f51cbd82b 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirCallableMemberDeclaration.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirCallableMemberDeclaration.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.fir.visitors.* @@ -31,6 +32,7 @@ interface FirCallableMemberDeclaration> : Fi override val typeParameters: List override val status: FirDeclarationStatus val containerSource: DeserializedContainerSource? + val dispatchReceiverType: ConeKotlinType? override fun accept(visitor: FirVisitor, data: D): R = visitor.visitCallableMemberDeclaration(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirConstructor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirConstructor.kt index ef918088b7d..d28a5fed3f3 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirConstructor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirConstructor.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.fir.visitors.* @@ -35,6 +36,7 @@ abstract class FirConstructor : FirPureAbstractElement(), FirFunction abstract override val status: FirDeclarationStatus abstract override val containerSource: DeserializedContainerSource? + abstract override val dispatchReceiverType: ConeKotlinType? abstract override val annotations: List abstract override val symbol: FirConstructorSymbol abstract val delegatedConstructor: FirDelegatedConstructorCall? diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirEnumEntry.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirEnumEntry.kt index c90a4dc95ac..eb8f5cc8c5f 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirEnumEntry.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirEnumEntry.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -42,6 +43,7 @@ abstract class FirEnumEntry : FirVariable(), FirCallableMemberDecl abstract override val typeParameters: List abstract override val status: FirDeclarationStatus abstract override val containerSource: DeserializedContainerSource? + abstract override val dispatchReceiverType: ConeKotlinType? override fun accept(visitor: FirVisitor, data: D): R = visitor.visitEnumEntry(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirField.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirField.kt index 991542c898d..8fc02aa2cf3 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirField.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirField.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -42,6 +43,7 @@ abstract class FirField : FirVariable(), FirTypeParametersOwner, FirCa abstract override val typeParameters: List abstract override val status: FirDeclarationStatus abstract override val containerSource: DeserializedContainerSource? + abstract override val dispatchReceiverType: ConeKotlinType? override fun accept(visitor: FirVisitor, data: D): R = visitor.visitField(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirProperty.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirProperty.kt index 1e339d96b55..05e024e3a86 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirProperty.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirProperty.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -43,6 +44,7 @@ abstract class FirProperty : FirVariable(), FirTypeParametersOwner, abstract override val typeParameters: List abstract override val controlFlowGraphReference: FirControlFlowGraphReference? abstract override val containerSource: DeserializedContainerSource? + abstract override val dispatchReceiverType: ConeKotlinType? abstract override val symbol: FirPropertySymbol abstract val backingFieldSymbol: FirBackingFieldSymbol abstract val isLocal: Boolean diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirPropertyAccessor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirPropertyAccessor.kt index d298bf54368..4fd2da4e163 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirPropertyAccessor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirPropertyAccessor.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.fir.visitors.* @@ -35,6 +36,7 @@ abstract class FirPropertyAccessor : FirPureAbstractElement(), FirFunction diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAbstractConstructorBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAbstractConstructorBuilder.kt index 615fc1b3ae6..1760228750f 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAbstractConstructorBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAbstractConstructorBuilder.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -46,6 +47,7 @@ interface FirAbstractConstructorBuilder : FirFunctionBuilder { abstract var controlFlowGraphReference: FirControlFlowGraphReference? abstract var status: FirDeclarationStatus abstract var containerSource: DeserializedContainerSource? + abstract var dispatchReceiverType: ConeKotlinType? abstract var symbol: FirConstructorSymbol abstract var delegatedConstructor: FirDelegatedConstructorCall? override fun build(): FirConstructor diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt index ccb3d34716d..aefc4f1397b 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -46,6 +47,7 @@ open class FirConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotationC override val valueParameters: MutableList = mutableListOf() override lateinit var status: FirDeclarationStatus override var containerSource: DeserializedContainerSource? = null + override var dispatchReceiverType: ConeKotlinType? = null override val annotations: MutableList = mutableListOf() override lateinit var symbol: FirConstructorSymbol override var delegatedConstructor: FirDelegatedConstructorCall? = null @@ -64,6 +66,7 @@ open class FirConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotationC valueParameters, status, containerSource, + dispatchReceiverType, annotations, symbol, delegatedConstructor, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirEnumEntryBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirEnumEntryBuilder.kt index 5da7b892d03..f3a52a76cf2 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirEnumEntryBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirEnumEntryBuilder.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name @@ -47,6 +48,7 @@ class FirEnumEntryBuilder : FirAnnotationContainerBuilder { val typeParameters: MutableList = mutableListOf() lateinit var status: FirDeclarationStatus var containerSource: DeserializedContainerSource? = null + var dispatchReceiverType: ConeKotlinType? = null override fun build(): FirEnumEntry { return FirEnumEntryImpl( @@ -63,6 +65,7 @@ class FirEnumEntryBuilder : FirAnnotationContainerBuilder { typeParameters, status, containerSource, + dispatchReceiverType, ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt index 647a90ca479..bb7132a48e6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name @@ -47,6 +48,7 @@ open class FirFieldBuilder : FirAnnotationContainerBuilder { open val typeParameters: MutableList = mutableListOf() open lateinit var status: FirDeclarationStatus open var containerSource: DeserializedContainerSource? = null + open var dispatchReceiverType: ConeKotlinType? = null override fun build(): FirField { return FirFieldImpl( @@ -63,6 +65,7 @@ open class FirFieldBuilder : FirAnnotationContainerBuilder { typeParameters, status, containerSource, + dispatchReceiverType, ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPrimaryConstructorBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPrimaryConstructorBuilder.kt index 62c8a88c7a4..5ad8596fd15 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPrimaryConstructorBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPrimaryConstructorBuilder.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -46,6 +47,7 @@ class FirPrimaryConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotatio override val valueParameters: MutableList = mutableListOf() override lateinit var status: FirDeclarationStatus override var containerSource: DeserializedContainerSource? = null + override var dispatchReceiverType: ConeKotlinType? = null override val annotations: MutableList = mutableListOf() override lateinit var symbol: FirConstructorSymbol override var delegatedConstructor: FirDelegatedConstructorCall? = null @@ -64,6 +66,7 @@ class FirPrimaryConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotatio valueParameters, status, containerSource, + dispatchReceiverType, annotations, symbol, delegatedConstructor, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyAccessorBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyAccessorBuilder.kt index 8bcb8d90f05..d774420c18c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyAccessorBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyAccessorBuilder.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -48,6 +49,7 @@ class FirPropertyAccessorBuilder : FirFunctionBuilder, FirAnnotationContainerBui override var body: FirBlock? = null lateinit var status: FirDeclarationStatus var containerSource: DeserializedContainerSource? = null + var dispatchReceiverType: ConeKotlinType? = null var contractDescription: FirContractDescription = FirEmptyContractDescription lateinit var symbol: FirPropertyAccessorSymbol var isGetter: Boolean by kotlin.properties.Delegates.notNull() @@ -67,6 +69,7 @@ class FirPropertyAccessorBuilder : FirFunctionBuilder, FirAnnotationContainerBui body, status, containerSource, + dispatchReceiverType, contractDescription, symbol, isGetter, @@ -101,6 +104,7 @@ inline fun buildPropertyAccessorCopy(original: FirPropertyAccessor, init: FirPro copyBuilder.body = original.body copyBuilder.status = original.status copyBuilder.containerSource = original.containerSource + copyBuilder.dispatchReceiverType = original.dispatchReceiverType copyBuilder.contractDescription = original.contractDescription copyBuilder.symbol = original.symbol copyBuilder.isGetter = original.isGetter diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyBuilder.kt index a32c2fd2841..b8bebc811fe 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirPropertyBuilder.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name @@ -54,6 +55,7 @@ class FirPropertyBuilder : FirTypeParametersOwnerBuilder, FirAnnotationContainer override val annotations: MutableList = mutableListOf() override val typeParameters: MutableList = mutableListOf() var containerSource: DeserializedContainerSource? = null + var dispatchReceiverType: ConeKotlinType? = null lateinit var symbol: FirPropertySymbol var isLocal: Boolean by kotlin.properties.Delegates.notNull() lateinit var status: FirDeclarationStatus @@ -77,6 +79,7 @@ class FirPropertyBuilder : FirTypeParametersOwnerBuilder, FirAnnotationContainer annotations, typeParameters, containerSource, + dispatchReceiverType, symbol, isLocal, status, @@ -116,6 +119,7 @@ inline fun buildPropertyCopy(original: FirProperty, init: FirPropertyBuilder.() copyBuilder.annotations.addAll(original.annotations) copyBuilder.typeParameters.addAll(original.typeParameters) copyBuilder.containerSource = original.containerSource + copyBuilder.dispatchReceiverType = original.dispatchReceiverType copyBuilder.symbol = original.symbol copyBuilder.isLocal = original.isLocal copyBuilder.status = original.status diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirSimpleFunctionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirSimpleFunctionBuilder.kt index 955bde403f2..7d3a094c72d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirSimpleFunctionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirSimpleFunctionBuilder.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name @@ -50,6 +51,7 @@ open class FirSimpleFunctionBuilder : FirFunctionBuilder, FirTypeParametersOwner override var body: FirBlock? = null open lateinit var status: FirDeclarationStatus open var containerSource: DeserializedContainerSource? = null + open var dispatchReceiverType: ConeKotlinType? = null open var contractDescription: FirContractDescription = FirEmptyContractDescription open lateinit var name: Name open lateinit var symbol: FirFunctionSymbol @@ -70,6 +72,7 @@ open class FirSimpleFunctionBuilder : FirFunctionBuilder, FirTypeParametersOwner body, status, containerSource, + dispatchReceiverType, contractDescription, name, symbol, @@ -105,6 +108,7 @@ inline fun buildSimpleFunctionCopy(original: FirSimpleFunction, init: FirSimpleF copyBuilder.body = original.body copyBuilder.status = original.status copyBuilder.containerSource = original.containerSource + copyBuilder.dispatchReceiverType = original.dispatchReceiverType copyBuilder.contractDescription = original.contractDescription copyBuilder.name = original.name copyBuilder.symbol = original.symbol diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirConstructorImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirConstructorImpl.kt index 0bae5a016c1..63bd1d946c7 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirConstructorImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirConstructorImpl.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.fir.visitors.* @@ -40,6 +41,7 @@ internal class FirConstructorImpl( override val valueParameters: MutableList, override var status: FirDeclarationStatus, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, override val annotations: MutableList, override val symbol: FirConstructorSymbol, override var delegatedConstructor: FirDelegatedConstructorCall?, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt index feef07e1aea..e2c9a19c9a1 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirEnumEntryImpl.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -42,6 +43,7 @@ internal class FirEnumEntryImpl( override val typeParameters: MutableList, override var status: FirDeclarationStatus, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, ) : FirEnumEntry() { override val receiverTypeRef: FirTypeRef? get() = null override val delegate: FirExpression? get() = null diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt index 5e515ff69fe..8708335687c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -42,6 +43,7 @@ internal class FirFieldImpl( override val typeParameters: MutableList, override var status: FirDeclarationStatus, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, ) : FirField() { override val receiverTypeRef: FirTypeRef? get() = null override val initializer: FirExpression? get() = null diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPrimaryConstructor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPrimaryConstructor.kt index 116edabe5ac..268d596c66a 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPrimaryConstructor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPrimaryConstructor.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.fir.visitors.* @@ -40,6 +41,7 @@ internal class FirPrimaryConstructor( override val valueParameters: MutableList, override var status: FirDeclarationStatus, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, override val annotations: MutableList, override val symbol: FirConstructorSymbol, override var delegatedConstructor: FirDelegatedConstructorCall?, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyAccessorImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyAccessorImpl.kt index f73c394679b..808c6698755 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyAccessorImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyAccessorImpl.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.fir.visitors.* @@ -41,6 +42,7 @@ open class FirPropertyAccessorImpl @FirImplementationDetail constructor( override var body: FirBlock?, override var status: FirDeclarationStatus, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, override var contractDescription: FirContractDescription, override val symbol: FirPropertyAccessorSymbol, override val isGetter: Boolean, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyImpl.kt index a7fef8d744e..7f8849fb8f0 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirPropertyImpl.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -48,6 +49,7 @@ internal class FirPropertyImpl( override val annotations: MutableList, override val typeParameters: MutableList, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, override val symbol: FirPropertySymbol, override val isLocal: Boolean, override var status: FirDeclarationStatus, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirSimpleFunctionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirSimpleFunctionImpl.kt index b50aebe187c..436d7a0fb7d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirSimpleFunctionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirSimpleFunctionImpl.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -42,6 +43,7 @@ open class FirSimpleFunctionImpl @FirImplementationDetail constructor( override var body: FirBlock?, override var status: FirDeclarationStatus, override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeKotlinType?, override var contractDescription: FirContractDescription, override val name: Name, override val symbol: FirFunctionSymbol, diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDefaultPropertyAccessor.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDefaultPropertyAccessor.kt index cf6bdf729a7..fc1d8f5d69a 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDefaultPropertyAccessor.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDefaultPropertyAccessor.kt @@ -6,10 +6,10 @@ package org.jetbrains.kotlin.fir.declarations.impl import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin @@ -46,6 +46,7 @@ abstract class FirDefaultPropertyAccessor( body = null, FirDeclarationStatusImpl(visibility, Modality.FINAL), containerSource = null, + dispatchReceiverType = null, contractDescription = FirEmptyContractDescription, symbol, isGetter, diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt index 39071d28e9c..d6adcd91ade 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirAccessorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -37,6 +38,9 @@ class FirSyntheticProperty( override val returnTypeRef: FirTypeRef get() = getter.returnTypeRef + override val dispatchReceiverType: ConeKotlinType? + get() = getter.dispatchReceiverType + override val source: FirSourceElement? get() = null @@ -145,4 +149,4 @@ class FirSyntheticProperty( override fun replaceInitializer(newInitializer: FirExpression?) { throw AssertionError("Mutation of synthetic property isn't supported") } -} \ No newline at end of file +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt index 60382c17c45..ca23b2b789e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -42,6 +43,9 @@ class FirSyntheticPropertyAccessor( override val status: FirDeclarationStatus get() = delegate.status + override val dispatchReceiverType: ConeKotlinType? + get() = delegate.dispatchReceiverType + override val receiverTypeRef: FirTypeRef? get() = null diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 786c1d5ebb3..8cfbf259578 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -95,6 +95,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild withArg("F", "FirCallableMemberDeclaration") parentArg(callableDeclaration, "F", "F") +field("containerSource", type(DeserializedContainerSource::class), nullable = true) + +field("dispatchReceiverType", coneKotlinTypeType, nullable = true) } function.configure { From 52c6aebec27e2e3caf841c4c3c0182fe93402710 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 9 Oct 2020 10:39:00 +0300 Subject: [PATCH 032/554] FIR: Use copy-builders at FirObjectImportedCallableScope --- .../impl/FirObjectImportedCallableScope.kt | 31 +++---------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt index 090981949c0..b0143c4f190 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin -import org.jetbrains.kotlin.fir.declarations.builder.buildProperty -import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction +import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy +import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope @@ -30,19 +30,9 @@ class FirObjectImportedCallableScope( return@wrapper } val function = symbol.fir - val syntheticFunction = buildSimpleFunction { - source = function.source - session = function.session + val syntheticFunction = buildSimpleFunctionCopy(function) { origin = FirDeclarationOrigin.ImportedFromObject - returnTypeRef = function.returnTypeRef - receiverTypeRef = function.receiverTypeRef - this.name = function.name - status = function.status this.symbol = FirNamedFunctionSymbol(CallableId(importedClassId, name), overriddenSymbol = symbol) - resolvePhase = function.resolvePhase - typeParameters.addAll(function.typeParameters) - valueParameters.addAll(function.valueParameters) - annotations.addAll(function.annotations) } processor(syntheticFunction.symbol) } @@ -55,20 +45,9 @@ class FirObjectImportedCallableScope( return@wrapper } val property = symbol.fir - val syntheticFunction = buildProperty { - source = property.source - session = property.session + val syntheticFunction = buildPropertyCopy(property) { origin = FirDeclarationOrigin.ImportedFromObject - returnTypeRef = property.returnTypeRef - receiverTypeRef = property.receiverTypeRef - this.name = property.name - status = property.status - isVar = property.isVar - isLocal = property.isLocal this.symbol = FirPropertySymbol(CallableId(importedClassId, name), overriddenSymbol = symbol) - resolvePhase = property.resolvePhase - typeParameters.addAll(property.typeParameters) - annotations.addAll(property.annotations) } processor(syntheticFunction.symbol) } @@ -77,4 +56,4 @@ class FirObjectImportedCallableScope( override fun getCallableNames(): Set = objectUseSiteScope.getCallableNames() override fun getClassifierNames(): Set = emptySet() -} \ No newline at end of file +} From ecb89a66be25310c86835ee621e33755f403e52d Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 23 Oct 2020 12:10:18 +0300 Subject: [PATCH 033/554] FIR: Copy `attributes` when copying declaration Otherwise they share FirDeclarationAttributes instance that might lead to problems when modifying only one of them --- .../org/jetbrains/kotlin/fir/utils/ArrayMap.kt | 18 +++++++++++++++--- .../kotlin/fir/utils/AttributeArrayOwner.kt | 12 ++++++++---- .../builder/FirConstructorBuilder.kt | 2 +- .../builder/FirPropertyAccessorBuilder.kt | 2 +- .../declarations/builder/FirPropertyBuilder.kt | 2 +- .../builder/FirSimpleFunctionBuilder.kt | 2 +- .../builder/FirValueParameterBuilder.kt | 2 +- .../declarations/FirDeclarationAttributes.kt | 8 +++++++- .../fir/tree/generator/printer/builder.kt | 8 +++++--- 9 files changed, 40 insertions(+), 16 deletions(-) diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/ArrayMap.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/ArrayMap.kt index 6d2070d5b61..a66f9366b01 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/ArrayMap.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/ArrayMap.kt @@ -10,6 +10,8 @@ sealed class ArrayMap : Iterable { abstract operator fun set(index: Int, value: T) abstract operator fun get(index: Int): T? + + abstract fun copy(): ArrayMap } fun ArrayMap<*>.isEmpty(): Boolean = size == 0 @@ -27,6 +29,8 @@ internal object EmptyArrayMap : ArrayMap() { return null } + override fun copy(): ArrayMap = this + override fun iterator(): Iterator { return object : Iterator { override fun hasNext(): Boolean = false @@ -48,6 +52,8 @@ internal class OneElementArrayMap(val value: T, val index: Int) : Array return if (index == this.index) value else null } + override fun copy(): ArrayMap = OneElementArrayMap(value, index) + override fun iterator(): Iterator { return object : Iterator { private var notVisited = true @@ -68,16 +74,20 @@ internal class OneElementArrayMap(val value: T, val index: Int) : Array } } -internal class ArrayMapImpl : ArrayMap() { +internal class ArrayMapImpl private constructor( + private var data: Array +) : ArrayMap() { companion object { private const val DEFAULT_SIZE = 20 private const val INCREASE_K = 2 } + constructor() : this(arrayOfNulls(DEFAULT_SIZE)) + override var size: Int = 0 private set - private var data = arrayOfNulls(DEFAULT_SIZE) + private fun ensureCapacity(index: Int) { if (data.size <= index) { data = data.copyOf(data.size * INCREASE_K) @@ -97,6 +107,8 @@ internal class ArrayMapImpl : ArrayMap() { return data.getOrNull(index) as T? } + override fun copy(): ArrayMap = ArrayMapImpl(data.copyOf()) + override fun iterator(): Iterator { return object : AbstractIterator() { private var index = -1 @@ -128,4 +140,4 @@ internal class ArrayMapImpl : ArrayMap() { } data class Entry(override val key: Int, override val value: T) : Map.Entry -} \ No newline at end of file +} diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/AttributeArrayOwner.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/AttributeArrayOwner.kt index 1d5b2360fd8..a7bee7edba9 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/AttributeArrayOwner.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/utils/AttributeArrayOwner.kt @@ -17,11 +17,15 @@ import kotlin.reflect.KClass * from components in [ComponentArrayOwner] */ @OptIn(Protected::class) -abstract class AttributeArrayOwner : AbstractArrayMapOwner() { - @Suppress("UNCHECKED_CAST") - final override var arrayMap: ArrayMap = EmptyArrayMap as ArrayMap +abstract class AttributeArrayOwner protected constructor( + arrayMap: ArrayMap +) : AbstractArrayMapOwner() { + final override var arrayMap: ArrayMap = arrayMap private set + @Suppress("UNCHECKED_CAST") + constructor() : this(EmptyArrayMap as ArrayMap) + final override fun registerComponent(tClass: KClass, value: T) { val id = typeRegistry.getId(tClass) when (arrayMap.size) { @@ -61,4 +65,4 @@ abstract class AttributeArrayOwner : AbstractArrayMapOwner() { +class FirDeclarationAttributes : AttributeArrayOwner { override val typeRegistry: TypeRegistry get() = FirDeclarationDataRegistry + constructor() : super() + private constructor(arrayMap: ArrayMap) : super(arrayMap) + internal operator fun set(key: KClass, value: Any?) { if (value == null) { removeComponent(key) @@ -25,6 +29,8 @@ class FirDeclarationAttributes : AttributeArrayOwner registerComponent(key, value) } } + + fun copy(): FirDeclarationAttributes = FirDeclarationAttributes(arrayMap.copy()) } /* diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt index e6050cb2df8..25bd5c33832 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.tree.generator.printer +import org.jetbrains.kotlin.fir.tree.generator.declarationAttributesType import org.jetbrains.kotlin.fir.tree.generator.model.* import java.io.File @@ -294,12 +295,13 @@ private fun SmartPrinter.printDslBuildCopyFunction( println("}") println("val copyBuilder = $builderType()") for (field in builder.allFields) { - when (field.origin) { - is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})") + when { + field.origin is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})") + field.type == declarationAttributesType.type -> println("copyBuilder.${field.name} = original.${field.name}.copy()") else -> println("copyBuilder.${field.name} = original.${field.name}") } } println("return copyBuilder.apply(init).build()") } println("}") -} \ No newline at end of file +} From 9996c983c905e2f1f48d11f384fa0baf511c440c Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 23 Oct 2020 12:16:51 +0300 Subject: [PATCH 034/554] FIR: Initialize dispatchReceiverType and containingClassAttr for callable members --- .../deserialization/ClassDeserialization.kt | 14 ++++-- .../deserialization/FirMemberDeserializer.kt | 8 ++++ .../impl/FirBuiltinSymbolProvider.kt | 2 + .../fir/backend/jvm/FirMetadataSerializer.kt | 11 +++-- .../generators/DataClassMembersGenerator.kt | 10 +++- .../generators/FakeOverrideGenerator.kt | 6 ++- .../kotlin/fir/java/JavaScopeProvider.kt | 4 +- .../kotlin/fir/java/JavaSymbolProvider.kt | 47 ++++++++++++++++--- .../java/declarations/FirJavaConstructor.kt | 7 ++- .../fir/java/declarations/FirJavaField.kt | 9 ++-- .../fir/java/declarations/FirJavaMethod.kt | 6 ++- .../java/enhancement/SignatureEnhancement.kt | 12 ++++- .../JavaClassMembersEnhancementScope.kt | 3 +- .../fir/resolve/scopes/JvmMappedScopes.kt | 5 +- .../converter/DeclarationsConverter.kt | 24 ++++++++-- .../kotlin/fir/builder/RawFirBuilder.kt | 23 +++++++-- .../kotlin/fir/builder/BaseFirBuilder.kt | 19 +++++++- .../jetbrains/kotlin/fir/builder/Context.kt | 8 +++- .../kotlin/fir/resolve/SamResolution.kt | 4 ++ .../kotlin/fir/resolve/ScopeUtils.kt | 25 +++++++++- .../kotlin/fir/resolve/SupertypeUtils.kt | 6 +-- .../resolve/calls/ConstructorProcessing.kt | 8 +++- .../impl/FirCloneableSymbolProvider.kt | 5 +- .../FirAbstractBodyResolveTransformer.kt | 3 +- .../kotlin/fir/scopes/KotlinScopeProvider.kt | 19 ++++---- .../scopes/impl/FirClassSubstitutionScope.kt | 20 ++++---- .../scopes/impl/FirDelegatedMemberScope.kt | 12 +++-- .../scopes/impl/FirFakeOverrideGenerator.kt | 38 +++++++++++---- .../scopes/impl/FirTypeIntersectionScope.kt | 21 +++++---- .../builder/FirConstructorBuilder.kt | 1 + .../org/jetbrains/kotlin/fir/ClassMembers.kt | 33 +++++++++++++ .../jetbrains/kotlin/fir/EnumClassUtils.kt | 4 ++ 32 files changed, 334 insertions(+), 83 deletions(-) create mode 100644 compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 197b278b588..da46bd7f3a5 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.ConeAttributes +import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl @@ -161,6 +162,8 @@ fun deserializeClassToSymbol( isStatic = true } resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + }.apply { + containingClassAttr = context.dispatchReceiver!!.lookupTag } property @@ -168,11 +171,15 @@ fun deserializeClassToSymbol( ) if (classKind == ClassKind.ENUM_CLASS) { - generateValuesFunction(session, classId.packageFqName, classId.relativeClassName) + generateValuesFunction( + session, + classId.packageFqName, + classId.relativeClassName + ) generateValueOfFunction(session, classId.packageFqName, classId.relativeClassName) } - addCloneForArrayIfNeeded(classId) + addCloneForArrayIfNeeded(classId, context.dispatchReceiver) addSerializableIfNeeded(classId) declarations.sortWith(object : Comparator { @@ -224,7 +231,7 @@ private fun FirRegularClassBuilder.addSerializableIfNeeded(classId: ClassId) { } } -private fun FirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId) { +private fun FirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId, dispatchReceiver: ConeClassLikeType?) { if (classId.packageFqName != StandardNames.BUILT_INS_PACKAGE_FQ_NAME) return if (classId.shortClassName !in ARRAY_CLASSES) return superTypeRefs += buildResolvedTypeRef { @@ -259,5 +266,6 @@ private fun FirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId) { } name = CLONE symbol = FirNamedFunctionSymbol(CallableId(classId, CLONE)) + dispatchReceiverType = dispatchReceiver!! } } diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt index be140999d61..ac5d59a33cd 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt @@ -7,12 +7,14 @@ package org.jetbrains.kotlin.fir.deserialization import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.containingClassAttr import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.impl.* import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.* @@ -64,6 +66,7 @@ class FirDeserializationContext( ) val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this) + val dispatchReceiver = relativeClassName?.let { ClassId(packageFqName, it, false).defaultType(allTypeParameters) } companion object { fun createForPackage( @@ -225,6 +228,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(getterFlags) } this.symbol = FirPropertyAccessorSymbol() + dispatchReceiverType = c.dispatchReceiver }.apply { versionRequirementsTable = c.versionRequirementTable } @@ -256,6 +260,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(setterFlags) } this.symbol = FirPropertyAccessorSymbol() + dispatchReceiverType = c.dispatchReceiver valueParameters += local.memberDeserializer.valueParameters( listOf(proto.setterValueParameter), proto, @@ -288,6 +293,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { name = callableName this.isVar = isVar this.symbol = symbol + dispatchReceiverType = c.dispatchReceiver isLocal = false status = FirResolvedDeclarationStatusImpl( ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)), @@ -365,6 +371,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { isSuspend = Flags.IS_SUSPEND.get(flags) } this.symbol = symbol + dispatchReceiverType = c.dispatchReceiver resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir } valueParameters += local.memberDeserializer.valueParameters( @@ -443,6 +450,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { annotations += c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable) }.build().apply { + containingClassAttr = c.dispatchReceiver!!.lookupTag versionRequirementsTable = c.versionRequirementTable } } diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirBuiltinSymbolProvider.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirBuiltinSymbolProvider.kt index 1f92e9c3e8a..ec03ff32768 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirBuiltinSymbolProvider.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirBuiltinSymbolProvider.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider @@ -225,6 +226,7 @@ class FirBuiltinSymbolProvider(session: FirSession, val kotlinScopeProvider: Kot isVararg = false } } + dispatchReceiverType = classId.defaultType(typeParameters.map { it.symbol }) } ) } diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt index d615b5c7a50..0337a03af47 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt @@ -11,18 +11,21 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.* +import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction +import org.jetbrains.kotlin.fir.declarations.builder.buildProperty +import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessor +import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameterCopy import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic -import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.serialization.FirElementSerializer import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.MetadataSource -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.getPackageFragment import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.types.AbstractTypeApproximator @@ -128,6 +131,8 @@ class FirMetadataSerializer( isVar = property.isVar isLocal = property.isLocal status = property.status + dispatchReceiverType = property.dispatchReceiverType + attributes = property.attributes.copy() annotations += property.annotations typeParameters += typeParameterSet }.apply { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt index ac1e6109934..0a57abffb52 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DataClassMembersGenerator.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.fir.backend.generators import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter @@ -17,8 +16,11 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.ConeStarProjection +import org.jetbrains.kotlin.fir.types.constructType import org.jetbrains.kotlin.fir.types.impl.FirImplicitBooleanTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitIntTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef @@ -35,7 +37,6 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.descriptors.DescriptorVisibilities /** * A generator that generates synthetic members of data class as well as part of inline class. @@ -248,6 +249,11 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) { } ) } + dispatchReceiverType = + ConeClassLikeLookupTagImpl(classId) + .constructType( + (1..irClass.typeParameters.size).map { ConeStarProjection }.toTypedArray(), isNullable = false + ) } val signature = if (classId.isLocal) null else components.signatureComposer.composeSignature(firFunction) return components.declarationStorage.declareIrSimpleFunction(signature, null) { symbol -> diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index 1187a7a5820..4c8b81fadaf 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -10,13 +10,16 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -30,7 +33,6 @@ import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeProjection import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities -import org.jetbrains.kotlin.name.ClassId class FakeOverrideGenerator( private val session: FirSession, @@ -87,6 +89,7 @@ class FakeOverrideGenerator( createFakeOverrideSymbol = { firFunction, callableSymbol -> FirFakeOverrideGenerator.createFakeOverrideFunction( session, firFunction, callableSymbol, + newDispatchReceiverType = klass.defaultType(), derivedClassId = klass.symbol.classId, isExpect = (klass as? FirRegularClass)?.isExpect == true ) @@ -110,6 +113,7 @@ class FakeOverrideGenerator( createFakeOverrideSymbol = { firProperty, callableSymbol -> FirFakeOverrideGenerator.createFakeOverrideProperty( session, firProperty, callableSymbol, + newDispatchReceiverType = klass.defaultType(), derivedClassId = klass.symbol.classId, isExpect = (klass as? FirRegularClass)?.isExpect == true ) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt index 0cb17a5b9f1..671723f4fe6 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt @@ -96,7 +96,7 @@ class JavaScopeProvider( val scope = buildJavaEnhancementScope(useSiteSession, symbol, scopeSession, visitedSymbols) visitedSymbols.remove(symbol) useSiteSuperType.wrapSubstitutionScopeIfNeed( - useSiteSession, scope, symbol.fir, scopeSession, regularClass.classId + useSiteSession, scope, symbol.fir, scopeSession, derivedClass = regularClass ) } else { null @@ -112,7 +112,7 @@ class JavaScopeProvider( else JavaTypeParameterStack.EMPTY ), superTypeEnhancementScopes, - regularClass.classId, + regularClass.defaultType(), ), wrappedDeclaredScope ) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index d11f8581b78..16f8fd00103 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -19,12 +19,14 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.java.declarations.* import org.jetbrains.kotlin.fir.resolve.constructType +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals import org.jetbrains.kotlin.fir.resolve.providers.SymbolProviderCache import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl @@ -187,6 +189,9 @@ class JavaSymbolProvider( buildOuterClassTypeParameterRef { symbol = it.symbol } } } + + val dispatchReceiver = classId.defaultType(typeParameters.map { it.symbol } ) + status = FirResolvedDeclarationStatusImpl( javaClass.visibility, javaClass.modality @@ -200,7 +205,7 @@ class JavaSymbolProvider( // TODO: may be we can process fields & methods later. // However, they should be built up to override resolve stage for (javaField in javaClass.fields) { - declarations += convertJavaFieldToFir(javaField, classId, javaTypeParameterStack) + declarations += convertJavaFieldToFir(javaField, classId, javaTypeParameterStack, dispatchReceiver) } val valueParametersForAnnotationConstructor = ValueParametersForAnnotationConstructor() val classIsAnnotation = classKind == ClassKind.ANNOTATION_CLASS @@ -212,7 +217,8 @@ class JavaSymbolProvider( classId, javaTypeParameterStack, classIsAnnotation, - valueParametersForAnnotationConstructor + valueParametersForAnnotationConstructor, + dispatchReceiver ) } val javaClassDeclaredConstructors = javaClass.constructors @@ -243,11 +249,16 @@ class JavaSymbolProvider( } if (classKind == ClassKind.ENUM_CLASS) { - generateValuesFunction(session, classId.packageFqName, classId.relativeClassName) + generateValuesFunction( + session, + classId.packageFqName, + classId.relativeClassName + ) generateValueOfFunction(session, classId.packageFqName, classId.relativeClassName) } if (classIsAnnotation) { - declarations += buildConstructorForAnnotationClass(constructorId, this, valueParametersForAnnotationConstructor) + declarations += + buildConstructorForAnnotationClass(constructorId, this, valueParametersForAnnotationConstructor) } parentClassTypeParameterStackCache.remove(classSymbol) } @@ -265,7 +276,8 @@ class JavaSymbolProvider( private fun convertJavaFieldToFir( javaField: JavaField, classId: ClassId, - javaTypeParameterStack: JavaTypeParameterStack + javaTypeParameterStack: JavaTypeParameterStack, + dispatchReceiver: ConeClassLikeType ): FirDeclaration { val fieldName = javaField.name val fieldId = CallableId(classId.packageFqName, classId.relativeClassName, fieldName) @@ -289,6 +301,8 @@ class JavaSymbolProvider( resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES origin = FirDeclarationOrigin.Java addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack) + }.apply { + containingClassAttr = ConeClassLikeLookupTagImpl(classId) } else -> buildJavaField { source = (javaField as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement() @@ -311,6 +325,14 @@ class JavaSymbolProvider( isStatic = javaField.isStatic addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack) initializer = convertJavaInitializerToFir(javaField.initializerValue) + + if (!javaField.isStatic) { + dispatchReceiverType = dispatchReceiver + } + }.apply { + if (javaField.isStatic) { + containingClassAttr = ConeClassLikeLookupTagImpl(classId) + } } } } @@ -325,7 +347,8 @@ class JavaSymbolProvider( classId: ClassId, javaTypeParameterStack: JavaTypeParameterStack, classIsAnnotation: Boolean, - valueParametersForAnnotationConstructor: ValueParametersForAnnotationConstructor + valueParametersForAnnotationConstructor: ValueParametersForAnnotationConstructor, + dispatchReceiver: ConeClassLikeType ): FirJavaMethod { val methodName = javaMethod.name val methodId = CallableId(classId.packageFqName, classId.relativeClassName, methodName) @@ -364,6 +387,14 @@ class JavaSymbolProvider( isExternal = false isSuspend = false } + + if (!javaMethod.isStatic) { + dispatchReceiverType = dispatchReceiver + } + }.apply { + if (javaMethod.isStatic) { + containingClassAttr = ConeClassLikeLookupTagImpl(classId) + } } if (classIsAnnotation) { val parameterForAnnotationConstructor = buildJavaValueParameter { @@ -425,6 +456,8 @@ class JavaSymbolProvider( ) } } + }.apply { + containingClassAttr = ownerClassBuilder.symbol.toLookupTag() } } @@ -445,6 +478,8 @@ class JavaSymbolProvider( visibility = Visibilities.Public isInner = false isPrimary = true + }.apply { + containingClassAttr = ownerClassBuilder.symbol.toLookupTag() } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaConstructor.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaConstructor.kt index 70712a60cb7..262f4a8f8d7 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaConstructor.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaConstructor.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.fir.java.declarations +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.FirConstructorBuilder @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -37,6 +38,7 @@ class FirJavaConstructor @FirImplementationDetail constructor( override val annotations: MutableList, override var status: FirDeclarationStatus, override var resolvePhase: FirResolvePhase, + override val dispatchReceiverType: ConeKotlinType?, ) : FirConstructor() { override val receiverTypeRef: FirTypeRef? get() = null @@ -154,7 +156,8 @@ class FirJavaConstructorBuilder : FirConstructorBuilder() { typeParameters, annotations, status, - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES, + dispatchReceiverType ) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt index 318321e4287..cc4db634ec7 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt @@ -6,10 +6,10 @@ package org.jetbrains.kotlin.fir.java.declarations import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.FirFieldBuilder @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -42,6 +43,8 @@ class FirJavaField @FirImplementationDetail constructor( override val annotations: MutableList, override val typeParameters: MutableList, override var initializer: FirExpression?, + override val dispatchReceiverType: ConeKotlinType?, + override val attributes: FirDeclarationAttributes, ) : FirField() { init { symbol.bind(this) @@ -55,8 +58,6 @@ class FirJavaField @FirImplementationDetail constructor( override val origin: FirDeclarationOrigin get() = FirDeclarationOrigin.Java - override val attributes: FirDeclarationAttributes = FirDeclarationAttributes() - override fun transformReturnTypeRef(transformer: FirTransformer, data: D): FirField { returnTypeRef = returnTypeRef.transformSingle(transformer, data) return this @@ -163,6 +164,8 @@ internal class FirJavaFieldBuilder : FirFieldBuilder() { annotations, typeParameters, initializer, + dispatchReceiverType, + attributes, ) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaMethod.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaMethod.kt index a0e91d3cbcc..5beda4584f5 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaMethod.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaMethod.kt @@ -6,10 +6,10 @@ package org.jetbrains.kotlin.fir.java.declarations import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.declarations.* @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef import org.jetbrains.kotlin.name.Name @@ -53,6 +54,7 @@ class FirJavaMethod @FirImplementationDetail constructor( containerSource: DeserializedContainerSource?, symbol: FirFunctionSymbol, annotations: MutableList, + dispatchReceiverType: ConeKotlinType?, ) : FirSimpleFunctionImpl( source, session, @@ -65,6 +67,7 @@ class FirJavaMethod @FirImplementationDetail constructor( body, status, containerSource, + dispatchReceiverType = dispatchReceiverType, contractDescription = FirEmptyContractDescription, name, symbol, @@ -107,6 +110,7 @@ class FirJavaMethodBuilder : FirSimpleFunctionBuilder() { containerSource, symbol, annotations, + dispatchReceiverType, ) } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt index 751c0639d8f..ad4db202932 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt @@ -95,14 +95,18 @@ class FirSignatureEnhancement( session = this@FirSignatureEnhancement.session this.symbol = symbol this.name = name + returnTypeRef = newReturnTypeRef + + // TODO: Use some kind of copy mechanism visibility = firElement.visibility modality = firElement.modality - returnTypeRef = newReturnTypeRef isVar = firElement.isVar isStatic = firElement.isStatic annotations += firElement.annotations status = firElement.status initializer = firElement.initializer + dispatchReceiverType = firElement.dispatchReceiverType + attributes = firElement.attributes.copy() } return symbol } @@ -221,12 +225,16 @@ class FirSignatureEnhancement( isInner = firMethod.isInner } this.symbol = symbol + dispatchReceiverType = firMethod.dispatchReceiverType + attributes = firMethod.attributes.copy() } } else { FirConstructorBuilder().apply { returnTypeRef = newReturnTypeRef status = firMethod.status this.symbol = symbol + dispatchReceiverType = firMethod.dispatchReceiverType + attributes = firMethod.attributes.copy() } }.apply { source = firMethod.source @@ -250,6 +258,8 @@ class FirSignatureEnhancement( resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES valueParameters += newValueParameters typeParameters += firMethod.typeParameters + dispatchReceiverType = firMethod.dispatchReceiverType + attributes = firMethod.attributes.copy() } } else -> throw AssertionError("Unknown Java method to enhance: ${firMethod.render()}") diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt index c83bf00e6af..7ae0e0cb2b4 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt @@ -104,7 +104,8 @@ class JavaClassMembersEnhancementScope( FirDeclarationOrigin.Enhancement, newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) -> newType ?: valueParameter.returnTypeRef.coneType - } + }, + newDispatchReceiverType = dispatchReceiverType, ) } } diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt index 2745335d041..e9d75ab0c29 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt @@ -46,7 +46,10 @@ fun wrapScopeWithJvmMapped( (klass.symbol.constructType( klass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), false - ) as ConeClassLikeType).wrapSubstitutionScopeIfNeed(useSiteSession, jvmMappedScope, klass, scopeSession, klass.classId) + ) as ConeClassLikeType).wrapSubstitutionScopeIfNeed( + useSiteSession, jvmMappedScope, klass, scopeSession, + derivedClass = klass, + ) } } } else { diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index e3b97e6c79d..8f3ea61e77f 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -415,7 +415,7 @@ class DeclarationsConverter( addCapturedTypeParameters(firTypeParameters) val selfType = classNode.toDelegatedSelfType(this) - + registerSelfType(selfType) val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it, symbol, selfType) } var delegatedSuperTypeRef: FirTypeRef? = delegationSpecifiers?.delegatedSuperTypeRef @@ -500,8 +500,18 @@ class DeclarationsConverter( } if (modifiers.isEnum()) { - generateValuesFunction(baseSession, context.packageFqName, context.className, modifiers.hasExpect()) - generateValueOfFunction(baseSession, context.packageFqName, context.className, modifiers.hasExpect()) + generateValuesFunction( + baseSession, + context.packageFqName, + context.className, + modifiers.hasExpect() + ) + generateValueOfFunction( + baseSession, + context.packageFqName, + context.className, + modifiers.hasExpect() + ) } } } @@ -523,6 +533,7 @@ class DeclarationsConverter( symbol = FirAnonymousObjectSymbol() typeParameters += context.capturedTypeParameters.map { buildOuterClassTypeParameterRef { this.symbol = it } } val delegatedSelfType = objectLiteral.toDelegatedSelfType(this) + registerSelfType(delegatedSelfType) var modifiers = Modifier() var primaryConstructor: LighterASTNode? = null @@ -637,7 +648,7 @@ class DeclarationsConverter( emptyArray(), isNullable = false ) - }, + }.also { registerSelfType(it) }, delegatedSuperTypeRef = classWrapper.delegatedSelfTypeRef, superTypeCallEntry = enumSuperTypeCallEntry ) @@ -743,6 +754,8 @@ class DeclarationsConverter( this.valueParameters += valueParameters.map { it.firValueParameter } delegatedConstructor = firDelegatedCall this.body = body + }.apply { + containingClassAttr = currentDispatchReceiverType()!!.lookupTag }, valueParameters ) } @@ -814,6 +827,7 @@ class DeclarationsConverter( this.body = body context.firFunctionTargets.removeLast() }.also { + it.containingClassAttr = currentDispatchReceiverType()!!.lookupTag target.bind(it) } } @@ -969,6 +983,7 @@ class DeclarationsConverter( this.isLocal = false receiverTypeRef = receiverType symbol = FirPropertySymbol(callableIdForName(propertyName)) + dispatchReceiverType = currentDispatchReceiverType() withCapturedTypeParameters { typeParameters += firTypeParameters addCapturedTypeParameters(firTypeParameters) @@ -1292,6 +1307,7 @@ class DeclarationsConverter( } symbol = FirNamedFunctionSymbol(callableIdForName(functionName, isLocal)) + dispatchReceiverType = currentDispatchReceiverType() } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index cd7711679b6..7c9ffe9e39b 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* -import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.scopes.FirScopeProvider @@ -462,6 +461,8 @@ class RawFirBuilder( visibility ) else null extractAnnotationsTo(this) + + dispatchReceiverType = currentDispatchReceiverType() }.apply { isFromVararg = firParameter.isVararg } @@ -687,6 +688,8 @@ class RawFirBuilder( this@toFirConstructor?.extractAnnotationsTo(this) this@toFirConstructor?.extractValueParametersTo(this) this.body = body + }.apply { + containingClassAttr = currentDispatchReceiverType()!!.lookupTag } } @@ -750,6 +753,8 @@ class RawFirBuilder( val delegatedEntrySelfType = buildResolvedTypeRef { type = ConeClassLikeTypeImpl(this@buildAnonymousObject.symbol.toLookupTag(), emptyArray(), isNullable = false) } + registerSelfType(delegatedEntrySelfType) + superTypeRefs += delegatedEnumSelfTypeRef val superTypeCallEntry = superTypeListEntries.firstIsInstanceOrNull() val correctedEnumSelfTypeRef = buildResolvedTypeRef { @@ -777,6 +782,8 @@ class RawFirBuilder( } } } + }.apply { + containingClassAttr = currentDispatchReceiverType()!!.lookupTag } } @@ -827,6 +834,8 @@ class RawFirBuilder( addCapturedTypeParameters(typeParameters.take(classOrObject.typeParameters.size)) val delegatedSelfType = classOrObject.toDelegatedSelfType(this) + registerSelfType(delegatedSelfType) + val delegatedSuperType = classOrObject.extractSuperTypeListEntriesTo( this, delegatedSelfType, @@ -884,10 +893,14 @@ class RawFirBuilder( if (classOrObject.hasModifier(ENUM_KEYWORD)) { generateValuesFunction( - baseSession, context.packageFqName, context.className, classOrObject.hasExpectModifier() + baseSession, + context.packageFqName, + context.className, + classOrObject.hasExpectModifier() ) generateValueOfFunction( - baseSession, context.packageFqName, context.className, classOrObject.hasExpectModifier() + baseSession, context.packageFqName, context.className, + classOrObject.hasExpectModifier() ) } } @@ -907,6 +920,7 @@ class RawFirBuilder( symbol = FirAnonymousObjectSymbol() typeParameters += context.capturedTypeParameters.map { buildOuterClassTypeParameterRef { symbol = it } } val delegatedSelfType = objectDeclaration.toDelegatedSelfType(this) + registerSelfType(delegatedSelfType) objectDeclaration.extractAnnotationsTo(this) val delegatedSuperType = objectDeclaration.extractSuperTypeListEntriesTo( this, @@ -975,6 +989,7 @@ class RawFirBuilder( name = function.nameAsSafeName labelName = runIf(!name.isSpecial) { name.identifier } symbol = FirNamedFunctionSymbol(callableIdForName(function.nameAsSafeName, function.isLocal)) + dispatchReceiverType = currentDispatchReceiverType() status = FirDeclarationStatusImpl( if (function.isLocal) Visibilities.Local else function.visibility, function.modality, @@ -1170,6 +1185,7 @@ class RawFirBuilder( this.body = body this@RawFirBuilder.context.firFunctionTargets.removeLast() }.also { + it.containingClassAttr = currentDispatchReceiverType()!!.lookupTag target.bind(it) } } @@ -1244,6 +1260,7 @@ class RawFirBuilder( isLocal = false receiverTypeRef = receiverTypeReference.convertSafe() symbol = FirPropertySymbol(callableIdForName(propertyName)) + dispatchReceiverType = currentDispatchReceiverType() extractTypeParametersTo(this) withCapturedTypeParameters { addCapturedTypeParameters(this.typeParameters) diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index ad90864de3a..5f6d441a0b8 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -66,14 +67,27 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte ): T { context.className = context.className.child(name) context.localBits.add(isLocal) + val dispatchReceiversNumber = context.dispatchReceiverTypesStack.size return try { l() } finally { + require(context.dispatchReceiverTypesStack.size <= dispatchReceiversNumber + 1) { + "Wrong number of ${context.dispatchReceiverTypesStack.size}" + } + + if (context.dispatchReceiverTypesStack.size > dispatchReceiversNumber) { + context.dispatchReceiverTypesStack.removeAt(context.dispatchReceiverTypesStack.lastIndex) + } + context.className = context.className.parent() context.localBits.removeLast() } } + fun registerSelfType(selfType: FirResolvedTypeRef) { + context.dispatchReceiverTypesStack.add(selfType.type as ConeClassLikeType) + } + inline fun withCapturedTypeParameters(block: () -> T): T { val previous = context.capturedTypeParameters val result = block() @@ -109,6 +123,8 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte else -> CallableId(context.packageFqName, context.className, name) } + fun currentDispatchReceiverType(): ConeClassLikeType? = context.dispatchReceiverTypesStack.lastOrNull() + fun callableIdForClassConstructor() = if (context.className == FqName.ROOT) CallableId(context.packageFqName, Name.special("")) else CallableId(context.packageFqName, context.className, context.className.shortName()) @@ -1067,7 +1083,7 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte this.name = name status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL) symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name)) - + dispatchReceiverType = currentDispatchReceiverType() // Refer to FIR backend ClassMemberGenerator for body generation. } classBuilder.addDeclaration(componentFunction) @@ -1087,6 +1103,7 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte name = copyName status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL) symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName)) + dispatchReceiverType = currentDispatchReceiverType() for ((ktParameter, firProperty) in zippedParameters) { val propertyName = firProperty.name val parameterSource = ktParameter?.toFirSourceElement(FirFakeSourceElementKind.DataClassGeneratedMembers) diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/Context.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/Context.kt index 12e146bc4ea..8d35e8bb7b0 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/Context.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/Context.kt @@ -6,9 +6,14 @@ package org.jetbrains.kotlin.fir.builder import kotlinx.collections.immutable.persistentListOf -import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.FirFunctionTarget +import org.jetbrains.kotlin.fir.FirLabel +import org.jetbrains.kotlin.fir.FirLoopTarget +import org.jetbrains.kotlin.fir.FirSourceElementKind import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -27,4 +32,5 @@ class Context { val arraySetArgument = mutableMapOf() var forcedElementSourceKind: FirSourceElementKind? = null + val dispatchReceiverTypesStack = mutableListOf() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt index 31482813a43..a5e435f198a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.containingClassAttr import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction @@ -44,6 +45,7 @@ val SAM_PARAMETER_NAME = Name.identifier("block") class FirSamResolverImpl( private val firSession: FirSession, private val scopeSession: ScopeSession, + private val outerClassManager: FirOuterClassManager, ) : FirSamResolver() { private val resolvedFunctionType: MutableMap = mutableMapOf() @@ -197,6 +199,8 @@ class FirSamResolverImpl( } resolvePhase = FirResolvePhase.BODY_RESOLVE + }.apply { + containingClassAttr = outerClassManager.outerClass(firRegularClass.symbol)?.toLookupTag() } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index 08c565eb236..6b9db604795 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -18,11 +18,13 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculat import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope import org.jetbrains.kotlin.fir.scopes.scopeForClass +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl +import org.jetbrains.kotlin.name.ClassId fun ConeKotlinType.scope( useSiteSession: FirSession, @@ -64,7 +66,8 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope FirStandardOverrideChecker(useSiteSession), intersectedTypes.mapNotNullTo(mutableListOf()) { it.scope(useSiteSession, scopeSession, requiredPhase) - } + }, + type ) is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession, requiredPhase) is ConeIntegerLiteralType -> error("ILT should not be in receiver position") @@ -72,6 +75,14 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope } } + +fun FirClass<*>.defaultType(): ConeClassLikeType = + when (this) { + is FirRegularClass -> defaultType() + is FirAnonymousObject -> defaultType() + else -> error("Unknown class ${this::class}") + } + fun FirRegularClass.defaultType(): ConeClassLikeTypeImpl { return ConeClassLikeTypeImpl( symbol.toLookupTag(), @@ -93,4 +104,16 @@ fun FirAnonymousObject.defaultType(): ConeClassLikeType { ) } +fun ClassId.defaultType(parameters: List): ConeClassLikeType = + ConeClassLikeTypeImpl( + ConeClassLikeLookupTagImpl(this), + parameters.map { + ConeTypeParameterTypeImpl( + it.toLookupTag(), + isNullable = false + ) + }.toTypedArray(), + isNullable = false, + ) + val TYPE_PARAMETER_SCOPE_KEY = scopeSessionKey() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt index 13c7335b386..4ef186f110e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.model.CaptureStatus abstract class SupertypeSupplier { @@ -91,7 +90,7 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed( useSiteMemberScope: FirTypeScope, declaration: FirClassLikeDeclaration<*>, builder: ScopeSession, - derivedClassId: ClassId? + derivedClass: FirRegularClass ): FirTypeScope { if (this.typeArguments.isEmpty()) return useSiteMemberScope return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) { @@ -110,7 +109,8 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed( } FirClassSubstitutionScope( session, useSiteMemberScope, substitutor, - skipPrivateMembers = true, derivedClassId = derivedClassId + dispatchReceiverTypeForSubstitutedMembers = derivedClass.defaultType(), + skipPrivateMembers = true, ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt index 02fe401afbe..fca0cfe2dba 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt @@ -124,8 +124,11 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias( session ) { newReturnType, newParameterTypes, newTypeParameters -> FirFakeOverrideGenerator.createFakeOverrideFunction( - session, this, namedSymbol, null, - newReturnType, newParameterTypes, newTypeParameters + session, this, namedSymbol, + newDispatchReceiverType = null, + newReceiverType = null, + newReturnType, newParameterTypes, newTypeParameters, + expansionRegularClass.classId, ).fir } ?: return null @@ -263,6 +266,7 @@ private fun prepareSubstitutingScopeForTypeAliasConstructors( valueParameters += this@factory.valueParameters } this.typeParameters += newTypeParameters + this.attributes = this@factory.attributes.copy() } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirCloneableSymbolProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirCloneableSymbolProvider.kt index 7d8fd4b65e3..33825d8e5cc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirCloneableSymbolProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirCloneableSymbolProvider.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl +import org.jetbrains.kotlin.fir.resolve.constructType import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals import org.jetbrains.kotlin.fir.scopes.FirScopeProvider @@ -47,6 +48,7 @@ class FirCloneableSymbolProvider(session: FirSession, scopeProvider: FirScopePro Modality.ABSTRACT ) classKind = ClassKind.INTERFACE + symbol = FirRegularClassSymbol(CLONEABLE_CLASS_ID) declarations += buildSimpleFunction { this.session = session resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES @@ -57,10 +59,11 @@ class FirCloneableSymbolProvider(session: FirSession, scopeProvider: FirScopePro status = FirDeclarationStatusImpl(Visibilities.Protected, Modality.OPEN) name = CLONE symbol = FirNamedFunctionSymbol(CallableId(CLONEABLE_CLASS_ID, CLONE)) + dispatchReceiverType = this@buildRegularClass.symbol.constructType(emptyArray(), isNullable = false) } this.scopeProvider = scopeProvider name = CLONEABLE - symbol = FirRegularClassSymbol(CLONEABLE_CLASS_ID) + } override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt index 9d3cb58deff..6a9861c2657 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt @@ -122,7 +122,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb override val symbolProvider: FirSymbolProvider = session.firSymbolProvider override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner() - override val samResolver: FirSamResolver = FirSamResolverImpl(session, scopeSession) + private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(this) override val callResolver: FirCallResolver = FirCallResolver( this, @@ -137,5 +137,6 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb override val syntheticCallGenerator: FirSyntheticCallGenerator = FirSyntheticCallGenerator(this) override val doubleColonExpressionResolver: FirDoubleColonExpressionResolver = FirDoubleColonExpressionResolver(session) override val outerClassManager: FirOuterClassManager = FirOuterClassManager(session, context.outerLocalClassForNested) + override val samResolver: FirSamResolver = FirSamResolverImpl(session, scopeSession, outerClassManager) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt index 30e6d7dc0b8..50f5b0e8bbd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.symbols.CallableId -import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassErrorType import org.jetbrains.kotlin.fir.types.ConeClassLikeType @@ -60,9 +59,9 @@ class KotlinScopeProvider( useSiteSession, FirTypeIntersectionScope.prepareIntersectionScope( useSiteSession, FirStandardOverrideChecker(useSiteSession), scopes, - klass.classId, + klass.defaultType(), ), - decoratedDeclaredMemberScope + decoratedDeclaredMemberScope, ) } } @@ -113,7 +112,7 @@ fun FirClass<*>.scopeForClass( ): FirTypeScope = scopeForClassImpl( substitutor, useSiteSession, scopeSession, skipPrivateMembers = false, - containingClassForAdditionalMembers = symbol.toLookupTag(), + classFirDispatchReceiver = this, // TODO: why it's always false? isFromExpectClass = false ) @@ -129,12 +128,12 @@ private fun FirClass<*>.scopeForSupertype( useSiteSession, scopeSession, skipPrivateMembers = true, - containingClassForAdditionalMembers = subClass.symbol.toLookupTag(), + classFirDispatchReceiver = subClass, isFromExpectClass = (subClass as? FirRegularClass)?.isExpect == true ).let { if (delegateField != null) { scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) { - FirDelegatedMemberScope(it, useSiteSession, subClass.symbol.toLookupTag(), delegateField) + FirDelegatedMemberScope(it, useSiteSession, subClass, delegateField) } } else { it @@ -146,18 +145,18 @@ private fun FirClass<*>.scopeForClassImpl( useSiteSession: FirSession, scopeSession: ScopeSession, skipPrivateMembers: Boolean, - containingClassForAdditionalMembers: ConeClassLikeLookupTag, + classFirDispatchReceiver: FirClass<*>, isFromExpectClass: Boolean ): FirTypeScope { val basicScope = unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator = false) if (substitutor == ConeSubstitutor.Empty) return basicScope return scopeSession.getOrBuild( - this, ConeSubstitutionScopeKey(containingClassForAdditionalMembers.classId, isFromExpectClass, substitutor) + this, ConeSubstitutionScopeKey(classFirDispatchReceiver.classId, isFromExpectClass, substitutor) ) { FirClassSubstitutionScope( - useSiteSession, basicScope, substitutor, skipPrivateMembers, - containingClassForAdditionalMembers.classId, makeExpect = isFromExpectClass + useSiteSession, basicScope, substitutor, classFirDispatchReceiver.defaultType(), + skipPrivateMembers, makeExpect = isFromExpectClass ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt index d77013263d6..ac4da4cc229 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt @@ -12,13 +12,11 @@ import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.chain -import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.runIf @@ -26,8 +24,8 @@ class FirClassSubstitutionScope( private val session: FirSession, private val useSiteMemberScope: FirTypeScope, private val substitutor: ConeSubstitutor, + private val dispatchReceiverTypeForSubstitutedMembers: ConeClassLikeType, private val skipPrivateMembers: Boolean, - private val derivedClassId: ClassId? = null, private val makeExpect: Boolean = false ) : FirTypeScope() { @@ -35,6 +33,8 @@ class FirClassSubstitutionScope( private val fakeOverrideConstructors = mutableMapOf() private val fakeOverrideVariables = mutableMapOf, FirVariableSymbol<*>>() + private val newOwnerClassId = dispatchReceiverTypeForSubstitutedMembers.lookupTag.classId + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { useSiteMemberScope.processFunctionsByName(name) process@{ original -> val function = fakeOverrideFunctions.getOrPut(original) { createFakeOverrideFunction(original) } @@ -139,11 +139,12 @@ class FirClassSubstitutionScope( session, member, original, + dispatchReceiverTypeForSubstitutedMembers, newReceiverType, newReturnType, newParameterTypes, newTypeParameters as List, - derivedClassId, + newOwnerClassId, makeExpect, fakeOverrideSubstitution ) @@ -163,7 +164,8 @@ class FirClassSubstitutionScope( } return FirFakeOverrideGenerator.createFakeOverrideConstructor( FirConstructorSymbol(original.callableId, overriddenSymbol = original), - session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect, fakeOverrideSubstitution + session, constructor, dispatchReceiverTypeForSubstitutedMembers, + newReturnType, newParameterTypes, newTypeParameters, makeExpect, fakeOverrideSubstitution ).symbol } @@ -184,10 +186,11 @@ class FirClassSubstitutionScope( session, member, original, + dispatchReceiverTypeForSubstitutedMembers, newReceiverType, newReturnType, newTypeParameters as List, - derivedClassId, + newOwnerClassId, makeExpect, fakeOverrideSubstitution ) @@ -205,7 +208,7 @@ class FirClassSubstitutionScope( val (newTypeParameters, substitutor) = FirFakeOverrideGenerator.createNewTypeParametersAndSubstitutor( member as FirTypeParameterRefsOwner, substitutor, - forceTypeParametersRecreation = derivedClassId != null && derivedClassId != member.symbol.callableId.classId + forceTypeParametersRecreation = dispatchReceiverTypeForSubstitutedMembers.lookupTag != member.dispatchReceiverClassOrNull() ) val receiverType = member.receiverTypeRef?.coneType @@ -226,7 +229,7 @@ class FirClassSubstitutionScope( // TODO: do we have fields with implicit type? val newReturnType = returnType?.substitute() ?: return original - return FirFakeOverrideGenerator.createFakeOverrideField(session, member, original, newReturnType, derivedClassId) + return FirFakeOverrideGenerator.createFakeOverrideField(session, member, original, newReturnType, newOwnerClassId) } private fun createFakeOverrideAccessor(original: FirAccessorSymbol): FirAccessorSymbol { @@ -250,6 +253,7 @@ class FirClassSubstitutionScope( session, member, original, + dispatchReceiverTypeForSubstitutedMembers, newReturnType, newParameterTypes, fakeOverrideSubstitution diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt index 1fd0b4cb952..9614936addc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag @@ -17,11 +18,12 @@ import org.jetbrains.kotlin.name.Name class FirDelegatedMemberScope( private val useSiteScope: FirTypeScope, private val session: FirSession, - private val containingClass: ConeClassLikeLookupTag, + private val containingClass: FirClass<*>, private val delegateField: FirField, ) : FirTypeScope() { private val delegatedFunctionCache = mutableMapOf() private val delegatedPropertyCache = mutableMapOf() + private val dispatchReceiverType = containingClass.defaultType() override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { useSiteScope.processFunctionsByName(name) processor@{ functionSymbol -> @@ -43,9 +45,10 @@ class FirDelegatedMemberScope( original, session, FirDeclarationOrigin.Delegated, + newDispatchReceiverType = dispatchReceiverType, newModality = Modality.OPEN, ).apply { - delegatedWrapperData = DelegatedWrapperData(functionSymbol.fir, containingClass, delegateField) + delegatedWrapperData = DelegatedWrapperData(functionSymbol.fir, containingClass.symbol.toLookupTag(), delegateField) }.symbol as FirNamedFunctionSymbol } processor(delegatedSymbol) @@ -72,8 +75,9 @@ class FirDelegatedMemberScope( original, session, newModality = Modality.OPEN, + newDispatchReceiverType = dispatchReceiverType, ).apply { - delegatedWrapperData = DelegatedWrapperData(propertySymbol.fir, containingClass, delegateField) + delegatedWrapperData = DelegatedWrapperData(propertySymbol.fir, containingClass.symbol.toLookupTag(), delegateField) }.symbol } processor(delegatedSymbol) @@ -105,7 +109,7 @@ class FirDelegatedMemberScope( ): ProcessorAction { val wrappedData = (symbol.fir as? FirCallableMemberDeclaration<*>)?.delegatedWrapperData return when { - wrappedData == null || wrappedData.containingClass != containingClass -> { + wrappedData == null || wrappedData.containingClass != containingClass.symbol.toLookupTag() -> { useSiteScope.processDirectOverriddenCallablesWithBaseScope(symbol, processor) } else -> processor(wrappedData.wrapped.symbol as D, useSiteScope) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt index 276de0851bd..454ca646a62 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt @@ -32,6 +32,7 @@ object FirFakeOverrideGenerator { session: FirSession, baseFunction: FirSimpleFunction, baseSymbol: FirNamedFunctionSymbol, + newDispatchReceiverType: ConeKotlinType?, newReceiverType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null, newParameterTypes: List? = null, @@ -45,7 +46,7 @@ object FirFakeOverrideGenerator { isFakeOverride = true, overriddenSymbol = baseSymbol ) createFakeOverrideFunction( - symbol, session, baseFunction, newReceiverType, newReturnType, + symbol, session, baseFunction, newDispatchReceiverType, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution ) return symbol @@ -55,6 +56,7 @@ object FirFakeOverrideGenerator { fakeOverrideSymbol: FirFunctionSymbol, session: FirSession, baseFunction: FirSimpleFunction, + newDispatchReceiverType: ConeKotlinType?, newReceiverType: ConeKotlinType?, newReturnType: ConeKotlinType?, newParameterTypes: List?, @@ -70,6 +72,7 @@ object FirFakeOverrideGenerator { session, FirDeclarationOrigin.SubstitutionOverride, isExpect, + newDispatchReceiverType, newParameterTypes, newTypeParameters, newReceiverType, @@ -84,6 +87,7 @@ object FirFakeOverrideGenerator { session: FirSession, origin: FirDeclarationOrigin, isExpect: Boolean = baseFunction.isExpect, + newDispatchReceiverType: ConeKotlinType?, newParameterTypes: List? = null, newTypeParameters: List? = null, newReceiverType: ConeKotlinType? = null, @@ -101,6 +105,8 @@ object FirFakeOverrideGenerator { symbol = newSymbol resolvePhase = baseFunction.resolvePhase + dispatchReceiverType = newDispatchReceiverType + attributes = baseFunction.attributes.copy() typeParameters += configureAnnotationsTypeParametersAndSignature( session, baseFunction, newParameterTypes, newTypeParameters, newReceiverType, newReturnType, fakeOverrideSubstitution @@ -112,6 +118,7 @@ object FirFakeOverrideGenerator { fakeOverrideSymbol: FirConstructorSymbol, session: FirSession, baseConstructor: FirConstructor, + newDispatchReceiverType: ConeKotlinType?, newReturnType: ConeKotlinType?, newParameterTypes: List?, newTypeParameters: List?, @@ -121,17 +128,21 @@ object FirFakeOverrideGenerator { // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl // As second alternative, we can invent some light-weight kind of FirRegularClass return buildConstructor { - source = baseConstructor.source this.session = session origin = FirDeclarationOrigin.SubstitutionOverride receiverTypeRef = baseConstructor.receiverTypeRef?.withReplacedConeType(null) status = baseConstructor.status.updatedStatus(isExpect) symbol = fakeOverrideSymbol - resolvePhase = baseConstructor.resolvePhase typeParameters += configureAnnotationsTypeParametersAndSignature( session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType, fakeOverrideSubstitution ) + + dispatchReceiverType = newDispatchReceiverType + + resolvePhase = baseConstructor.resolvePhase + source = baseConstructor.source + attributes = baseConstructor.attributes.copy() } } @@ -235,6 +246,7 @@ object FirFakeOverrideGenerator { session: FirSession, baseProperty: FirProperty, baseSymbol: FirPropertySymbol, + newDispatchReceiverType: ConeKotlinType?, newReceiverType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null, newTypeParameters: List? = null, @@ -248,7 +260,7 @@ object FirFakeOverrideGenerator { ) createCopyForFirProperty( symbol, baseProperty, session, isExpect, - newTypeParameters, newReceiverType, newReturnType, + newDispatchReceiverType, newTypeParameters, newReceiverType, newReturnType, fakeOverrideSubstitution = fakeOverrideSubstitution ) return symbol @@ -259,6 +271,7 @@ object FirFakeOverrideGenerator { baseProperty: FirProperty, session: FirSession, isExpect: Boolean = baseProperty.isExpect, + newDispatchReceiverType: ConeKotlinType?, newTypeParameters: List? = null, newReceiverType: ConeKotlinType? = null, newReturnType: ConeKotlinType? = null, @@ -277,6 +290,8 @@ object FirFakeOverrideGenerator { status = baseProperty.status.updatedStatus(isExpect, newModality, newVisibility) resolvePhase = baseProperty.resolvePhase + dispatchReceiverType = newDispatchReceiverType + attributes = baseProperty.attributes.copy() typeParameters += configureAnnotationsTypeParametersAndSignature( baseProperty, newTypeParameters, @@ -373,17 +388,20 @@ object FirFakeOverrideGenerator { CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseField.name) ) buildField { - source = baseField.source this.session = session - origin = FirDeclarationOrigin.SubstitutionOverride - resolvePhase = baseField.resolvePhase - returnTypeRef = baseField.returnTypeRef.withReplacedConeType(newReturnType) - name = baseField.name this.symbol = symbol + origin = FirDeclarationOrigin.SubstitutionOverride + returnTypeRef = baseField.returnTypeRef.withReplacedConeType(newReturnType) + + source = baseField.source + resolvePhase = baseField.resolvePhase + name = baseField.name isVar = baseField.isVar status = baseField.status resolvePhase = baseField.resolvePhase annotations += baseField.annotations + attributes = baseField.attributes.copy() + dispatchReceiverType = baseField.dispatchReceiverType } return symbol } @@ -392,6 +410,7 @@ object FirFakeOverrideGenerator { session: FirSession, baseProperty: FirSyntheticProperty, baseSymbol: FirAccessorSymbol, + newDispatchReceiverType: ConeKotlinType?, newReturnType: ConeKotlinType?, newParameterTypes: List?, fakeOverrideSubstitution: FakeOverrideSubstitution? @@ -401,6 +420,7 @@ object FirFakeOverrideGenerator { functionSymbol, session, baseProperty.getter.delegate, + newDispatchReceiverType, newReceiverType = null, newReturnType, newParameterTypes, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt index c71abeac6fc..f2d8fc71c8a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt @@ -10,16 +10,13 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol import org.jetbrains.kotlin.fir.symbols.impl.* -import org.jetbrains.kotlin.fir.types.ConeFlexibleType -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext -import org.jetbrains.kotlin.fir.types.coneTypeSafe -import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeCheckerContext @@ -30,7 +27,7 @@ class FirTypeIntersectionScope private constructor( session: FirSession, overrideChecker: FirOverrideChecker, private val scopes: List, - private val derivedClassId: ClassId?, + private val dispatchReceiverType: ConeKotlinType, ) : AbstractFirOverrideScope(session, overrideChecker) { private val absentFunctions: MutableSet = mutableSetOf() private val absentProperties: MutableSet = mutableSetOf() @@ -261,9 +258,13 @@ class FirTypeIntersectionScope private constructor( newModality: Modality, newVisibility: Visibility, ): FirNamedFunctionSymbol { + val newSymbol = FirNamedFunctionSymbol( - CallableId(derivedClassId ?: mostSpecific.callableId.classId!!, mostSpecific.fir.name), + CallableId( + dispatchReceiverType.classId ?: mostSpecific.dispatchReceiverClassOrNull()?.classId!!, + mostSpecific.fir.name + ), mostSpecific.isFakeOverride, mostSpecific, isIntersectionOverride = true @@ -273,6 +274,7 @@ class FirTypeIntersectionScope private constructor( newSymbol, mostSpecificFunction, session, FirDeclarationOrigin.IntersectionOverride, mostSpecificFunction.isExpect, + newDispatchReceiverType = dispatchReceiverType, newModality = newModality, newVisibility = newVisibility, ) @@ -290,6 +292,7 @@ class FirTypeIntersectionScope private constructor( newSymbol, mostSpecificProperty, mostSpecificProperty.session, newModality = newModality, newVisibility = newVisibility, + newDispatchReceiverType = dispatchReceiverType, ) return newSymbol } @@ -486,10 +489,10 @@ class FirTypeIntersectionScope private constructor( session: FirSession, overrideChecker: FirOverrideChecker, scopes: List, - derivedClassId: ClassId? = null, + dispatchReceiverType: ConeKotlinType, ): FirTypeScope { scopes.singleOrNull()?.let { return it } - return FirTypeIntersectionScope(session, overrideChecker, scopes, derivedClassId) + return FirTypeIntersectionScope(session, overrideChecker, scopes, dispatchReceiverType) } } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt index 5141013b87f..8bc8af44ab4 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirConstructorBuilder.kt @@ -108,6 +108,7 @@ inline fun buildConstructorCopy(original: FirConstructor, init: FirConstructorBu copyBuilder.valueParameters.addAll(original.valueParameters) copyBuilder.status = original.status copyBuilder.containerSource = original.containerSource + copyBuilder.dispatchReceiverType = original.dispatchReceiverType copyBuilder.annotations.addAll(original.annotations) copyBuilder.symbol = original.symbol copyBuilder.delegatedConstructor = original.delegatedConstructor diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt new file mode 100644 index 00000000000..fa37e7f6bab --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt @@ -0,0 +1,33 @@ +/* + * 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.fir + +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataKey +import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataRegistry +import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.ConeIntersectionType + +fun FirCallableSymbol<*>.dispatchReceiverClassOrNull(): ConeClassLikeLookupTag? = + (fir as? FirCallableMemberDeclaration<*>)?.dispatchReceiverClassOrNull() + +fun FirCallableDeclaration<*>.dispatchReceiverClassOrNull(): ConeClassLikeLookupTag? { + if (this !is FirCallableMemberDeclaration<*>) return null + if (symbol.isIntersectionOverride && dispatchReceiverType is ConeIntersectionType) return symbol.overriddenSymbol!!.fir.dispatchReceiverClassOrNull() + + return (dispatchReceiverType as? ConeClassLikeType)?.lookupTag +} + +fun FirCallableSymbol<*>.containingClass(): ConeClassLikeLookupTag? = fir.containingClass() +fun FirCallableDeclaration<*>.containingClass(): ConeClassLikeLookupTag? { + return (containingClassAttr ?: dispatchReceiverClassOrNull()) +} + +private object ContainingClassKey : FirDeclarationDataKey() +var FirCallableDeclaration<*>.containingClassAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt index d247d89336f..4e502fddd80 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt @@ -55,6 +55,8 @@ fun FirRegularClassBuilder.generateValuesFunction( symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUES)) resolvePhase = FirResolvePhase.BODY_RESOLVE body = buildEmptyExpressionBlock() + }.apply { + containingClassAttr = this@generateValuesFunction.symbol.toLookupTag() } } @@ -93,5 +95,7 @@ fun FirRegularClassBuilder.generateValueOfFunction( } resolvePhase = FirResolvePhase.BODY_RESOLVE body = buildEmptyExpressionBlock() + }.apply { + containingClassAttr = this@generateValueOfFunction.symbol.toLookupTag() } } From 4d9ef4d414f7e942b317a95dbfa711e624946e37 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 23 Oct 2020 17:04:41 +0300 Subject: [PATCH 035/554] FIR: Get rid of CallableId::classId usages Use dispatchReceiverType or containingClassAttr instead --- .../fir/analysis/checkers/FirHelpers.kt | 20 ++++------------ ...rclassNotAccessibleFromInterfaceChecker.kt | 17 +++---------- ...BeReplacedWithOperatorAssignmentChecker.kt | 9 +++---- .../checkers/extended/UnusedChecker.kt | 4 ++-- .../fir/backend/jvm/FirJvmMangleComputer.kt | 3 ++- .../backend/jvm/FirJvmSerializerExtension.kt | 4 ++-- .../kotlin/fir/backend/ConversionUtils.kt | 11 +++++++-- .../fir/backend/Fir2IrDeclarationStorage.kt | 12 +++++----- .../generators/CallAndReferenceGenerator.kt | 5 ++-- .../generators/ClassMemberGenerator.kt | 3 ++- .../generators/DelegatedMemberGenerator.kt | 6 +++-- .../generators/FakeOverrideGenerator.kt | 14 +++++------ .../kotlin/fir/lazy/Fir2IrLazyClass.kt | 9 +++---- .../signaturer/FirBasedSignatureComposer.kt | 24 +++++++++---------- .../jvm/ConeEquivalentCallConflictResolver.kt | 7 +++--- .../fir/FirEffectiveVisibilityResolverImpl.kt | 4 ++-- .../kotlin/fir/FirVisibilityChecker.kt | 17 +++++++++---- .../fir/resolve/calls/ResolutionStages.kt | 19 +++++++-------- .../kotlin/fir/resolve/calls/SuperCalls.kt | 3 ++- .../kotlin/fir/resolve/calls/Synthetics.kt | 9 +++++-- .../fir/resolve/calls/tower/TowerLevels.kt | 23 +++++++++--------- .../kotlin/fir/resolve/dfa/VariableStorage.kt | 13 +++++----- .../body/resolve/FirImplicitBodyResolve.kt | 6 ++--- .../level/api/file/structure/FileStructure.kt | 6 +++-- .../resolve/FirLazyDeclarationResolver.kt | 8 ++++--- ...deDeserializedDeclarationSourceProvider.kt | 5 ++-- .../api/fir/symbols/KtFirConstructorSymbol.kt | 10 ++++---- .../api/fir/symbols/KtFirEnumEntrySymbol.kt | 7 +++--- .../api/fir/symbols/KtFirFunctionSymbol.kt | 11 +++++---- .../api/fir/symbols/KtFirPropertySymbol.kt | 9 +++---- .../plugin/AllOpenVisibilityTransformer.kt | 5 ++-- 31 files changed, 152 insertions(+), 151 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index e56d444a223..7c70973ee92 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -7,11 +7,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression @@ -23,7 +24,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType @@ -142,18 +142,8 @@ inline fun FirQualifiedAccessExpression.getDeclaration(): T? { * Returns the ClassLikeDeclaration where the Fir object has been defined * or null if no proper declaration has been found. */ -fun FirSymbolOwner<*>.getContainingClass(context: CheckerContext): FirClassLikeDeclaration<*>? { - val classId = this.symbol.safeAs>() - ?.callableId - ?.classId - ?: return null - - if (!classId.isLocal) { - return context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir - } - - return null -} +fun FirSymbolOwner<*>.getContainingClass(context: CheckerContext): FirClassLikeDeclaration<*>? = + this.safeAs>()?.containingClass()?.toSymbol(context.session)?.fir /** * Returns the FirClassLikeDeclaration the type alias is pointing diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt index 19644efb0c1..5cbdc7c00a5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration @@ -15,8 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirSuperReference -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -45,17 +44,7 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecke * or null if no proper declaration has been found. */ private fun getClassLikeDeclaration(functionCall: FirQualifiedAccessExpression, context: CheckerContext): FirClassLikeDeclaration<*>? { - val classId = functionCall.calleeReference.safeAs() - ?.resolvedSymbol.safeAs() - ?.callableId - ?.classId - ?: return null - - if (!classId.isLocal) { - return context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir - } - - return null + return functionCall.calleeReference.safeAs()?.resolvedSymbol?.fir?.getContainingClass(context) } private fun DiagnosticReporter.report(source: FirSourceElement?) { @@ -63,4 +52,4 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecke report(FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE.on(it)) } } -} \ No newline at end of file +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt index bb344b7ceb0..0f28f5e2d70 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt @@ -9,9 +9,7 @@ import com.intellij.lang.LighterASTNode import com.intellij.openapi.util.Ref import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.KtNodeTypes -import org.jetbrains.kotlin.fir.FirFakeSourceElementKind -import org.jetbrains.kotlin.fir.FirLightSourceElement -import org.jetbrains.kotlin.fir.FirPsiSourceElement +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter @@ -20,7 +18,6 @@ import org.jetbrains.kotlin.fir.analysis.getChild import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol -import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.types.classId @@ -41,7 +38,7 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker)?.getContainingClass(checkerContext) != null) return + if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf { !it.symbol.classId.isLocal }!= null) return val properties = LocalPropertyCollector.collect(graph) if (properties.isEmpty()) return @@ -203,4 +203,4 @@ object UnusedChecker : FirControlFlowChecker() { private val FirPropertySymbol.identifierSource: FirSourceElement? get() = fir.source?.getChild(KtTokens.IDENTIFIER, 0, 1) -} \ No newline at end of file +} diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt index 8e3bdf6c496..c9e9caeafe5 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.firSymbolProvider @@ -75,7 +76,7 @@ open class FirJvmMangleComputer( private fun FirDeclaration.visitParent() { val (parentPackageFqName, parentClassId) = when (this) { - is FirCallableDeclaration<*> -> this.symbol.callableId.let { it.packageName to it.classId } + is FirCallableMemberDeclaration<*> -> this.containingClass()?.classId?.let { it.packageFqName to it } ?: return is FirClassLikeDeclaration<*> -> this.symbol.classId.let { it.packageFqName to it.outerClassId } else -> return } diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt index b5fb0c58d17..af4b627c07a 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt @@ -10,8 +10,8 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.firProvider @@ -279,7 +279,7 @@ class FirJvmSerializerExtension( if (!hasJvmFieldAnnotation) return false val container = - symbol.callableId.classId?.let { + dispatchReceiverType?.classId?.let { session.firProvider.getFirClassifierByFqName(it) as? FirRegularClass } if (container == null || !container.isCompanion) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 0a61b28bdcd..3960f0d2dc4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope @@ -218,7 +219,9 @@ internal tailrec fun FirCallableSymbol<*>.deepestOverriddenSymbol(): FirCallable internal tailrec fun FirCallableSymbol<*>.deepestMatchingOverriddenSymbol(root: FirCallableSymbol<*> = this): FirCallableSymbol<*> { if (isIntersectionOverride) return this - val overriddenSymbol = overriddenSymbol?.takeIf { it.callableId == root.callableId } ?: return this + val overriddenSymbol = overriddenSymbol?.takeIf { + it.containingClass() == root.containingClass() + } ?: return this return overriddenSymbol.deepestMatchingOverriddenSymbol(this) } @@ -235,7 +238,11 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols( if ((it.fir as FirSimpleFunction).visibility == Visibilities.Private) { return@processDirectlyOverriddenFunctions ProcessorAction.NEXT } - val overridden = declarationStorage.getIrFunctionSymbol(it.unwrapSubstitutionOverrides()) + + val unwrapped = + it.fir.delegatedWrapperData?.takeIf { it.containingClass == containingClass.symbol.toLookupTag() }?.wrapped?.symbol ?: it + + val overridden = declarationStorage.getIrFunctionSymbol(unwrapped.unwrapSubstitutionOverrides()) overriddenSet += overridden as IrSimpleFunctionSymbol ProcessorAction.NEXT } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index a07f39fc0d9..0ad64004aa7 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.fir.FirAnnotationContainer +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator import org.jetbrains.kotlin.fir.declarations.* @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction -import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType @@ -236,7 +235,7 @@ class Fir2IrDeclarationStorage( internal fun findIrParent(callableDeclaration: FirCallableDeclaration<*>): IrDeclarationParent? { val firBasedSymbol = callableDeclaration.symbol val callableId = firBasedSymbol.callableId - return findIrParent(callableId.packageName, callableId.classId, firBasedSymbol) + return findIrParent(callableId.packageName, callableDeclaration.containingClass()?.classId, firBasedSymbol) } private fun IrDeclaration.setAndModifyParent(irParent: IrDeclarationParent?) { @@ -977,7 +976,8 @@ class Fir2IrDeclarationStorage( val firConstructor = firConstructorSymbol.fir getCachedIrConstructor(firConstructor)?.let { return it.symbol } val signature = signatureComposer.composeSignature(firConstructor) - val irParent = findIrParent(firConstructor) as IrClass + val irParent = findIrParent(firConstructor) as? IrClass + ?: error("sadsad") val parentOrigin = irParent.origin if (signature != null) { symbolTable.referenceConstructorIfAny(signature)?.let { irConstructorSymbol -> @@ -1100,7 +1100,7 @@ class Fir2IrDeclarationStorage( symbolTable.declareProperty(signature, { symbol }) { val isFakeOverride = firPropertySymbol.isFakeOverride && - firPropertySymbol.callableId != firPropertySymbol.overriddenSymbol?.callableId + firPropertySymbol.dispatchReceiverClassOrNull() != firPropertySymbol.overriddenSymbol?.dispatchReceiverClassOrNull() Fir2IrLazyProperty( components, startOffset, endOffset, declarationOrigin, fir, irParent.fir, symbol, isFakeOverride ).apply { @@ -1154,7 +1154,7 @@ class Fir2IrDeclarationStorage( is FirEnumEntry -> { classifierStorage.getCachedIrEnumEntry(firDeclaration)?.let { return it.symbol } val containingFile = firProvider.getFirCallableContainerFile(firVariableSymbol) - val irParentClass = firVariableSymbol.callableId.classId?.let { findIrClass(it) } + val irParentClass = firDeclaration.containingClass()?.classId?.let { findIrClass(it) } classifierStorage.createIrEnumEntry( firDeclaration, irParent = irParentClass, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 73f63c70351..95e1f9f9970 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend.generators import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.psi @@ -401,9 +402,9 @@ class CallAndReferenceGenerator( return null } val resolvedReference = callableReferenceAccess.calleeReference as FirResolvedNamedReference - val callableId = (resolvedReference.resolvedSymbol as FirCallableSymbol<*>).callableId + val firCallableSymbol = resolvedReference.resolvedSymbol as FirCallableSymbol<*> // Make sure the reference indeed refers to a member of that companion - if (callableId.classId != classSymbol.classId) { + if (firCallableSymbol.dispatchReceiverClassOrNull() != classSymbol.toLookupTag()) { return null } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index 915e7249a8f..d3a5aa1d379 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression @@ -124,7 +125,7 @@ internal class ClassMemberGenerator( irFunction.body = IrSyntheticBodyImpl(startOffset, endOffset, kind) } irFunction.parent is IrClass && irFunction.parentAsClass.isData -> { - val classId = firFunction?.symbol?.callableId?.classId + val classId = firFunction?.symbol?.dispatchReceiverClassOrNull()?.classId when { DataClassMembersGenerator.isComponentN(irFunction) -> firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt index bcae521cba9..dc0bb655b8d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl @@ -84,7 +85,7 @@ internal class DelegatedMemberGenerator( } } - private inline fun > S.unwrapDelegateTarget( + private inline fun > S.unwrapDelegateTarget( subClassLookupTag: ConeClassLikeLookupTag, noinline directOverridden: S.() -> List, firField: FirField, @@ -103,7 +104,8 @@ internal class DelegatedMemberGenerator( val wrappedSymbol = wrapped.symbol as? S ?: return null return when { - wrappedSymbol.isFakeOverride && wrappedSymbol.callableId.classId == firSubClass.classId -> + wrappedSymbol.isFakeOverride && + (wrappedSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag == firSubClass.symbol.toLookupTag() -> wrapped.symbol.overriddenSymbol!!.fir else -> wrapped } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index 4c8b81fadaf..e40a2f1598d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -149,16 +149,16 @@ class FakeOverrideGenerator( scope: FirTypeScope, ) where S : FirCallableSymbol, S : PossiblyFirFakeOverrideSymbol { if (originalSymbol !is S || originalSymbol in realDeclarationSymbols) return - val classId = klass.symbol.classId + val classLookupTag = klass.symbol.toLookupTag() val originalDeclaration = originalSymbol.fir - if (originalSymbol.callableId.classId == classId && !originalDeclaration.origin.fromSupertypes) return + if (originalSymbol.dispatchReceiverClassOrNull() == classLookupTag && !originalDeclaration.origin.fromSupertypes) return if (originalDeclaration.visibility == Visibilities.Private) return val origin = IrDeclarationOrigin.FAKE_OVERRIDE val baseSymbol = originalSymbol.deepestOverriddenSymbol() as S if ((originalSymbol.isFakeOverride || originalSymbol.isIntersectionOverride) && - originalSymbol.callableId.classId == classId + originalSymbol.dispatchReceiverClassOrNull() == classLookupTag ) { // Substitution case // NB: see comment above about substituted function' parent @@ -170,7 +170,7 @@ class FakeOverrideGenerator( isLocal ) irDeclaration.parent = irClass - baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classId) + baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag) result += irDeclaration } else if (originalDeclaration.allowsToHaveFakeOverrideIn(klass)) { // Trivial fake override case @@ -189,7 +189,7 @@ class FakeOverrideGenerator( return } irDeclaration.parent = irClass - baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classId) + baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag) result += irDeclaration } } @@ -199,12 +199,12 @@ class FakeOverrideGenerator( basedSymbol: S, directOverridden: FirTypeScope.(S) -> List, scope: FirTypeScope, - containingClassId: ClassId, + containingClass: ConeClassLikeLookupTag, ): List { if (!symbol.isIntersectionOverride) return listOf(basedSymbol) return scope.directOverridden(symbol).map { @Suppress("UNCHECKED_CAST") - if (it is PossiblyFirFakeOverrideSymbol<*, *> && it.isFakeOverride && it.callableId.classId == containingClassId) + if (it is PossiblyFirFakeOverrideSymbol<*, *> && it.isFakeOverride && it.dispatchReceiverClassOrNull() == containingClass) it.overriddenSymbol!! as S else it diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index ce10f5017a9..b7a1418ffd5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -5,14 +5,12 @@ package org.jetbrains.kotlin.fir.lazy -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter import org.jetbrains.kotlin.fir.backend.toIrType import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -26,7 +24,6 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.descriptors.DescriptorVisibility class Fir2IrLazyClass( components: Fir2IrComponents, @@ -140,7 +137,7 @@ class Fir2IrLazyClass( result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner } else { scope.processFunctionsByName(declaration.name) { - if (it is FirNamedFunctionSymbol && it.callableId.classId == fir.symbol.classId) { + if (it is FirNamedFunctionSymbol && it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) { if (it.isAbstractMethodOfAny()) { return@processFunctionsByName } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt index 10fb4f5abb9..31bce5491f1 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt @@ -6,16 +6,12 @@ package org.jetbrains.kotlin.fir.signaturer import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.NoMutableState +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.render -import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.ir.util.IdSignature -import org.jetbrains.kotlin.name.FqName @NoMutableState class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatureComposer { @@ -60,14 +56,12 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu } } - private val CallableId.relativeCallableName: FqName - get() = className?.child(callableName) ?: FqName.topLevel(callableName) - override fun composeSignature(declaration: FirDeclaration, containingClass: ConeClassLikeLookupTag?): IdSignature? { if (declaration is FirAnonymousObject || declaration is FirAnonymousFunction) return null if (declaration is FirRegularClass && declaration.classId.isLocal) return null if (declaration is FirCallableMemberDeclaration<*>) { - if (declaration.visibility == Visibilities.Local || declaration.symbol.callableId.classId?.isLocal == true || containingClass?.classId?.isLocal == true) return null + if (declaration.visibility == Visibilities.Local) return null + if (declaration.symbol.dispatchReceiverClassOrNull()?.classId?.isLocal == true || containingClass?.classId?.isLocal == true) return null } val builder = SignatureBuilder() try { @@ -93,11 +87,15 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu is FirCallableMemberDeclaration<*> -> { if (declaration.visibility == Visibilities.Private) return null val containingClassId = containingClass?.classId - val baseCallableId = declaration.symbol.callableId - val callableId = - if (containingClassId != null) CallableId(containingClassId, baseCallableId.callableName) else baseCallableId + + val classId = containingClassId ?: declaration.containingClass()?.classId + val packageName = classId?.packageFqName ?: declaration.symbol.callableId.packageName + val callableName = declaration.symbol.callableId.callableName + IdSignature.PublicSignature( - callableId.packageName.asString(), callableId.relativeCallableName.asString(), builder.hashId, builder.mask + packageName.asString(), + classId?.relativeClassName?.child(callableName)?.asString() ?: callableName.asString(), + builder.hashId, builder.mask ) } else -> error("Unsupported FIR declaration in signature composer: ${declaration.render()}") diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/calls/jvm/ConeEquivalentCallConflictResolver.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/calls/jvm/ConeEquivalentCallConflictResolver.kt index f5e0481e6fa..d2157e910ad 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/calls/jvm/ConeEquivalentCallConflictResolver.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/calls/jvm/ConeEquivalentCallConflictResolver.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.calls.jvm +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.calls.AbstractConeCallConflictResolver import org.jetbrains.kotlin.fir.resolve.calls.Candidate @@ -31,10 +32,10 @@ class ConeEquivalentCallConflictResolver( val result = mutableSetOf() outerLoop@ for (myCandidate in candidates) { val me = myCandidate.symbol.fir - if (me is FirCallableMemberDeclaration<*> && me.symbol.callableId.className == null) { + if (me is FirCallableMemberDeclaration<*> && me.symbol.containingClass() == null) { for (otherCandidate in result) { val other = otherCandidate.symbol.fir - if (other is FirCallableMemberDeclaration<*> && other.symbol.callableId.className == null) { + if (other is FirCallableMemberDeclaration<*> && other.symbol.containingClass() == null) { if (areEquivalentTopLevelCallables(me, myCandidate, other, otherCandidate)) { continue@outerLoop } @@ -71,4 +72,4 @@ class ConeEquivalentCallConflictResolver( else -> error("Not supported: $declaration") } } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt index 7509a66433e..e9a30612e26 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt @@ -117,13 +117,13 @@ open class FirEffectiveVisibilityResolverImpl(private val session: FirSession) : } private fun FirDeclaration.getParentClassId(): ClassId? = when (this) { - is FirCallableMemberDeclaration<*> -> this.symbol.callableId.classId + is FirCallableMemberDeclaration<*> -> this.containingClass()?.classId is FirClassLikeDeclaration<*> -> this.symbol.classId.outerClassId else -> null } private fun FirDeclaration.getClassId(): ClassId? = when (this) { - is FirCallableMemberDeclaration<*> -> this.symbol.callableId.classId + is FirCallableMemberDeclaration<*> -> this.containingClass()?.classId is FirClassLikeDeclaration<*> -> this.symbol.classId else -> null } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index 83a199e2707..a595faf950e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol @@ -38,11 +39,17 @@ abstract class FirVisibilityChecker : FirSessionComponent { } } - fun isVisible( - declaration: FirMemberDeclaration, - symbol: AbstractFirBasedSymbol<*>, + fun isVisible( + declaration: T, candidate: Candidate - ): Boolean { + ): Boolean where T : FirMemberDeclaration, T : FirSymbolOwner<*> { + val symbol = declaration.symbol + + if (symbol is PossiblyFirFakeOverrideSymbol<*, *> && symbol.overriddenSymbol != null) { + @Suppress("UNCHECKED_CAST") + return isVisible(symbol.overriddenSymbol!!.fir as T, candidate) + } + val callInfo = candidate.callInfo val useSiteFile = callInfo.containingFile val containingDeclarations = callInfo.containingDeclarations @@ -174,7 +181,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { ownerId } } - is FirCallableSymbol<*> -> callableId.classId + is FirCallableSymbol<*> -> containingClass()?.classId else -> error("Unsupported owner search for ${fir.javaClass}: ${fir.render()}") } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index c184071e083..905b6f04f7c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.inference.* -import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol @@ -226,33 +225,31 @@ internal object CheckVisibility : CheckerStage() { val symbol = candidate.symbol val declaration = symbol.fir if (declaration is FirMemberDeclaration) { - if (!checkVisibility(declaration, symbol, sink, candidate, visibilityChecker)) { + if (!checkVisibility(declaration, sink, candidate, visibilityChecker)) { return } } if (declaration is FirConstructor) { - val ownerClassId = declaration.symbol.callableId.classId!! - val provider = declaration.session.firSymbolProvider - val classSymbol = provider.getClassLikeSymbolByFqName(ownerClassId) + // TODO: Should be some other form + val classSymbol = declaration.returnTypeRef.coneTypeUnsafe().lookupTag.toSymbol(declaration.session) if (classSymbol is FirRegularClassSymbol) { if (classSymbol.fir.classKind.isSingleton) { sink.yieldDiagnostic(HiddenCandidate) } - checkVisibility(classSymbol.fir, classSymbol, sink, candidate, visibilityChecker) + checkVisibility(classSymbol.fir, sink, candidate, visibilityChecker) } } } - private suspend fun checkVisibility( - declaration: FirMemberDeclaration, - symbol: AbstractFirBasedSymbol<*>, + private suspend fun checkVisibility( + declaration: T, sink: CheckerSink, candidate: Candidate, visibilityChecker: FirVisibilityChecker - ): Boolean { - if (!visibilityChecker.isVisible(declaration, symbol, candidate)) { + ): Boolean where T : FirMemberDeclaration, T : FirSymbolOwner<*> { + if (!visibilityChecker.isVisible(declaration, candidate)) { sink.yieldDiagnostic(HiddenCandidate) return false } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt index fd3eef45bf6..3630cc0ef40 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.modality +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.references.FirNamedReference @@ -146,5 +147,5 @@ private fun BodyResolveComponents.isConcreteMember(supertype: ConeKotlinType, me val classSymbol = (supertype as? ConeClassLikeType)?.lookupTag?.toSymbol(session) as? FirRegularClassSymbol ?: return true if (classSymbol.fir.classKind != ClassKind.INTERFACE) return true - return member.symbol.unwrapSubstitutionOverrides().callableId.classId != StandardClassIds.Any + return member.symbol.unwrapSubstitutionOverrides().dispatchReceiverClassOrNull()?.classId != StandardClassIds.Any } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt index 6c365b65288..ff7a2ab09fd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.isStatic import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction @@ -74,7 +75,7 @@ class FirSyntheticPropertiesScope( val parameter = setter.valueParameters.singleOrNull() ?: return if (setter.typeParameters.isNotEmpty() || setter.isStatic) return val parameterType = (parameter.returnTypeRef as? FirResolvedTypeRef)?.type ?: return - if (getter.symbol.callableId.classId == setter.symbol.callableId.classId) { + if (getter.symbol.dispatchReceiverClassOrNull() == setter.symbol.dispatchReceiverClassOrNull()) { if (getterReturnType.withNullability(NOT_NULL) != parameterType.withNullability(NOT_NULL)) { return } @@ -102,12 +103,16 @@ class FirSyntheticPropertiesScope( } } + val classLookupTag = getterSymbol.dispatchReceiverClassOrNull() + val packageName = classLookupTag?.classId?.packageFqName ?: getterSymbol.callableId.packageName + val className = classLookupTag?.classId?.relativeClassName + val property = buildSyntheticProperty { session = this@FirSyntheticPropertiesScope.session name = propertyName symbol = SyntheticPropertySymbol( accessorId = getterSymbol.callableId, - callableId = CallableId(getterSymbol.callableId.packageName, getterSymbol.callableId.className, propertyName) + callableId = CallableId(packageName, className, propertyName) ) delegateGetter = getter delegateSetter = matchingSetter diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt index ae5996dfd79..e825ea6c706 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt @@ -9,22 +9,21 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.isInner +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier -import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.* -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType -import org.jetbrains.kotlin.fir.resolve.typeForQualifier import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectClassId import org.jetbrains.kotlin.fir.scopes.processClassifiersByName import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeNullability -import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.withNullability import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.OperatorNameConventions @@ -190,13 +189,13 @@ class ScopeTowerLevel( } private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? { - val holderId = candidate.callableId.classId - if (holderId != null && candidate.fir.origin == FirDeclarationOrigin.ImportedFromObject) { - val symbol = session.firSymbolProvider.getClassLikeSymbolByFqName(holderId) + val lookupTag = candidate.dispatchReceiverClassOrNull() + candidate.fir.importedFromObjectClassId?.let { objectClassId -> + val symbol = session.firSymbolProvider.getClassLikeSymbolByFqName(objectClassId) if (symbol is FirRegularClassSymbol) { val resolvedQualifier = buildResolvedQualifier { - packageFqName = holderId.packageFqName - relativeClassFqName = holderId.relativeClassName + packageFqName = objectClassId.packageFqName + relativeClassFqName = objectClassId.relativeClassName this.symbol = symbol }.apply { resultType = bodyResolveComponents.typeForQualifier(this) @@ -206,9 +205,9 @@ class ScopeTowerLevel( } return when { candidate !is FirBackingFieldSymbol -> null - candidate.callableId.classId != null -> { + lookupTag != null -> { bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver { implicitReceiverValue -> - implicitReceiverValue.type.classId == holderId + (implicitReceiverValue.type as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag == lookupTag } } else -> { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorage.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorage.kt index 282732b54c1..db9e5223a30 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorage.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorage.kt @@ -8,11 +8,10 @@ package org.jetbrains.kotlin.fir.resolve.dfa import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.modality +import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.references.FirThisReference @@ -164,14 +163,14 @@ class VariableStorage(private val session: FirSession) { property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> false property.modality != Modality.FINAL -> { val dispatchReceiver = (originalFir as? FirQualifiedAccess)?.dispatchReceiver ?: return false - val propertyClassName = (this as FirPropertySymbol).let { it.overriddenSymbol ?: it }.callableId.classId + val propertyClassLookupTag = (this as FirPropertySymbol).let { it.overriddenSymbol ?: it }.dispatchReceiverClassOrNull() val receiverType = dispatchReceiver.typeRef.coneTypeSafe()?.fullyExpandedType(session) ?: return false val receiverSymbol = receiverType.fullyExpandedType(session).lookupTag.toSymbol(session) ?: return false - val receiverClassName = receiverSymbol.classId - if (propertyClassName != receiverClassName) { + val receiverClassLookupTag = receiverSymbol.toLookupTag() + if (propertyClassLookupTag != receiverClassLookupTag) { when (val receiverFir = receiverSymbol.fir) { - is FirAnonymousObject -> true - is FirRegularClass -> receiverFir.modality == Modality.FINAL + is org.jetbrains.kotlin.fir.declarations.FirAnonymousObject -> true + is org.jetbrains.kotlin.fir.declarations.FirRegularClass -> receiverFir.modality == Modality.FINAL else -> throw IllegalStateException("Should not be here: $receiverFir") } } else false diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt index 62cb3c4d51e..254d768a19c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt @@ -5,13 +5,11 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve -import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind -import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.firProvider @@ -245,7 +243,7 @@ private class ReturnTypeCalculatorWithJump( } else { val file = provider.getFirCallableContainerFile(symbol) - val outerClasses = generateSequence(id.classId) { classId -> + val outerClasses = generateSequence(symbol.containingClass()?.classId) { classId -> classId.outerClassId }.mapTo(mutableListOf()) { provider.getFirClassifierByFqName(it) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt index 96b6cb1c8b6..973b4d7aeae 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.structure import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache @@ -74,9 +76,9 @@ internal class FileStructure( val declarations = if (from.symbol.callableId.className == null) { firFile.declarations as MutableList } else { - val classId = from.symbol.callableId.classId + val classLikeLookupTag = from.containingClass() ?: error("Class name should not be null for non-top-level & non-local declarations") - val containingClass = firIdeProvider.getFirClassifierByFqName(classId) as FirRegularClass + val containingClass = classLikeLookupTag.toSymbol(firFile.session)?.fir as FirRegularClass containingClass.declarations as MutableList } declarations.replaceFirst(from, to) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt index 28c4081318a..d9d436f897a 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt @@ -5,24 +5,26 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector -import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedBodyResolveTransformerForIDE import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider +import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedBodyResolveTransformerForIDE import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedContractsResolveTransformerForIDE import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedImplicitTypesTransformerForIDE import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled import org.jetbrains.kotlin.idea.fir.low.level.api.util.executeWithoutPCE import org.jetbrains.kotlin.idea.fir.low.level.api.util.findSourceNonLocalFirDeclaration import org.jetbrains.kotlin.idea.fir.low.level.api.util.getContainingFile -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtPsiUtil internal class FirLazyDeclarationResolver( private val firFileBuilder: FirFileBuilder @@ -132,7 +134,7 @@ internal class FirLazyDeclarationResolver( if (nonLocalDeclarationToResolve !is FirFile) { val id = when (nonLocalDeclarationToResolve) { is FirCallableDeclaration<*> -> { - nonLocalDeclarationToResolve.symbol.callableId.classId + nonLocalDeclarationToResolve.containingClass()?.classId } is FirClassLikeDeclaration<*> -> { nonLocalDeclarationToResolve.symbol.classId diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirIdeDeserializedDeclarationSourceProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirIdeDeserializedDeclarationSourceProvider.kt index ac148068fb7..0d885bd75c2 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirIdeDeserializedDeclarationSourceProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirIdeDeserializedDeclarationSourceProvider.kt @@ -10,6 +10,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSession @@ -116,7 +117,7 @@ object FirIdeDeserializedDeclarationSourceProvider { } private fun FirCallableDeclaration<*>.containingKtClass(project: Project): KtClassOrObject? = - unrollFakeOverrides().symbol.callableId.classId?.let { classByClassId(it, scope(project), project) } + unrollFakeOverrides().containingClass()?.classId?.let { classByClassId(it, scope(project), project) } private fun classByClassId(classId: ClassId, scope: GlobalSearchScope, project: Project): KtClassOrObject? { val fqName = classId.asStringForUsingInIndexes().let { classIdMapping[it] ?: it } @@ -143,4 +144,4 @@ fun FirElement.findPsi(project: Project): PsiElement? = psi ?: FirIdeDeserializedDeclarationSourceProvider.findPsi(this, project) fun FirElement.findPsi(session: FirSession): PsiElement? = - findPsi((session as FirIdeSession).project) \ No newline at end of file + findPsi((session as FirIdeSession).project) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt index c9e0d032593..57dc27adc99 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirConstructorSymbol.kt @@ -6,22 +6,24 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirConstructorSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion import org.jetbrains.kotlin.name.ClassId @@ -43,7 +45,7 @@ internal class KtFirConstructorSymbol( } override val containingClassIdIfNonLocal: ClassId? - get() = firRef.withFir { fir -> fir.symbol.callableId.classId /* TODO check if local */ } + get() = firRef.withFir { fir -> fir.containingClass()?.classId /* TODO check if local */ } override val isPrimary: Boolean get() = firRef.withFir { it.isPrimary } @@ -56,4 +58,4 @@ internal class KtFirConstructorSymbol( ?: error("ClassId should present for member declaration") return KtFirConstructorSymbolPointer(ownerClassId, isPrimary, firRef.withFir { it.createSignature() }) } -} \ No newline at end of file +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt index 3436bebd86a..981efd4e959 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirEnumEntrySymbol.kt @@ -6,12 +6,12 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.FirEnumEntry import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirEnumEntrySymbolPointer import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -35,10 +36,10 @@ internal class KtFirEnumEntrySymbol( override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) } override val containingEnumClassIdIfNonLocal: ClassId? - get() = firRef.withFir { it.symbol.callableId.classId?.takeUnless { it.isLocal } } + get() = firRef.withFir { it.containingClass()?.classId?.takeUnless { it.isLocal } } override fun createPointer(): KtSymbolPointer { KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } return KtFirEnumEntrySymbolPointer(containingEnumClassIdIfNonLocal!!, firRef.withFir { it.createSignature() }) } -} \ No newline at end of file +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt index 33e46f5be3e..897fb72a6b9 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirFunctionSymbol.kt @@ -6,22 +6,23 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirMemberFunctionSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef -import org.jetbrains.kotlin.idea.frontend.api.symbols.* +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -59,7 +60,7 @@ internal class KtFirFunctionSymbol( get() = firRef.withFir { fir -> when { fir.isLocal -> KtSymbolKind.LOCAL - fir.symbol.callableId.classId == null -> KtSymbolKind.TOP_LEVEL + fir.containingClass()?.classId == null -> KtSymbolKind.TOP_LEVEL else -> KtSymbolKind.MEMBER } } @@ -70,7 +71,7 @@ internal class KtFirFunctionSymbol( return when (symbolKind) { KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet") KtSymbolKind.MEMBER -> KtFirMemberFunctionSymbolPointer( - firRef.withFir { it.symbol.callableId.classId ?: error("ClassId should not be null for member function") }, + firRef.withFir { it.containingClass()?.classId ?: error("ClassId should not be null for member function") }, firRef.withFir { it.createSignature() } ) KtSymbolKind.NON_PROPERTY_PARAMETER -> error("KtFunction could not be a parameter") @@ -79,4 +80,4 @@ internal class KtFirFunctionSymbol( ) } } -} \ No newline at end of file +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt index 179d1965f14..9b07a20d881 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPropertySymbol.kt @@ -6,12 +6,12 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.frontend.api.ValidityToken -import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirMemberPropertySymbolPointer import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -45,7 +46,7 @@ internal class KtFirPropertySymbol( override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null } override val symbolKind: KtSymbolKind get() = firRef.withFir { fir -> - when (fir.symbol.callableId.classId) { + when (fir.containingClass()?.classId) { null -> KtSymbolKind.TOP_LEVEL else -> KtSymbolKind.MEMBER } @@ -63,10 +64,10 @@ internal class KtFirPropertySymbol( KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet") KtSymbolKind.NON_PROPERTY_PARAMETER -> TODO("Creating symbol for top level parameters is not supported yet") KtSymbolKind.MEMBER -> KtFirMemberPropertySymbolPointer( - firRef.withFir { it.symbol.callableId.classId ?: error("ClassId should not be null for member property") }, + firRef.withFir { it.containingClass()?.classId ?: error("ClassId should not be null for member property") }, firRef.withFir { it.createSignature() } ) KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(name.asString()) } } -} \ No newline at end of file +} diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenVisibilityTransformer.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenVisibilityTransformer.kt index 03385adabee..b034ea958ee 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenVisibilityTransformer.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenVisibilityTransformer.kt @@ -5,9 +5,10 @@ package org.jetbrains.kotlin.fir.plugin -import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus @@ -61,7 +62,7 @@ class AllOpenVisibilityTransformer(session: FirSession) : FirStatusTransformerEx } ?: return null val argument = annotation.arguments.firstOrNull() as? FirQualifiedAccessExpression ?: return null val symbol = (argument.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirVariableSymbol<*> ?: return null - val name = symbol.callableId.takeIf { it.classId == VisibilityClassId }?.callableName ?: return null + val name = symbol.takeIf { it.containingClass()?.classId == VisibilityClassId }?.callableId?.callableName ?: return null return when (name) { PublicName -> Visibilities.Public InternalName -> Visibilities.Internal From 09b7237ae5f1f3f60d56c577e7e361edca777d82 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 23 Oct 2020 17:07:17 +0300 Subject: [PATCH 036/554] FIR: Introduce importedFromObjectClassId --- .../scopes/impl/FirObjectImportedCallableScope.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt index b0143c4f190..d5b0ecbc081 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt @@ -12,10 +12,7 @@ import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.symbols.CallableId -import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -33,6 +30,8 @@ class FirObjectImportedCallableScope( val syntheticFunction = buildSimpleFunctionCopy(function) { origin = FirDeclarationOrigin.ImportedFromObject this.symbol = FirNamedFunctionSymbol(CallableId(importedClassId, name), overriddenSymbol = symbol) + }.apply { + importedFromObjectClassId = importedClassId } processor(syntheticFunction.symbol) } @@ -48,6 +47,8 @@ class FirObjectImportedCallableScope( val syntheticFunction = buildPropertyCopy(property) { origin = FirDeclarationOrigin.ImportedFromObject this.symbol = FirPropertySymbol(CallableId(importedClassId, name), overriddenSymbol = symbol) + }.apply { + importedFromObjectClassId = importedClassId } processor(syntheticFunction.symbol) } @@ -57,3 +58,7 @@ class FirObjectImportedCallableScope( override fun getClassifierNames(): Set = emptySet() } + +private object ImportedFromObjectClassIdKey : FirDeclarationDataKey() +var > + D.importedFromObjectClassId: ClassId? by FirDeclarationDataRegistry.data(ImportedFromObjectClassIdKey) From b6a312483a46cd128963f1d0fd1547020f6ba914 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 23 Oct 2020 17:09:29 +0300 Subject: [PATCH 037/554] FIR: Fix fir2symbol inconsistencies for imported properties Do not copy delegateFieldSymbol because otherwise the old symbol will be rebound to the new instance of a property --- .../kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt index d5b0ecbc081..8842b30403e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirObjectImportedCallableScope.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.fir.scopes.impl -import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope @@ -47,6 +47,7 @@ class FirObjectImportedCallableScope( val syntheticFunction = buildPropertyCopy(property) { origin = FirDeclarationOrigin.ImportedFromObject this.symbol = FirPropertySymbol(CallableId(importedClassId, name), overriddenSymbol = symbol) + this.delegateFieldSymbol = null }.apply { importedFromObjectClassId = importedClassId } From 2bdb21793f3c6131cdc8726e859fdecc91b99a59 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 26 Oct 2020 14:48:19 +0300 Subject: [PATCH 038/554] FIR: Adjust test data --- .../box/reflection/methodsFromAny/fakeOverrideToString2.kt | 1 - .../bytecodeText/multifileClasses/privateFunctionName.kt | 1 - .../irText/declarations/inlineCollectionOfInlineClass.fir.txt | 2 +- .../ir/irText/firProblems/InnerClassInAnonymous.fir.txt | 3 ++- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/testData/codegen/box/reflection/methodsFromAny/fakeOverrideToString2.kt b/compiler/testData/codegen/box/reflection/methodsFromAny/fakeOverrideToString2.kt index 80f45d65c78..587c0a2ad35 100644 --- a/compiler/testData/codegen/box/reflection/methodsFromAny/fakeOverrideToString2.kt +++ b/compiler/testData/codegen/box/reflection/methodsFromAny/fakeOverrideToString2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR, JS, NATIVE // IGNORE_BACKEND: JS_IR_ES6 // WITH_REFLECT diff --git a/compiler/testData/codegen/bytecodeText/multifileClasses/privateFunctionName.kt b/compiler/testData/codegen/bytecodeText/multifileClasses/privateFunctionName.kt index 8510f7e1603..9c8b20ce1d2 100644 --- a/compiler/testData/codegen/bytecodeText/multifileClasses/privateFunctionName.kt +++ b/compiler/testData/codegen/bytecodeText/multifileClasses/privateFunctionName.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME // FILE: part1.kt diff --git a/compiler/testData/ir/irText/declarations/inlineCollectionOfInlineClass.fir.txt b/compiler/testData/ir/irText/declarations/inlineCollectionOfInlineClass.fir.txt index 15575da2ed4..38dd5a8740c 100644 --- a/compiler/testData/ir/irText/declarations/inlineCollectionOfInlineClass.fir.txt +++ b/compiler/testData/ir/irText/declarations/inlineCollectionOfInlineClass.fir.txt @@ -92,7 +92,7 @@ FILE fqName: fileName:/inlineCollectionOfInlineClass.kt $this: VALUE_PARAMETER name: type:.InlineMutableSet BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .InlineMutableSet' - CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.Set' type=kotlin.Int origin=GET_PROPERTY + CALL 'public abstract fun (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.Int origin=GET_PROPERTY $this: CALL 'private final fun (): kotlin.collections.MutableSet<.IT> declared in .InlineMutableSet' type=kotlin.collections.MutableSet<.IT> origin=GET_PROPERTY $this: GET_VAR ': .InlineMutableSet declared in .InlineMutableSet.' type=.InlineMutableSet origin=null FUN name:contains visibility:public modality:FINAL <> ($this:.InlineMutableSet, element:.IT) returnType:kotlin.Boolean [operator] diff --git a/compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.fir.txt b/compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.fir.txt index b0bf9cce90a..c6218892a32 100644 --- a/compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.fir.txt +++ b/compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.fir.txt @@ -48,10 +48,11 @@ FILE fqName: fileName:/InnerClassInAnonymous.kt other: CALL 'public final fun (): kotlin.String declared in .box.' type=kotlin.String origin=GET_PROPERTY $this: GET_VAR ': .box. declared in .box.' type=.box. origin=null PROPERTY FAKE_OVERRIDE name:s visibility:public modality:FINAL [fake_override,val] - FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> () returnType:kotlin.String [fake_override] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.box..Base) returnType:kotlin.String [fake_override] correspondingProperty: PROPERTY FAKE_OVERRIDE name:s visibility:public modality:FINAL [fake_override,val] overridden: public final fun (): kotlin.String declared in .box..Base + $this: VALUE_PARAMETER name: type:.box..Base FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any From 923bb3b6740962dc937ce530ce8bd5953090f2de Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 26 Oct 2020 14:55:39 +0300 Subject: [PATCH 039/554] FIR2IR: Mute failing bb test ^KT-42946 Open --- .../testData/codegen/box/specialBuiltins/explicitSuperCall.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/testData/codegen/box/specialBuiltins/explicitSuperCall.kt b/compiler/testData/codegen/box/specialBuiltins/explicitSuperCall.kt index 6c0a3b7f566..eb8cf9326cf 100644 --- a/compiler/testData/codegen/box/specialBuiltins/explicitSuperCall.kt +++ b/compiler/testData/codegen/box/specialBuiltins/explicitSuperCall.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND_FIR: JVM_IR // KJS_WITH_FULL_RUNTIME // IGNORE_BACKEND: NATIVE From 2105a041a5f9489647d8207139f66ce9c5cac23d Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 26 Oct 2020 15:21:10 +0300 Subject: [PATCH 040/554] FIR: Optimize usages of `containingClass` and its implementation --- .../fir/java/FirJavaVisibilityChecker.kt | 4 +- .../kotlin/fir/FirVisibilityChecker.kt | 41 +++++++++---------- .../fir/resolve/calls/tower/TowerLevels.kt | 3 +- .../org/jetbrains/kotlin/fir/ClassMembers.kt | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt index b8caf7d1368..118346cea64 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaVisibilityChecker.kt @@ -12,9 +12,9 @@ import org.jetbrains.kotlin.fir.FirVisibilityChecker import org.jetbrains.kotlin.fir.NoMutableState import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.getOwnerId import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol -import org.jetbrains.kotlin.name.ClassId @NoMutableState object FirJavaVisibilityChecker : FirVisibilityChecker() { @@ -22,7 +22,6 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() { declarationVisibility: Visibility, symbol: AbstractFirBasedSymbol<*>, useSiteFile: FirFile, - ownerId: ClassId?, containingDeclarations: List, candidate: Candidate, session: FirSession @@ -32,6 +31,7 @@ object FirJavaVisibilityChecker : FirVisibilityChecker() { if (symbol.packageFqName() == useSiteFile.packageFqName) { true } else { + val ownerId = symbol.getOwnerId() ownerId != null && canSeeProtectedMemberOf(containingDeclarations, candidate.dispatchReceiverValue, ownerId, session) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index a595faf950e..f36276465f4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -30,7 +30,6 @@ abstract class FirVisibilityChecker : FirSessionComponent { declarationVisibility: Visibility, symbol: AbstractFirBasedSymbol<*>, useSiteFile: FirFile, - ownerId: ClassId?, containingDeclarations: List, candidate: Candidate, session: FirSession @@ -55,13 +54,14 @@ abstract class FirVisibilityChecker : FirSessionComponent { val containingDeclarations = callInfo.containingDeclarations val session = callInfo.session val provider = session.firProvider - val ownerId = symbol.getOwnerId() + return when (declaration.visibility) { Visibilities.Internal -> { declaration.session == callInfo.session } Visibilities.Private, Visibilities.PrivateToThis -> { + val ownerId = symbol.getOwnerId() if (declaration.session == callInfo.session) { if (ownerId == null || declaration is FirConstructor && declaration.isFromSealedClass) { val candidateFile = when (symbol) { @@ -81,6 +81,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { } Visibilities.Protected -> { + val ownerId = symbol.getOwnerId() ownerId != null && canSeeProtectedMemberOf(containingDeclarations, candidate.dispatchReceiverValue, ownerId, session) } @@ -88,7 +89,6 @@ abstract class FirVisibilityChecker : FirSessionComponent { declaration.visibility, symbol, useSiteFile, - ownerId, containingDeclarations, candidate, session @@ -100,7 +100,6 @@ abstract class FirVisibilityChecker : FirSessionComponent { declarationVisibility: Visibility, symbol: AbstractFirBasedSymbol<*>, useSiteFile: FirFile, - ownerId: ClassId?, containingDeclarations: List, candidate: Candidate, session: FirSession @@ -171,23 +170,6 @@ abstract class FirVisibilityChecker : FirSessionComponent { (name == "monitorEnter" || name == "monitorExit") } - private fun AbstractFirBasedSymbol<*>.getOwnerId(): ClassId? { - return when (this) { - is FirClassLikeSymbol<*> -> { - val ownerId = classId.outerClassId - if (classId.isLocal) { - ownerId?.asLocal() ?: classId - } else { - ownerId - } - } - is FirCallableSymbol<*> -> containingClass()?.classId - else -> error("Unsupported owner search for ${fir.javaClass}: ${fir.render()}") - } - } - - private fun ClassId.asLocal(): ClassId = ClassId(packageFqName, relativeClassName, true) - protected fun canSeeProtectedMemberOf( containingDeclarationOfUseSite: List, dispatchReceiver: ReceiverValue?, @@ -214,3 +196,20 @@ abstract class FirVisibilityChecker : FirSessionComponent { } val FirSession.visibilityChecker: FirVisibilityChecker by FirSession.sessionComponentAccessor() + +fun AbstractFirBasedSymbol<*>.getOwnerId(): ClassId? { + return when (this) { + is FirClassLikeSymbol<*> -> { + val ownerId = classId.outerClassId + if (classId.isLocal) { + ownerId?.asLocal() ?: classId + } else { + ownerId + } + } + is FirCallableSymbol<*> -> containingClass()?.classId + else -> error("Unsupported owner search for ${fir.javaClass}: ${fir.render()}") + } +} + +private fun ClassId.asLocal(): ClassId = ClassId(packageFqName, relativeClassName, true) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt index e825ea6c706..c18f88ac262 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt @@ -189,7 +189,6 @@ class ScopeTowerLevel( } private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? { - val lookupTag = candidate.dispatchReceiverClassOrNull() candidate.fir.importedFromObjectClassId?.let { objectClassId -> val symbol = session.firSymbolProvider.getClassLikeSymbolByFqName(objectClassId) if (symbol is FirRegularClassSymbol) { @@ -203,6 +202,8 @@ class ScopeTowerLevel( return ExpressionReceiverValue(resolvedQualifier) } } + + val lookupTag = candidate.dispatchReceiverClassOrNull() return when { candidate !is FirBackingFieldSymbol -> null lookupTag != null -> { diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt index fa37e7f6bab..fc727bdabc0 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt @@ -19,7 +19,7 @@ fun FirCallableSymbol<*>.dispatchReceiverClassOrNull(): ConeClassLikeLookupTag? fun FirCallableDeclaration<*>.dispatchReceiverClassOrNull(): ConeClassLikeLookupTag? { if (this !is FirCallableMemberDeclaration<*>) return null - if (symbol.isIntersectionOverride && dispatchReceiverType is ConeIntersectionType) return symbol.overriddenSymbol!!.fir.dispatchReceiverClassOrNull() + if (dispatchReceiverType is ConeIntersectionType && symbol.isIntersectionOverride) return symbol.overriddenSymbol!!.fir.dispatchReceiverClassOrNull() return (dispatchReceiverType as? ConeClassLikeType)?.lookupTag } From 2589de6c49914647c070a98e88f76fa3d50b90b7 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 27 Oct 2020 10:50:07 +0300 Subject: [PATCH 041/554] FIR: Refine delegated members introduced to use-site scope - Do not add hashCode/equals/toString - Do not add privates and ones that are already declared --- .../kotlin/fir/backend/ConversionUtils.kt | 6 +- .../generators/DelegatedMemberGenerator.kt | 4 - .../kotlin/fir/resolve/SamResolution.kt | 13 +- .../kotlin/fir/scopes/KotlinScopeProvider.kt | 8 +- .../scopes/impl/FirDelegatedMemberScope.kt | 61 ++++++- .../jetbrains/kotlin/fir/scopes/FirScope.kt | 8 + .../delegatedGenericImplementation.fir.txt | 84 +++------- .../classes/delegatedImplementation.fir.txt | 72 +++------ ...gatedImplementationOfJavaInterface.fir.txt | 30 +--- ...ImplementationWithExplicitOverride.fir.txt | 30 +--- ...itNotNullOnDelegatedImplementation.fir.txt | 150 ++++-------------- .../ir/irText/declarations/kt35550.fir.txt | 42 ++--- .../parameters/delegatedMembers.fir.txt | 42 ++--- .../ir/irText/types/javaWildcardType.fir.txt | 42 ++--- .../irText/types/rawTypeInSignature.fir.txt | 30 +--- 15 files changed, 212 insertions(+), 410 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 3960f0d2dc4..5c8b40313e5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.scopes.ProcessorAction -import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope @@ -239,10 +238,7 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols( return@processDirectlyOverriddenFunctions ProcessorAction.NEXT } - val unwrapped = - it.fir.delegatedWrapperData?.takeIf { it.containingClass == containingClass.symbol.toLookupTag() }?.wrapped?.symbol ?: it - - val overridden = declarationStorage.getIrFunctionSymbol(unwrapped.unwrapSubstitutionOverrides()) + val overridden = declarationStorage.getIrFunctionSymbol(it.unwrapSubstitutionOverrides()) overriddenSet += overridden as IrSimpleFunctionSymbol ProcessorAction.NEXT } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt index dc0bb655b8d..380d9ff6582 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol -import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.ir.declarations.* @@ -54,9 +53,6 @@ internal class DelegatedMemberGenerator( if (isJavaDefault(unwrapped)) { return@processAllFunctions } - if (firSubClass is FirRegularClass && firSubClass.isData && unwrapped.symbol.callableId.classId == StandardClassIds.Any) { - return@processAllFunctions - } val irSubFunction = generateDelegatedFunction( subClass, firSubClass, irField, member, functionSymbol.fir diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt index a5e435f198a..0d844106096 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap +import org.jetbrains.kotlin.fir.scopes.impl.hasTypeOf import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.StandardClassIds @@ -29,7 +30,6 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance @@ -337,17 +337,6 @@ fun FirSimpleFunction.isPublicInObject(checkOnlyName: Boolean): Boolean { } } -private fun FirValueParameter.hasTypeOf(classId: ClassId, allowNullable: Boolean): Boolean { - val classLike = when (val type = returnTypeRef.coneType) { - is ConeClassLikeType -> type - is ConeFlexibleType -> type.upperBound as? ConeClassLikeType ?: return false - else -> return false - } - - if (classLike.isMarkedNullable && !allowNullable) return false - return classLike.lookupTag.classId == classId -} - private val PUBLIC_METHOD_NAMES_IN_OBJECT = setOf("equals", "hashCode", "getClass", "wait", "notify", "notifyAll", "toString") private fun FirSimpleFunction.getFunctionTypeForAbstractMethod(): ConeLookupTagBasedType { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt index 50f5b0e8bbd..14632038c67 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt @@ -47,7 +47,8 @@ class KotlinScopeProvider( symbol.fir.scopeForSupertype( substitutor(symbol, useSiteSuperType, useSiteSession), useSiteSession, scopeSession, delegateField, - subClass = klass + subClass = klass, + decoratedDeclaredMemberScope ).let { it as? FirTypeScope ?: error("$it is expected to be FirOverrideAwareScope") } @@ -122,7 +123,8 @@ private fun FirClass<*>.scopeForSupertype( useSiteSession: FirSession, scopeSession: ScopeSession, delegateField: FirField?, - subClass: FirClass<*> + subClass: FirClass<*>, + declaredMemberScope: FirScope, ): FirTypeScope = scopeForClassImpl( substitutor, useSiteSession, @@ -133,7 +135,7 @@ private fun FirClass<*>.scopeForSupertype( ).let { if (delegateField != null) { scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) { - FirDelegatedMemberScope(it, useSiteSession, subClass, delegateField) + FirDelegatedMemberScope(it, useSiteSession, subClass, delegateField, declaredMemberScope) } } else { it diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt index 9614936addc..569ed070e76 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt @@ -6,13 +6,19 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.defaultType -import org.jetbrains.kotlin.fir.scopes.FirTypeScope -import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.ConeFlexibleType +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.isMarkedNullable +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name class FirDelegatedMemberScope( @@ -20,22 +26,31 @@ class FirDelegatedMemberScope( private val session: FirSession, private val containingClass: FirClass<*>, private val delegateField: FirField, + private val declaredMemberScope: FirScope, ) : FirTypeScope() { private val delegatedFunctionCache = mutableMapOf() private val delegatedPropertyCache = mutableMapOf() private val dispatchReceiverType = containingClass.defaultType() + private val overrideChecker = FirStandardOverrideChecker(session) override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { useSiteScope.processFunctionsByName(name) processor@{ functionSymbol -> - if (functionSymbol !is FirNamedFunctionSymbol) { + if (functionSymbol !is FirNamedFunctionSymbol || functionSymbol.fir.isPublicInAny()) { processor(functionSymbol) return@processor } + val original = functionSymbol.fir - if (original.modality == Modality.FINAL) { + if (original.modality == Modality.FINAL || original.visibility == Visibilities.Private) { processor(functionSymbol) return@processor } + + if (declaredMemberScope.getFunctions(name).any { it is FirNamedFunctionSymbol && overrideChecker.isOverriddenFunction(it.fir, original) }) { + processor(functionSymbol) + return@processor + } + val delegatedSymbol = delegatedFunctionCache.getOrPut(functionSymbol) { val newSymbol = FirNamedFunctionSymbol( functionSymbol.callableId, @@ -61,11 +76,19 @@ class FirDelegatedMemberScope( processor(propertySymbol) return@processor } + val original = propertySymbol.fir - if (original.modality == Modality.FINAL) { + + if (original.modality == Modality.FINAL || original.visibility == Visibilities.Private) { processor(propertySymbol) return@processor } + + if (declaredMemberScope.getProperties(name).any { it is FirPropertySymbol && overrideChecker.isOverriddenProperty(it.fir, original) }) { + processor(propertySymbol) + return@processor + } + val delegatedSymbol = delegatedPropertyCache.getOrPut(propertySymbol) { FirFakeOverrideGenerator.createCopyForFirProperty( FirPropertySymbol( @@ -133,3 +156,31 @@ class DelegatedWrapperData>( ) var > D.delegatedWrapperData: DelegatedWrapperData? by FirDeclarationDataRegistry.data(DelegatedWrapperDataKey) + + +// From the definition of function interfaces in the Java specification (pt. 9.8): +// "methods that are members of I that do not have the same signature as any public instance method of the class Object" +// It means that if an interface declares `int hashCode()` then the method won't be taken into account when +// checking if the interface is SAM. +fun FirSimpleFunction.isPublicInAny(): Boolean { + if (name.asString() !in PUBLIC_METHOD_NAMES_IN_ANY) return false + + return when (name.asString()) { + "hashCode", "toString" -> valueParameters.isEmpty() + "equals" -> valueParameters.singleOrNull()?.hasTypeOf(StandardClassIds.Any, allowNullable = true) == true + else -> error("Unexpected method name: $name") + } +} + +fun FirValueParameter.hasTypeOf(classId: ClassId, allowNullable: Boolean): Boolean { + val classLike = when (val type = returnTypeRef.coneType) { + is ConeClassLikeType -> type + is ConeFlexibleType -> type.upperBound as? ConeClassLikeType ?: return false + else -> return false + } + + if (classLike.isMarkedNullable && !allowNullable) return false + return classLike.lookupTag.classId == classId +} + +private val PUBLIC_METHOD_NAMES_IN_ANY = setOf("equals", "hashCode", "toString") diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt index 533a509d3c8..ef5edfa1019 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt @@ -35,6 +35,14 @@ abstract class FirScope { open fun mayContainName(name: Name) = true } +fun FirScope.getFunctions(name: Name): List> = mutableListOf>().apply { + processFunctionsByName(name, this::add) +} + +fun FirScope.getProperties(name: Name): List> = mutableListOf>().apply { + processPropertiesByName(name, this::add) +} + fun FirTypeScope.processOverriddenFunctionsAndSelf( functionSymbol: FirFunctionSymbol<*>, processor: (FirFunctionSymbol<*>) -> ProcessorAction diff --git a/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt b/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt index 865f37c1eeb..ccdc5eb4067 100644 --- a/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt @@ -63,35 +63,6 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt receiver: GET_VAR ': .Test1.Test1> declared in .Test1.foo' type=.Test1.Test1> origin=null a: GET_VAR 'a: E of .Test1 declared in .Test1.foo' type=E of .Test1 origin=null b: GET_VAR 'b: B of .Test1.foo declared in .Test1.foo' type=B of .Test1.foo origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Test1.Test1>, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test1.Test1> - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Test1' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test1> visibility:local [final]' type=.IBase.Test1> origin=null - receiver: GET_VAR ': .Test1.Test1> declared in .Test1.equals' type=.Test1.Test1> origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Test1.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Test1.Test1>) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test1.Test1> - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Test1' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test1> visibility:local [final]' type=.IBase.Test1> origin=null - receiver: GET_VAR ': .Test1.Test1> declared in .Test1.hashCode' type=.Test1.Test1> origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Test1.Test1>) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test1.Test1> - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Test1' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test1> visibility:local [final]' type=.IBase.Test1> origin=null - receiver: GET_VAR ': .Test1.Test1> declared in .Test1.toString' type=.Test1.Test1> origin=null PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN ($this:.Test1.Test1>, $receiver:C of .Test1.) returnType:kotlin.collections.Map.Test1, C of .Test1.>? correspondingProperty: PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] @@ -138,6 +109,19 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt $receiver: GET_VAR ': kotlin.collections.List.Test1.> declared in .Test1.' type=kotlin.collections.List.Test1.> origin=null : GET_VAR ': D of .Test1.? declared in .Test1.' type=D of .Test1.? origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test1> visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:Test2 modality:FINAL visibility:public superTypes:[.IBase] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Test2 CONSTRUCTOR visibility:public <> (j:.IBase) returnType:.Test2 [primary] @@ -181,35 +165,6 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt receiver: GET_VAR ': .Test2 declared in .Test2.foo' type=.Test2 origin=null a: GET_VAR 'a: kotlin.String declared in .Test2.foo' type=kotlin.String origin=null b: GET_VAR 'b: B of .Test2.foo declared in .Test2.foo' type=B of .Test2.foo origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Test2, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test2 - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Test2' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.equals' type=.Test2 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Test2.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Test2) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Test2' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.hashCode' type=.Test2 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Test2) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Test2' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.toString' type=.Test2 origin=null PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN ($this:.Test2, $receiver:C of .Test2.) returnType:kotlin.collections.Map.Test2.>? correspondingProperty: PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] @@ -256,3 +211,16 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt $receiver: GET_VAR ': kotlin.collections.List.Test2.> declared in .Test2.' type=kotlin.collections.List.Test2.> origin=null : GET_VAR ': D of .Test2.? declared in .Test2.' type=D of .Test2.? origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt b/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt index 1f7658a66b0..cdb02665cd0 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt @@ -234,36 +234,20 @@ FILE fqName: fileName:/delegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null receiver: GET_VAR ': .Test1 declared in .Test1.qux' type=.Test1 origin=null $receiver: GET_VAR ': kotlin.String declared in .Test1.qux' type=kotlin.String origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Test1, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test1 + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Test1' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test1 declared in .Test1.equals' type=.Test1 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Test1.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Test1) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test1 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Test1' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test1 declared in .Test1.hashCode' type=.Test1 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Test1) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test1 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Test1' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test1 declared in .Test1.toString' type=.Test1 origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:Test2 modality:FINAL visibility:public superTypes:[.IBase; .IOther] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Test2 CONSTRUCTOR visibility:public <> () returnType:.Test2 [primary] @@ -309,35 +293,6 @@ FILE fqName: fileName:/delegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null receiver: GET_VAR ': .Test2 declared in .Test2.qux' type=.Test2 origin=null $receiver: GET_VAR ': kotlin.String declared in .Test2.qux' type=kotlin.String origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Test2, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test2 - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Test2' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.equals' type=.Test2 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Test2.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Test2) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Test2' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.hashCode' type=.Test2 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Test2) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Test2' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.toString' type=.Test2 origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] PROPERTY DELEGATED_MEMBER name:x visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Test2) returnType:kotlin.String @@ -412,3 +367,16 @@ FILE fqName: fileName:/delegatedImplementation.kt $receiver: GET_VAR ': kotlin.Byte declared in .Test2.' type=kotlin.Byte origin=null : GET_VAR ': kotlin.Int declared in .Test2.' type=kotlin.Int origin=null FIELD DELEGATE name:<$$delegate_1> type:.IOther visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt b/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt index dd5d8c80a02..fa36ada9640 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt @@ -77,33 +77,17 @@ FILE fqName: fileName:/delegatedImplementationOfJavaInterface.kt CALL 'public abstract fun returnsFlexible (): kotlin.String? declared in .J' type=kotlin.String? origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null receiver: GET_VAR ': .Test declared in .Test.returnsFlexible' type=.Test origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Test, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Test' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null - receiver: GET_VAR ': .Test declared in .Test.equals' type=.Test origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Test.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Test) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Test' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null - receiver: GET_VAR ': .Test declared in .Test.hashCode' type=.Test origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Test) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Test' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null - receiver: GET_VAR ': .Test declared in .Test.toString' type=.Test origin=null - FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt index 3265f6c05ef..a30487d58ad 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt @@ -69,33 +69,17 @@ FILE fqName: fileName:/delegatedImplementationWithExplicitOverride.kt CALL 'public abstract fun foo (): kotlin.Unit declared in .IFooBar' type=kotlin.Unit origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final]' type=.IFooBar origin=null receiver: GET_VAR ': .C declared in .C.foo' type=.C origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.C, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.C + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .C' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final]' type=.IFooBar origin=null - receiver: GET_VAR ': .C declared in .C.equals' type=.C origin=null - other: GET_VAR 'other: kotlin.Any? declared in .C.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.C - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .C' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final]' type=.IFooBar origin=null - receiver: GET_VAR ': .C declared in .C.hashCode' type=.C origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.C - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .C' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final]' type=.IFooBar origin=null - receiver: GET_VAR ': .C declared in .C.toString' type=.C origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt index c7858df0dce..cb48aec5b08 100644 --- a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt @@ -136,36 +136,20 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt CALL 'public abstract fun foo (): kotlin.String declared in .IFoo' type=kotlin.String origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestJFoo declared in .TestJFoo.foo' type=.TestJFoo origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.TestJFoo, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestJFoo + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .TestJFoo' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestJFoo declared in .TestJFoo.equals' type=.TestJFoo origin=null - other: GET_VAR 'other: kotlin.Any? declared in .TestJFoo.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.TestJFoo) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestJFoo - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .TestJFoo' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestJFoo declared in .TestJFoo.hashCode' type=.TestJFoo origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.TestJFoo) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestJFoo - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .TestJFoo' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestJFoo declared in .TestJFoo.toString' type=.TestJFoo origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:TestK1 modality:FINAL visibility:public superTypes:[.IFoo] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.TestK1 CONSTRUCTOR visibility:public <> () returnType:.TestK1 [primary] @@ -184,36 +168,20 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt CALL 'public abstract fun foo (): kotlin.String declared in .IFoo' type=kotlin.String origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK1 declared in .TestK1.foo' type=.TestK1 origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.TestK1, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK1 + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .TestK1' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK1 declared in .TestK1.equals' type=.TestK1 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .TestK1.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.TestK1) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK1 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .TestK1' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK1 declared in .TestK1.hashCode' type=.TestK1 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.TestK1) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK1 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .TestK1' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK1 declared in .TestK1.toString' type=.TestK1 origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:TestK2 modality:FINAL visibility:public superTypes:[.IFoo] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.TestK2 CONSTRUCTOR visibility:public <> () returnType:.TestK2 [primary] @@ -232,36 +200,20 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt CALL 'public abstract fun foo (): kotlin.String declared in .IFoo' type=kotlin.String origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK2 declared in .TestK2.foo' type=.TestK2 origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.TestK2, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK2 + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .TestK2' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK2 declared in .TestK2.equals' type=.TestK2 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .TestK2.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.TestK2) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .TestK2' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK2 declared in .TestK2.hashCode' type=.TestK2 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.TestK2) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .TestK2' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK2 declared in .TestK2.toString' type=.TestK2 origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:TestK3 modality:FINAL visibility:public superTypes:[.IFoo] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.TestK3 CONSTRUCTOR visibility:public <> () returnType:.TestK3 [primary] @@ -280,36 +232,20 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt CALL 'public abstract fun foo (): kotlin.String declared in .IFoo' type=kotlin.String origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK3 declared in .TestK3.foo' type=.TestK3 origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.TestK3, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK3 + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .TestK3' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK3 declared in .TestK3.equals' type=.TestK3 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .TestK3.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.TestK3) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK3 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .TestK3' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK3 declared in .TestK3.hashCode' type=.TestK3 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.TestK3) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK3 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .TestK3' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK3 declared in .TestK3.toString' type=.TestK3 origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any CLASS CLASS name:TestK4 modality:FINAL visibility:public superTypes:[.IFoo] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.TestK4 CONSTRUCTOR visibility:public <> () returnType:.TestK4 [primary] @@ -328,33 +264,17 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt CALL 'public abstract fun foo (): kotlin.String declared in .IFoo' type=kotlin.String origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK4 declared in .TestK4.foo' type=.TestK4 origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.TestK4, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK4 + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .TestK4' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK4 declared in .TestK4.equals' type=.TestK4 origin=null - other: GET_VAR 'other: kotlin.Any? declared in .TestK4.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.TestK4) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK4 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .TestK4' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK4 declared in .TestK4.hashCode' type=.TestK4 origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.TestK4) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.TestK4 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .TestK4' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null - receiver: GET_VAR ': .TestK4 declared in .TestK4.toString' type=.TestK4 origin=null - FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/kt35550.fir.txt b/compiler/testData/ir/irText/declarations/kt35550.fir.txt index c291ac2f8ec..fca54190d10 100644 --- a/compiler/testData/ir/irText/declarations/kt35550.fir.txt +++ b/compiler/testData/ir/irText/declarations/kt35550.fir.txt @@ -33,35 +33,6 @@ FILE fqName: fileName:/kt35550.kt SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final]' type=kotlin.Unit origin=EQ receiver: GET_VAR ': .A declared in .A' type=.A origin=null value: GET_VAR 'i: .I declared in .A.' type=.I origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.A, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.A - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .A' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final]' type=.I origin=null - receiver: GET_VAR ': .A declared in .A.equals' type=.A origin=null - other: GET_VAR 'other: kotlin.Any? declared in .A.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.A) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.A - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .A' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final]' type=.I origin=null - receiver: GET_VAR ': .A declared in .A.hashCode' type=.A origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.A) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.A - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .A' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final]' type=.I origin=null - receiver: GET_VAR ': .A declared in .A.toString' type=.A origin=null PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN ($this:.A, $receiver:T of .A.) returnType:T of .A. correspondingProperty: PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] @@ -78,3 +49,16 @@ FILE fqName: fileName:/kt35550.kt receiver: GET_VAR ': .A declared in .A.' type=.A origin=null $receiver: GET_VAR ': T of .A. declared in .A.' type=T of .A. origin=null FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt index 53cbb989a23..2e25ff1cdb9 100644 --- a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt +++ b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt @@ -62,35 +62,6 @@ FILE fqName: fileName:/delegatedMembers.kt receiver: GET_VAR ': .Test.Test> declared in .Test.qux' type=.Test.Test> origin=null t: GET_VAR 't: TT of .Test declared in .Test.qux' type=TT of .Test origin=null x: GET_VAR 'x: X of .Test.qux declared in .Test.qux' type=X of .Test.qux origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Test.Test>, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test.Test> - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Test' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final]' type=.IBase.Test> origin=null - receiver: GET_VAR ': .Test.Test> declared in .Test.equals' type=.Test.Test> origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Test.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Test.Test>) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test.Test> - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Test' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final]' type=.IBase.Test> origin=null - receiver: GET_VAR ': .Test.Test> declared in .Test.hashCode' type=.Test.Test> origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Test.Test>) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.Test.Test> - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Test' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final]' type=.IBase.Test> origin=null - receiver: GET_VAR ': .Test.Test> declared in .Test.toString' type=.Test.Test> origin=null PROPERTY DELEGATED_MEMBER name:bar visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Test.Test>) returnType:kotlin.Int correspondingProperty: PROPERTY DELEGATED_MEMBER name:bar visibility:public modality:OPEN [val] @@ -103,3 +74,16 @@ FILE fqName: fileName:/delegatedMembers.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final]' type=.IBase.Test> origin=null receiver: GET_VAR ': .Test.Test> declared in .Test.' type=.Test.Test> origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/types/javaWildcardType.fir.txt b/compiler/testData/ir/irText/types/javaWildcardType.fir.txt index 5dc5a48b9b0..256454833dd 100644 --- a/compiler/testData/ir/irText/types/javaWildcardType.fir.txt +++ b/compiler/testData/ir/irText/types/javaWildcardType.fir.txt @@ -76,35 +76,6 @@ FILE fqName: fileName:/javaWildcardType.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null receiver: GET_VAR ': .C declared in .C.jg2' type=.C origin=null c: GET_VAR 'c: kotlin.collections.Collection? declared in .C.jg2' type=kotlin.collections.Collection? origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.C, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.C - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .C' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null - receiver: GET_VAR ': .C declared in .C.equals' type=.C origin=null - other: GET_VAR 'other: kotlin.Any? declared in .C.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.C - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .C' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null - receiver: GET_VAR ': .C declared in .C.hashCode' type=.C origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.C - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .C' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null - receiver: GET_VAR ': .C declared in .C.toString' type=.C origin=null FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final] FUN DELEGATED_MEMBER name:kf1 visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.collections.Collection overridden: @@ -145,3 +116,16 @@ FILE fqName: fileName:/javaWildcardType.kt receiver: GET_VAR ': .C declared in .C.kg2' type=.C origin=null c: GET_VAR 'c: kotlin.collections.Collection declared in .C.kg2' type=kotlin.collections.Collection origin=null FIELD DELEGATE name:<$$delegate_1> type:.K visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt b/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt index b01fe5a3155..30b0c189dc0 100644 --- a/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt +++ b/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt @@ -163,33 +163,17 @@ FILE fqName: fileName:/rawTypeInSignature.kt CALL 'public abstract fun returnsRawGenericOut (): .GenericOut<*>? declared in .JRaw' type=.GenericOut<*>? origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final]' type=.JRaw origin=null receiver: GET_VAR ': .KRaw declared in .KRaw.returnsRawGenericOut' type=.KRaw origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.KRaw, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.KRaw + $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .KRaw' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final]' type=.JRaw origin=null - receiver: GET_VAR ': .KRaw declared in .KRaw.equals' type=.KRaw origin=null - other: GET_VAR 'other: kotlin.Any? declared in .KRaw.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.KRaw) returnType:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.KRaw - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .KRaw' - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final]' type=.JRaw origin=null - receiver: GET_VAR ': .KRaw declared in .KRaw.hashCode' type=.KRaw origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.KRaw) returnType:kotlin.String + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:.KRaw - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .KRaw' - CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final]' type=.JRaw origin=null - receiver: GET_VAR ': .KRaw declared in .KRaw.toString' type=.KRaw origin=null - FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final] + $this: VALUE_PARAMETER name: type:kotlin.Any From e9669bf5cb7ce7ae7339baa9485ccd193efe103f Mon Sep 17 00:00:00 2001 From: "nataliya.valtman" Date: Wed, 28 Oct 2020 11:30:28 +0300 Subject: [PATCH 042/554] fix unstable IncrementalFileToPathConverterTest tests --- .../storage/IncrementalFileToPathConverter.kt | 1 + .../IncrementalFileToPathConverterTest.kt | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt b/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt index 0e4bf9b6277..8f4441bbf00 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverter.kt @@ -27,6 +27,7 @@ open class IncrementalFileToPathConverter(val rootProjectDir: File?) : FileToPat private companion object { private const val PROJECT_DIR_PLACEHOLDER = "${'$'}PROJECT_DIR$" + //use only for prefix length because it OS dependent private const val PATH_PREFIX = "$PROJECT_DIR_PLACEHOLDER/" } diff --git a/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt b/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt index b049077b810..cfe017e0426 100644 --- a/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt +++ b/build-common/test/org/jetbrains/kotlin/incremental/storage/IncrementalFileToPathConverterTest.kt @@ -10,45 +10,46 @@ import org.junit.Test import java.io.File internal class IncrementalFileToPathConverterTest : TestWithWorkingDir() { + val separator: String = File.separator @Test fun testPathTransform() { val relativeFilePath = "testFile.txt" val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath) - assertEquals("${'$'}PROJECT_DIR${'$'}/$relativeFilePath", transformedPath) + assertEquals("${'$'}PROJECT_DIR${'$'}$separator$relativeFilePath", transformedPath) } @Test fun testComplicatedProjectRootPath() { val relativeFilePath = "testFile.txt" - val transformedPath = testPathTransformation(workingDir.resolve("first/../testDir"), relativeFilePath) + val transformedPath = testPathTransformation(workingDir.resolve("first$separator..${separator}testDir"), relativeFilePath) - assertEquals("${'$'}PROJECT_DIR${'$'}/$relativeFilePath", transformedPath) + assertEquals("${'$'}PROJECT_DIR${'$'}$separator$relativeFilePath", transformedPath) } @Test fun testInccorectProjectRootPath() { val relativeFilePath = "testFile.txt" - val transformedPath = testPathTransformation(workingDir.resolve("testDir/"), relativeFilePath) + val transformedPath = testPathTransformation(workingDir.resolve("testDir$separator"), relativeFilePath) - assertEquals("${'$'}PROJECT_DIR${'$'}/$relativeFilePath", transformedPath) + assertEquals("${'$'}PROJECT_DIR${'$'}$separator$relativeFilePath", transformedPath) } @Test fun testFileOutOfProject() { - val relativeFilePath = "../testFile.txt" + val relativeFilePath = "..${separator}testFile.txt" val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath) - assertEquals("${workingDir.absolutePath}/testFile.txt", transformedPath) + assertEquals("${workingDir.absolutePath}${separator}testFile.txt", transformedPath) } @Test fun testFileWithExtraSlash() { - val relativeFilePath = "testFile.txt/" + val relativeFilePath = "testFile.txt$separator" val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath) - assertEquals("${'$'}PROJECT_DIR${'$'}/testFile.txt", transformedPath) + assertEquals("${'$'}PROJECT_DIR${'$'}${separator}testFile.txt", transformedPath) } private fun testPathTransformation(projectRoot: File, relativeFilePath: String): String { From 09e1bed5c918bd51114f43d03dd71427193095dd Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 7 Aug 2020 10:22:11 +0900 Subject: [PATCH 043/554] Redundant 'inner' modifier: fix false positive/negative with constructor call #KT-40879 Fixed #KT-41223 Fixed #KT-41311 Fixed #KT-41680 Fixed --- .../RedundantInnerClassModifierInspection.kt | 22 +++++----- .../extendJavaNestedClass.1.java | 3 ++ .../extendJavaNestedClass.kt | 4 ++ .../extendJavaNestedInterface.1.java | 3 ++ .../extendJavaNestedInterface.1.java.after | 3 ++ .../extendJavaNestedInterface.kt | 3 ++ .../extendJavaNestedInterface.kt.after | 3 ++ .../extendJavaNestedStaticClass.1.java | 3 ++ .../extendJavaNestedStaticClass.1.java.after | 3 ++ .../extendJavaNestedStaticClass.kt | 3 ++ .../extendJavaNestedStaticClass.kt.after | 3 ++ .../hasConstructorCallOfOuterClassMember.kt | 8 ++++ .../hasConstructorCallOfOuterClassMember2.kt | 8 ++++ .../hasConstructorCallOfOuterClassMember3.kt | 7 ++++ ...onstructorCallOfOuterClassMember3.kt.after | 7 ++++ ...mberReferenceInSuperTypeConstructorCall.kt | 11 +++++ ...berReferenceInSuperTypeConstructorCall2.kt | 6 +++ .../LocalInspectionTestGenerated.java | 40 +++++++++++++++++++ 18 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.1.java create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java.after create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt.after create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java.after create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt.after create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember2.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt.after create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall.kt create mode 100644 idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall2.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantInnerClassModifierInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantInnerClassModifierInspection.kt index 46a28ffb3cc..e0d46b3d0d4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantInnerClassModifierInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantInnerClassModifierInspection.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType +import org.jetbrains.kotlin.psi.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf @@ -54,18 +55,21 @@ class RedundantInnerClassModifierInspection : AbstractKotlinInspection() { return anyDescendantOfType { expression -> when (expression) { is KtNameReferenceExpression -> { - val reference = expression.mainReference.resolve() - val referenceClass = reference?.getStrictParentOfType() - if (expression.getStrictParentOfType() != null) { - return@anyDescendantOfType reference is KtClass && reference.isInner() - || reference is KtPrimaryConstructor && referenceClass?.isInner() == true + val reference = expression.mainReference.resolve()?.let { + (it as? KtConstructor<*>)?.containingClass() ?: it } - if (referenceClass != null) { - if (referenceClass == targetClass) return@anyDescendantOfType false - if (referenceClass in outerClasses) return@anyDescendantOfType true + if (reference is PsiClass && reference.parent is PsiClass) { + return@anyDescendantOfType reference.getJavaClassDescriptor()?.isInner == true + } + val referenceContainingClass = reference?.getStrictParentOfType() + if (referenceContainingClass != null) { + if (referenceContainingClass == targetClass) return@anyDescendantOfType false + if (referenceContainingClass in outerClasses) { + return@anyDescendantOfType reference !is KtClass || reference.isInner() + } } if (!hasSuperType) return@anyDescendantOfType false - val referenceClassDescriptor = referenceClass?.descriptor as? ClassDescriptor + val referenceClassDescriptor = referenceContainingClass?.descriptor as? ClassDescriptor ?: reference?.getStrictParentOfType()?.getJavaClassDescriptor() ?: (expression.resolveToCall()?.resultingDescriptor as? SyntheticJavaPropertyDescriptor) ?.getMethod?.containingDeclaration as? ClassDescriptor diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.1.java b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.1.java new file mode 100644 index 00000000000..734a588b631 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.1.java @@ -0,0 +1,3 @@ +public class Java { + public abstract class NestedClass {} +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.kt new file mode 100644 index 00000000000..deb8d78e4ed --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.kt @@ -0,0 +1,4 @@ +// PROBLEM: none +class Test : Java() { + inner class Foo : Java.NestedClass() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java new file mode 100644 index 00000000000..8d6b55783aa --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java @@ -0,0 +1,3 @@ +public class Java { + public interface NestedInterface {} +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java.after b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java.after new file mode 100644 index 00000000000..8d6b55783aa --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.1.java.after @@ -0,0 +1,3 @@ +public class Java { + public interface NestedInterface {} +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt new file mode 100644 index 00000000000..806e71bbaf9 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt @@ -0,0 +1,3 @@ +class Test : Java() { + inner class Foo : Java.NestedInterface +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt.after b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt.after new file mode 100644 index 00000000000..9c7a31868d6 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt.after @@ -0,0 +1,3 @@ +class Test : Java() { + class Foo : Java.NestedInterface +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java new file mode 100644 index 00000000000..367b724177c --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java @@ -0,0 +1,3 @@ +public class Java { + public abstract static class NestedStaticClass {} +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java.after b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java.after new file mode 100644 index 00000000000..367b724177c --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.1.java.after @@ -0,0 +1,3 @@ +public class Java { + public abstract static class NestedStaticClass {} +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt new file mode 100644 index 00000000000..9a2bee584f0 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt @@ -0,0 +1,3 @@ +class Test : Java() { + inner class Foo2 : Java.NestedStaticClass() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt.after b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt.after new file mode 100644 index 00000000000..5391a5a8b98 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt.after @@ -0,0 +1,3 @@ +class Test : Java() { + class Foo2 : Java.NestedStaticClass() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember.kt new file mode 100644 index 00000000000..7b7d34c90dd --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember.kt @@ -0,0 +1,8 @@ +// PROBLEM: none +class Test { + private inner class Inner { + val inner2 = Inner2() + } + + private inner class Inner2 +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember2.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember2.kt new file mode 100644 index 00000000000..4f978ba4716 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember2.kt @@ -0,0 +1,8 @@ +// PROBLEM: none +class Test { + private inner class Inner { + val inner2 = Inner2() + } + + private inner class Inner2() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt new file mode 100644 index 00000000000..b87e81c2575 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt @@ -0,0 +1,7 @@ +class Test { + private inner class Inner { + val inner2 = Inner2() + } + + private class Inner2 +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt.after b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt.after new file mode 100644 index 00000000000..b32b6e22a55 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt.after @@ -0,0 +1,7 @@ +class Test { + private class Inner { + val inner2 = Inner2() + } + + private class Inner2 +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall.kt new file mode 100644 index 00000000000..bc82844c65f --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall.kt @@ -0,0 +1,11 @@ +// PROBLEM: none +abstract class Base(val x: Int) + +open class Outer(val x: Int) { + inner class Inner { + fun useX() { + object : Base(x) { + } + } + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall2.kt b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall2.kt new file mode 100644 index 00000000000..29065924d10 --- /dev/null +++ b/idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall2.kt @@ -0,0 +1,6 @@ +// PROBLEM: none +class A(private val someText: String) { + private inner class B() : C(someText) +} + +abstract class C(private val text: String) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 7752c4b1cbd..e5d4e063f74 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -7978,6 +7978,36 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/extendInnerClass2.kt"); } + @TestMetadata("extendJavaNestedClass.kt") + public void testExtendJavaNestedClass() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedClass.kt"); + } + + @TestMetadata("extendJavaNestedInterface.kt") + public void testExtendJavaNestedInterface() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedInterface.kt"); + } + + @TestMetadata("extendJavaNestedStaticClass.kt") + public void testExtendJavaNestedStaticClass() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/extendJavaNestedStaticClass.kt"); + } + + @TestMetadata("hasConstructorCallOfOuterClassMember.kt") + public void testHasConstructorCallOfOuterClassMember() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember.kt"); + } + + @TestMetadata("hasConstructorCallOfOuterClassMember2.kt") + public void testHasConstructorCallOfOuterClassMember2() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember2.kt"); + } + + @TestMetadata("hasConstructorCallOfOuterClassMember3.kt") + public void testHasConstructorCallOfOuterClassMember3() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasConstructorCallOfOuterClassMember3.kt"); + } + @TestMetadata("hasOuterClassMemberReference.kt") public void testHasOuterClassMemberReference() throws Exception { runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReference.kt"); @@ -8003,6 +8033,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReference5.kt"); } + @TestMetadata("hasOuterClassMemberReferenceInSuperTypeConstructorCall.kt") + public void testHasOuterClassMemberReferenceInSuperTypeConstructorCall() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall.kt"); + } + + @TestMetadata("hasOuterClassMemberReferenceInSuperTypeConstructorCall2.kt") + public void testHasOuterClassMemberReferenceInSuperTypeConstructorCall2() throws Exception { + runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassMemberReferenceInSuperTypeConstructorCall2.kt"); + } + @TestMetadata("hasOuterClassTypeReference.kt") public void testHasOuterClassTypeReference() throws Exception { runTest("idea/testData/inspectionsLocal/redundantInnerClassModifier/hasOuterClassTypeReference.kt"); From eb9b5da82badb26bc52e822d1bf89b5574b10b3b Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Wed, 28 Oct 2020 13:02:14 +0900 Subject: [PATCH 044/554] Kapt: Never mark static methods 'default' (KT-42915) --- .../stubs/ClassFileToSourceStubConverter.kt | 2 +- .../jetbrains/kotlin/kapt3/util/asmUtils.kt | 1 + .../testData/converter/jvmStatic.kt | 7 +++++ .../testData/converter/jvmStatic.txt | 31 +++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 47e14799614..b1e76f91cb5 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -814,7 +814,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati ElementKind.METHOD, packageFqName, visibleAnnotations, method.invisibleAnnotations, descriptor.annotations ) - if (containingClass.isInterface() && !method.isAbstract()) { + if (containingClass.isInterface() && !method.isAbstract() && !method.isStatic()) { modifiers.flags = modifiers.flags or Flags.DEFAULT } diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt index 088e1801d66..4a6c7c50258 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt @@ -39,6 +39,7 @@ internal fun ClassNode.isAnnotation() = (access and Opcodes.ACC_ANNOTATION) != 0 internal fun MethodNode.isVarargs() = (access and Opcodes.ACC_VARARGS) != 0 internal fun MethodNode.isAbstract() = (access and Opcodes.ACC_ABSTRACT) != 0 +internal fun MethodNode.isStatic() = (access and Opcodes.ACC_STATIC) != 0 internal fun FieldNode.isEnumValue() = (access and Opcodes.ACC_ENUM) != 0 diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.kt b/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.kt index b6dccdb66f5..f919195def0 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.kt @@ -11,3 +11,10 @@ class JvmStaticTest { const val three: Byte = 3.toByte() const val d: Char = 'D' } + +interface FooComponent { + companion object { + @JvmStatic + fun create(context: String): String = "foo" + } +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.txt b/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.txt index f09c3d3a89f..f92ab58e9c3 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/jvmStatic.txt @@ -1,5 +1,36 @@ import java.lang.System; +@kotlin.Metadata() +public abstract interface FooComponent { + @org.jetbrains.annotations.NotNull() + public static final FooComponent.Companion Companion = null; + + @org.jetbrains.annotations.NotNull() + public static java.lang.String create(@org.jetbrains.annotations.NotNull() + java.lang.String context) { + return null; + } + + @kotlin.Metadata() + public static final class Companion { + + @org.jetbrains.annotations.NotNull() + public final java.lang.String create(@org.jetbrains.annotations.NotNull() + java.lang.String context) { + return null; + } + + private Companion() { + super(); + } + } +} + +//////////////////// + + +import java.lang.System; + @kotlin.Metadata() public final class JvmStaticTest { public final byte three = (byte)3; From ef6b643b9c5718ce36ffc7081fc125a73f9d5d74 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 22 Oct 2020 13:42:48 +0300 Subject: [PATCH 045/554] [FIR2IR] Don't set WHILE_LOOP origin for blocks --- .../jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt | 3 ++- .../ir/irText/expressions/badBreakContinue.fir.txt | 8 ++++---- .../ir/irText/expressions/breakContinue.fir.txt | 12 ++++++------ .../expressions/breakContinueInLoopHeader.fir.txt | 14 +++++++------- .../ir/irText/expressions/whileDoWhile.fir.txt | 6 +++--- .../ir/irText/regressions/coercionInLoop.fir.txt | 2 +- .../enhancedNullabilityInForLoop.fir.txt | 2 +- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 5d36652269d..52bb921e5c4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -873,7 +873,8 @@ class Fir2IrVisitor( loopMap[whileLoop] = this label = whileLoop.label?.name condition = convertToIrExpression(whileLoop.condition) - body = whileLoop.block.convertToIrExpressionOrBlock(origin) + // NB: here we have strange origin logic, made to be compatible with FE 1.0 + body = whileLoop.block.convertToIrExpressionOrBlock(origin.takeIf { it != IrStatementOrigin.WHILE_LOOP }) loopMap.remove(whileLoop) } } diff --git a/compiler/testData/ir/irText/expressions/badBreakContinue.fir.txt b/compiler/testData/ir/irText/expressions/badBreakContinue.fir.txt index 6646171c5e2..4861247b5ec 100644 --- a/compiler/testData/ir/irText/expressions/badBreakContinue.fir.txt +++ b/compiler/testData/ir/irText/expressions/badBreakContinue.fir.txt @@ -7,14 +7,14 @@ FILE fqName: fileName:/badBreakContinue.kt BLOCK_BODY WHILE label=L1 origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null ERROR_EXPR 'Unbound loop: break@@@[ERROR_EXPR(Cannot bind label ERROR to a loop)] ' type=kotlin.Nothing ERROR_EXPR 'Unbound loop: continue@@@[ERROR_EXPR(Cannot bind label ERROR to a loop)] ' type=kotlin.Nothing FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY WHILE label=L1 origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null VAR name:lambda type:kotlin.Function0 [val] FUN_EXPR type=kotlin.Function0 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Nothing @@ -25,7 +25,7 @@ FILE fqName: fileName:/badBreakContinue.kt BLOCK_BODY WHILE label=null origin=WHILE_LOOP condition: ERROR_EXPR 'Unbound loop: break@@@[ERROR_EXPR(Cannot bind unlabeled jump to a loop)] ' type=kotlin.Nothing - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null WHILE label=null origin=WHILE_LOOP condition: ERROR_EXPR 'Unbound loop: continue@@@[ERROR_EXPR(Cannot bind unlabeled jump to a loop)] ' type=kotlin.Nothing - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null diff --git a/compiler/testData/ir/irText/expressions/breakContinue.fir.txt b/compiler/testData/ir/irText/expressions/breakContinue.fir.txt index 52bbb3be4fe..dfd2a27515b 100644 --- a/compiler/testData/ir/irText/expressions/breakContinue.fir.txt +++ b/compiler/testData/ir/irText/expressions/breakContinue.fir.txt @@ -17,19 +17,19 @@ FILE fqName: fileName:/breakContinue.kt BLOCK_BODY WHILE label=OUTER origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null WHILE label=INNER origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null BREAK label=INNER loop.label=INNER BREAK label=OUTER loop.label=OUTER BREAK label=OUTER loop.label=OUTER WHILE label=OUTER origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null WHILE label=INNER origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null CONTINUE label=INNER loop.label=INNER CONTINUE label=OUTER loop.label=OUTER CONTINUE label=OUTER loop.label=OUTER @@ -37,14 +37,14 @@ FILE fqName: fileName:/breakContinue.kt BLOCK_BODY WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true body: BREAK label=L loop.label=L BREAK label=L loop.label=L WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Nothing origin=WHILE_LOOP + body: BLOCK type=kotlin.Nothing origin=null WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true body: CONTINUE label=L loop.label=L diff --git a/compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.fir.txt b/compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.fir.txt index 89f3809e6e0..60b54f615b5 100644 --- a/compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.fir.txt +++ b/compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.fir.txt @@ -4,7 +4,7 @@ FILE fqName: fileName:/breakContinueInLoopHeader.kt BLOCK_BODY WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null WHILE label=L2 origin=WHILE_LOOP condition: BLOCK type=kotlin.Boolean origin=ELVIS VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Boolean? [val] @@ -19,13 +19,13 @@ FILE fqName: fileName:/breakContinueInLoopHeader.kt if: CONST Boolean type=kotlin.Boolean value=true then: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean GET_VAR 'val tmp_0: kotlin.Boolean? [val] declared in .test1' type=kotlin.Boolean? origin=null - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null FUN name:test2 visibility:public modality:FINAL <> (c:kotlin.Boolean?) returnType:kotlin.Unit VALUE_PARAMETER name:c index:0 type:kotlin.Boolean? BLOCK_BODY WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null WHILE label=L2 origin=WHILE_LOOP condition: BLOCK type=kotlin.Boolean origin=ELVIS VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Boolean? [val] @@ -40,13 +40,13 @@ FILE fqName: fileName:/breakContinueInLoopHeader.kt if: CONST Boolean type=kotlin.Boolean value=true then: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean GET_VAR 'val tmp_1: kotlin.Boolean? [val] declared in .test2' type=kotlin.Boolean? origin=null - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null FUN name:test3 visibility:public modality:FINAL <> (ss:kotlin.collections.List?) returnType:kotlin.Unit VALUE_PARAMETER name:ss index:0 type:kotlin.collections.List? BLOCK_BODY WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null BLOCK type=kotlin.Unit origin=FOR_LOOP VAR FOR_LOOP_ITERATOR name:tmp_2 type:kotlin.collections.Iterator [val] CALL 'public abstract fun iterator (): kotlin.collections.Iterator [operator] declared in kotlin.collections.List' type=kotlin.collections.Iterator origin=FOR_LOOP_ITERATOR @@ -75,7 +75,7 @@ FILE fqName: fileName:/breakContinueInLoopHeader.kt BLOCK_BODY WHILE label=L origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null BLOCK type=kotlin.Unit origin=FOR_LOOP VAR FOR_LOOP_ITERATOR name:tmp_4 type:kotlin.collections.Iterator [val] CALL 'public abstract fun iterator (): kotlin.collections.Iterator [operator] declared in kotlin.collections.List' type=kotlin.collections.Iterator origin=FOR_LOOP_ITERATOR @@ -105,7 +105,7 @@ FILE fqName: fileName:/breakContinueInLoopHeader.kt CONST Int type=kotlin.Int value=0 WHILE label=Outer origin=WHILE_LOOP condition: CONST Boolean type=kotlin.Boolean value=true - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null SET_VAR 'var i: kotlin.Int [var] declared in .test5' type=kotlin.Unit origin=EQ CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null $this: GET_VAR 'var i: kotlin.Int [var] declared in .test5' type=kotlin.Int origin=null diff --git a/compiler/testData/ir/irText/expressions/whileDoWhile.fir.txt b/compiler/testData/ir/irText/expressions/whileDoWhile.fir.txt index acda0e88efe..982bbd9e1ea 100644 --- a/compiler/testData/ir/irText/expressions/whileDoWhile.fir.txt +++ b/compiler/testData/ir/irText/expressions/whileDoWhile.fir.txt @@ -7,7 +7,7 @@ FILE fqName: fileName:/whileDoWhile.kt condition: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT arg0: GET_VAR 'var x: kotlin.Int [var] declared in .test' type=kotlin.Int origin=null arg1: CONST Int type=kotlin.Int value=0 - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null WHILE label=null origin=WHILE_LOOP condition: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT arg0: GET_VAR 'var x: kotlin.Int [var] declared in .test' type=kotlin.Int origin=null @@ -23,7 +23,7 @@ FILE fqName: fileName:/whileDoWhile.kt condition: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT arg0: GET_VAR 'var x: kotlin.Int [var] declared in .test' type=kotlin.Int origin=null arg1: CONST Int type=kotlin.Int value=10 - body: BLOCK type=kotlin.Int origin=WHILE_LOOP + body: BLOCK type=kotlin.Int origin=null VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val] GET_VAR 'var x: kotlin.Int [var] declared in .test' type=kotlin.Int origin=null SET_VAR 'var x: kotlin.Int [var] declared in .test' type=kotlin.Unit origin=EQ @@ -69,7 +69,7 @@ FILE fqName: fileName:/whileDoWhile.kt WHILE label=null origin=WHILE_LOOP condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean GET_VAR 'val a: kotlin.Any? [val] declared in .testSmartcastInCondition' type=kotlin.Any? origin=null - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null DO_WHILE label=null origin=DO_WHILE_LOOP body: COMPOSITE type=kotlin.Unit origin=DO_WHILE_LOOP condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean diff --git a/compiler/testData/ir/irText/regressions/coercionInLoop.fir.txt b/compiler/testData/ir/irText/regressions/coercionInLoop.fir.txt index c1bc6307f3d..fecdbd66787 100644 --- a/compiler/testData/ir/irText/regressions/coercionInLoop.fir.txt +++ b/compiler/testData/ir/irText/regressions/coercionInLoop.fir.txt @@ -12,7 +12,7 @@ FILE fqName: fileName:/coercionInLoop.kt WHILE label=null origin=WHILE_LOOP condition: CALL 'public abstract fun hasNext (): kotlin.Boolean [operator] declared in kotlin.collections.Iterator' type=kotlin.Boolean origin=null $this: GET_VAR 'val x: kotlin.collections.DoubleIterator [val] declared in .box' type=kotlin.collections.DoubleIterator origin=null - body: BLOCK type=kotlin.Int origin=WHILE_LOOP + body: BLOCK type=kotlin.Int origin=null WHEN type=kotlin.Unit origin=IF BRANCH if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ diff --git a/compiler/testData/ir/irText/types/nullChecks/enhancedNullabilityInForLoop.fir.txt b/compiler/testData/ir/irText/types/nullChecks/enhancedNullabilityInForLoop.fir.txt index a8bcb54b0c8..fafbbb8ac50 100644 --- a/compiler/testData/ir/irText/types/nullChecks/enhancedNullabilityInForLoop.fir.txt +++ b/compiler/testData/ir/irText/types/nullChecks/enhancedNullabilityInForLoop.fir.txt @@ -42,7 +42,7 @@ FILE fqName: fileName:/enhancedNullabilityInForLoop.kt WHILE label=null origin=WHILE_LOOP condition: CALL 'public abstract fun hasNext (): kotlin.Boolean [operator] declared in kotlin.collections.Iterator' type=kotlin.Boolean origin=null $this: GET_VAR 'val iterator: kotlin.collections.MutableIterator<.P?> [val] declared in .testDesugaredForInList' type=kotlin.collections.MutableIterator<.P?> origin=null - body: BLOCK type=kotlin.Unit origin=WHILE_LOOP + body: BLOCK type=kotlin.Unit origin=null VAR name:x type:.P? [val] CALL 'public abstract fun next (): T of kotlin.collections.MutableIterator [fake_override,operator] declared in kotlin.collections.MutableIterator' type=.P? origin=null $this: GET_VAR 'val iterator: kotlin.collections.MutableIterator<.P?> [val] declared in .testDesugaredForInList' type=kotlin.collections.MutableIterator<.P?> origin=null From e9a7b64ca030feba70abfaa03a8b8f6d39cdb0d4 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 23 Oct 2020 10:51:11 -0700 Subject: [PATCH 046/554] FIR2IR: use AnnotationGenerator to convert file annotations --- .../src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 52bb921e5c4..862a9cee7f5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -84,11 +84,7 @@ class Fir2IrVisitor( file.declarations.forEach { it.toIrDeclaration() } - - annotations = file.annotations.mapNotNull { - it.accept(this@Fir2IrVisitor, data) as? IrConstructorCall - } - + annotationGenerator.generate(this, file) metadata = FirMetadataSource.File(file) } } From 8f8ee88957e13aa51a53bdd61d8dd7f6c039017e Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 23 Oct 2020 11:50:03 -0700 Subject: [PATCH 047/554] FIR2IR: refactor implicit cast insertion, part 1: implicit cast --- .../fir/backend/Fir2IrImplicitCastInserter.kt | 126 ++++++++++++++++++ .../kotlin/fir/backend/Fir2IrVisitor.kt | 90 +------------ 2 files changed, 131 insertions(+), 85 deletions(-) create mode 100644 compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt new file mode 100644 index 00000000000..2653c51633c --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -0,0 +1,126 @@ +/* + * 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.fir.backend + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast +import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression +import org.jetbrains.kotlin.fir.references.FirReference +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.resolve.scope +import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.types.ConeIntersectionType +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.name.Name + +class Fir2IrImplicitCastInserter( + private val components: Fir2IrComponents, + private val visitor: Fir2IrVisitor +) : Fir2IrComponents by components, FirDefaultVisitor() { + + private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() } + + private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() } + + override fun visitElement(element: FirElement, data: IrElement): IrElement { + TODO("Should not be here: ${element.render()}") + } + + override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: IrElement): IrExpression { + return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef) + } + + internal fun convertToImplicitCastExpression( + expressionWithSmartcast: FirExpressionWithSmartcast, calleeReference: FirReference + ): IrExpression { + val originalExpression = expressionWithSmartcast.originalExpression + val value = visitor.convertToIrExpression(originalExpression) + val castTypeRef = expressionWithSmartcast.typeRef + if (calleeReference !is FirResolvedNamedReference) { + return implicitCastOrExpression(value, castTypeRef) + } + val referencedSymbol = calleeReference.resolvedSymbol + if (referencedSymbol !is FirPropertySymbol && referencedSymbol !is FirFunctionSymbol) { + return implicitCastOrExpression(value, castTypeRef) + } + + val originalTypeRef = expressionWithSmartcast.originalType + if (castTypeRef is FirResolvedTypeRef && originalTypeRef is FirResolvedTypeRef) { + val castType = castTypeRef.type + if (castType is ConeIntersectionType) { + val unwrappedSymbol = (referencedSymbol as? FirCallableSymbol)?.overriddenSymbol ?: referencedSymbol + castType.intersectedTypes.forEach { + if (it.doesContainReferencedSymbolInScope(unwrappedSymbol, calleeReference.name)) { + return implicitCastOrExpression(value, it) + } + } + } + } + return if (originalExpression is FirThisReceiverExpression && + originalExpression.calleeReference.boundSymbol is FirAnonymousFunctionSymbol + ) { + // If the original is a "this" in a local function and original.type is the same as castType, + // we still want to keep the cast. See kt-42517 + implicitCast(value, castTypeRef.toIrType()) + } else { + implicitCastOrExpression(value, castTypeRef.toIrType()) + } + } + + private fun ConeKotlinType.doesContainReferencedSymbolInScope( + referencedSymbol: AbstractFirBasedSymbol<*>, name: Name + ): Boolean { + val scope = scope(session, components.scopeSession, FakeOverrideTypeCalculator.Forced) ?: return false + var result = false + val processor = { it: FirCallableSymbol<*> -> + if (!result && it == referencedSymbol) { + result = true + } + } + when (referencedSymbol) { + is FirPropertySymbol -> scope.processPropertiesByName(name, processor) + is FirFunctionSymbol -> scope.processFunctionsByName(name, processor) + } + return result + } + + private fun implicitCastOrExpression(original: IrExpression, castType: ConeKotlinType): IrExpression { + return implicitCastOrExpression(original, castType.toIrType()) + } + + private fun implicitCastOrExpression(original: IrExpression, castType: FirTypeRef): IrExpression { + return implicitCastOrExpression(original, castType.toIrType()) + } + + internal fun implicitCastOrExpression(original: IrExpression, castType: IrType): IrExpression { + return original.takeIf { it.type == castType } ?: implicitCast(original, castType) + } + + private fun implicitCast(original: IrExpression, castType: IrType): IrExpression { + return IrTypeOperatorCallImpl( + original.startOffset, + original.endOffset, + castType, + IrTypeOperator.IMPLICIT_CAST, + castType, + original + ) + } +} diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 862a9cee7f5..0fa4fdfc3e3 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.isIteratorNext -import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator -import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor @@ -57,14 +54,14 @@ class Fir2IrVisitor( private val annotationGenerator = AnnotationGenerator(this) + private val implicitCastInserter = Fir2IrImplicitCastInserter(components, this) + private val memberGenerator = ClassMemberGenerator(components, this, conversionScope) private val operatorGenerator = OperatorExpressionGenerator(components, this, conversionScope) private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() } - private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() } - private fun applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration) override fun visitElement(element: FirElement, data: Any?): IrElement { @@ -419,87 +416,10 @@ class Fir2IrVisitor( return visitQualifiedAccessExpression(thisReceiverExpression, data) } - private fun implicitCastOrExpression(original: IrExpression, castType: ConeKotlinType): IrExpression { - return implicitCastOrExpression(original, castType.toIrType()) - } - - private fun implicitCastOrExpression(original: IrExpression, castType: FirTypeRef): IrExpression { - return implicitCastOrExpression(original, castType.toIrType()) - } - - private fun implicitCastOrExpression(original: IrExpression, castType: IrType): IrExpression { - return original.takeIf { it.type == castType } ?: implicitCast(original, castType) - } - - private fun implicitCast(original: IrExpression, castType: IrType): IrExpression { - return IrTypeOperatorCallImpl( - original.startOffset, - original.endOffset, - castType, - IrTypeOperator.IMPLICIT_CAST, - castType, - original - ) - } - - private fun ConeKotlinType.doesContainReferencedSymbolInScope( - referencedSymbol: AbstractFirBasedSymbol<*>, name: Name - ): Boolean { - val scope = scope(session, components.scopeSession, FakeOverrideTypeCalculator.Forced) ?: return false - var result = false - val processor = { it: FirCallableSymbol<*> -> - if (!result && it == referencedSymbol) { - result = true - } - } - when (referencedSymbol) { - is FirPropertySymbol -> scope.processPropertiesByName(name, processor) - is FirFunctionSymbol -> scope.processFunctionsByName(name, processor) - } - return result - } - - private fun convertToImplicitCastExpression( - expressionWithSmartcast: FirExpressionWithSmartcast, calleeReference: FirReference - ): IrExpression { - val originalExpression = expressionWithSmartcast.originalExpression - val value = convertToIrExpression(originalExpression) - val castTypeRef = expressionWithSmartcast.typeRef - if (calleeReference !is FirResolvedNamedReference) { - return implicitCastOrExpression(value, castTypeRef) - } - val referencedSymbol = calleeReference.resolvedSymbol - if (referencedSymbol !is FirPropertySymbol && referencedSymbol !is FirFunctionSymbol) { - return implicitCastOrExpression(value, castTypeRef) - } - - val originalTypeRef = expressionWithSmartcast.originalType - if (castTypeRef is FirResolvedTypeRef && originalTypeRef is FirResolvedTypeRef) { - val castType = castTypeRef.type - if (castType is ConeIntersectionType) { - val unwrappedSymbol = (referencedSymbol as? FirCallableSymbol)?.overriddenSymbol ?: referencedSymbol - castType.intersectedTypes.forEach { - if (it.doesContainReferencedSymbolInScope(unwrappedSymbol, calleeReference.name)) { - return implicitCastOrExpression(value, it) - } - } - } - } - return if (originalExpression is FirThisReceiverExpression && - originalExpression.calleeReference.boundSymbol is FirAnonymousFunctionSymbol - ) { - // If the original is a "this" in a local function and original.type is the same as castType, - // we still want to keep the cast. See kt-42517 - implicitCast(value, castTypeRef.toIrType()) - } else { - implicitCastOrExpression(value, castTypeRef.toIrType()) - } - } - override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: Any?): IrElement { // Generate the expression with the original type and then cast it to the smart cast type. val value = convertToIrExpression(expressionWithSmartcast.originalExpression) - return implicitCastOrExpression(value, expressionWithSmartcast.typeRef) + return implicitCastInserter.visitExpressionWithSmartcast(expressionWithSmartcast, value) } override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement { @@ -583,7 +503,7 @@ class Fir2IrVisitor( return when (expression) { null -> null is FirResolvedQualifier -> callGenerator.convertToGetObject(expression, callableReferenceAccess) - is FirExpressionWithSmartcast -> convertToImplicitCastExpression(expression, calleeReference) + is FirExpressionWithSmartcast -> implicitCastInserter.convertToImplicitCastExpression(expression, calleeReference) is FirFunctionCall, is FirThisReceiverExpression, is FirCallableReferenceAccess -> convertToIrExpression(expression) else -> if (expression is FirQualifiedAccessExpression && expression.explicitReceiver == null) { val variableAsFunctionMode = calleeReference is FirResolvedNamedReference && @@ -735,7 +655,7 @@ class Fir2IrVisitor( if (notNullType == originalType) { irGetLhsValue() } else { - implicitCastOrExpression( + implicitCastInserter.implicitCastOrExpression( irGetLhsValue(), firLhsVariable.returnTypeRef.resolvedTypeFromPrototype(notNullType).toIrType() ) From 8708bdec0d5d5390d5f9602f03f871f3d438196b Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 23 Oct 2020 14:45:03 -0700 Subject: [PATCH 048/554] FIR2IR: refactor implicit cast insertion, part 2: coerce-to-Unit --- .../fir/backend/Fir2IrImplicitCastInserter.kt | 33 ++++++++++++++- .../kotlin/fir/backend/Fir2IrVisitor.kt | 42 +++++-------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index 2653c51633c..fd7ca27c800 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -24,10 +24,10 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.name.Name class Fir2IrImplicitCastInserter( @@ -43,6 +43,35 @@ class Fir2IrImplicitCastInserter( TODO("Should not be here: ${element.render()}") } + // TODO: can be private once this visitor becomes more comprehensive + internal fun IrContainerExpression.insertImplicitCasts(): IrContainerExpression { + if (statements.isEmpty()) return this + + val lastIndex = statements.lastIndex + statements.forEachIndexed { i, irStatement -> + if (irStatement !is IrErrorCallExpression && irStatement is IrExpression) { + if (i != lastIndex) { + statements[i] = irStatement.coerceToUnitIfNeeded(irStatement.type, irBuiltIns) + } else { + // TODO: for the last statement, need to cast to the return type if mismatched + } + } + } + + return this + } + + internal fun IrBlockBody.insertImplicitCasts(): IrBlockBody { + if (statements.isEmpty()) return this + + statements.forEachIndexed { i, irStatement -> + if (irStatement !is IrErrorCallExpression && irStatement is IrExpression) { + statements[i] = irStatement.coerceToUnitIfNeeded(irStatement.type, irBuiltIns) + } + } + return this + } + override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: IrElement): IrExpression { return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 0fa4fdfc3e3..851584c80cf 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -36,7 +36,6 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.parentClassOrNull @@ -553,7 +552,11 @@ class Fir2IrVisitor( } else { emptyList() } - ).insertImplicitCasts() + ).also { + with(implicitCastInserter) { + it.insertImplicitCasts() + } + } } } @@ -571,42 +574,19 @@ class Fir2IrVisitor( IrCompositeImpl( startOffset, endOffset, type, origin, mapToIrStatements().filterNotNull() - ).insertImplicitCasts() + ) } else { IrBlockImpl( startOffset, endOffset, type, origin, mapToIrStatements().filterNotNull() - ).insertImplicitCasts() - } - } - } - - private fun IrBlockBody.insertImplicitCasts(): IrBlockBody { - if (statements.isEmpty()) return this - - statements.forEachIndexed { i, irStatement -> - if (irStatement !is IrErrorCallExpression && irStatement is IrExpression) { - statements[i] = irStatement.coerceToUnitIfNeeded(irStatement.type, irBuiltIns) - } - } - return this - } - - private fun IrContainerExpression.insertImplicitCasts(): IrContainerExpression { - if (statements.isEmpty()) return this - - val lastIndex = statements.lastIndex - statements.forEachIndexed { i, irStatement -> - if (irStatement !is IrErrorCallExpression && irStatement is IrExpression) { - if (i != lastIndex) { - statements[i] = irStatement.coerceToUnitIfNeeded(irStatement.type, irBuiltIns) - } else { - // TODO: for the last statement, need to cast to the return type if mismatched + ) + }.also { + // TODO: can remove this once implicit cast inserter visits more expression kinds directly + with(implicitCastInserter) { + it.insertImplicitCasts() } } } - - return this } override fun visitErrorExpression(errorExpression: FirErrorExpression, data: Any?): IrElement { From 318f4b5f0236187517aac9a5dad1a1cfa27020d3 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 23 Oct 2020 15:07:35 -0700 Subject: [PATCH 049/554] FIR2IR: refactor implicit cast insertion, part 3: implicit not_null --- .../fir/backend/Fir2IrImplicitCastInserter.kt | 29 ++++++++++++++++--- .../kotlin/fir/backend/Fir2IrVisitor.kt | 27 ++++------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index fd7ca27c800..eb2f769db42 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.references.FirReference @@ -18,10 +19,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -import org.jetbrains.kotlin.fir.types.ConeIntersectionType -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.expressions.* @@ -43,6 +41,29 @@ class Fir2IrImplicitCastInserter( TODO("Should not be here: ${element.render()}") } + // TODO: can be private once this visitor becomes more comprehensive, also generalized + internal fun IrExpression.insertImplicitNotNullCastIfNeeded(expression: FirExpression): IrExpression { + if (this is IrTypeOperatorCall && this.operator == IrTypeOperator.IMPLICIT_NOTNULL) { + return this + } + // TODO: Other conditions to check? + // [TypeOperatorLowering] will retrieve the source (from start offset to end offset) as an assertion message. + // Avoid type casting if we can't determine the source for some reasons, e.g., implicit `this` receiver. + if (expression.source == null || + expression.typeRef.coneTypeSafe()?.hasEnhancedNullability != true + ) { + return this + } + return IrTypeOperatorCallImpl( + this.startOffset, + this.endOffset, + this.type, + IrTypeOperator.IMPLICIT_NOTNULL, + this.type, + this + ) + } + // TODO: can be private once this visitor becomes more comprehensive internal fun IrContainerExpression.insertImplicitCasts(): IrContainerExpression { if (statements.isEmpty()) return this diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 851584c80cf..da293eec1fc 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -469,29 +469,12 @@ class Fir2IrVisitor( expression.accept(this, null) as IrExpression } } - }.insertImplicitNotNullCastIfNeeded(expression) - } - - private fun IrExpression.insertImplicitNotNullCastIfNeeded(expression: FirExpression): IrExpression { - if (this is IrTypeOperatorCall && this.operator == IrTypeOperator.IMPLICIT_NOTNULL) { - return this + }.let { + // TODO: expression(implicitCastInserter, it) as IrExpression + with(implicitCastInserter) { + it.insertImplicitNotNullCastIfNeeded(expression) + } } - // TODO: Other conditions to check? - // [TypeOperatorLowering] will retrieve the source (from start offset to end offset) as an assertion message. - // Avoid type casting if we can't determine the source for some reasons, e.g., implicit `this` receiver. - if (expression.source == null || - expression.typeRef.coneTypeSafe()?.hasEnhancedNullability != true - ) { - return this - } - return IrTypeOperatorCallImpl( - this.startOffset, - this.endOffset, - this.type, - IrTypeOperator.IMPLICIT_NOTNULL, - this.type, - this - ) } private fun convertToIrReceiverExpression( From 707e94bab50955329b90102e0b4de138c8cb6417 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 23 Oct 2020 16:42:13 -0700 Subject: [PATCH 050/554] FIR2IR: add test about coercion-to-Unit for nested when --- .../kotlin/fir/Fir2IrTextTestGenerated.java | 5 + .../coercionToUnitForNestedWhen.fir.txt | 102 ++++++++++++++++++ .../coercionToUnitForNestedWhen.kt | 17 +++ .../coercionToUnitForNestedWhen.txt | 100 +++++++++++++++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 5 + 5 files changed, 229 insertions(+) create mode 100644 compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.fir.txt create mode 100644 compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.kt create mode 100644 compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index dda0d42f391..c6cc25685c2 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1752,6 +1752,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/firProblems/ClashResolutionDescriptor.kt"); } + @TestMetadata("coercionToUnitForNestedWhen.kt") + public void testCoercionToUnitForNestedWhen() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.kt"); + } + @TestMetadata("DeepCopyIrTree.kt") public void testDeepCopyIrTree() throws Exception { runTest("compiler/testData/ir/irText/firProblems/DeepCopyIrTree.kt"); diff --git a/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.fir.txt b/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.fir.txt new file mode 100644 index 00000000000..0bb032b2b47 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.fir.txt @@ -0,0 +1,102 @@ +FILE fqName: fileName:/coercionToUnitForNestedWhen.kt + PROPERTY name:BACKSLASH visibility:private modality:FINAL [const,val] + FIELD PROPERTY_BACKING_FIELD name:BACKSLASH type:kotlin.Char visibility:private [final,static] + EXPRESSION_BODY + CONST Char type=kotlin.Char value='\\' + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> () returnType:kotlin.Char + correspondingProperty: PROPERTY name:BACKSLASH visibility:private modality:FINAL [const,val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): kotlin.Char declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:BACKSLASH type:kotlin.Char visibility:private [final,static]' type=kotlin.Char origin=null + FUN name:nextChar visibility:private modality:FINAL <> ($receiver:java.io.Reader) returnType:kotlin.Char? + $receiver: VALUE_PARAMETER name: type:java.io.Reader + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun nextChar (): kotlin.Char? declared in ' + BLOCK type=kotlin.Char? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int? [val] + CALL 'public final fun takeUnless (predicate: kotlin.Function1): T of kotlin.takeUnless? [inline] declared in kotlin' type=kotlin.Int? origin=null + : kotlin.Int + $receiver: CALL 'public open fun read (): kotlin.Int declared in java.io.Reader' type=kotlin.Int origin=null + $this: GET_VAR ': java.io.Reader declared in .nextChar' type=java.io.Reader origin=null + predicate: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Boolean + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Boolean declared in .nextChar' + CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'it: kotlin.Int declared in .nextChar.' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=-1 + WHEN type=kotlin.Char? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_0: kotlin.Int? [val] declared in .nextChar' type=kotlin.Int? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun toChar (): kotlin.Char declared in kotlin.Int' type=kotlin.Char origin=null + $this: GET_VAR 'val tmp_0: kotlin.Int? [val] declared in .nextChar' type=kotlin.Int? origin=null + FUN name:consumeRestOfQuotedSequence visibility:public modality:FINAL <> ($receiver:java.io.Reader, sb:java.lang.StringBuilder, quote:kotlin.Char) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER name: type:java.io.Reader + VALUE_PARAMETER name:sb index:0 type:java.lang.StringBuilder + VALUE_PARAMETER name:quote index:1 type:kotlin.Char + BLOCK_BODY + VAR name:ch type:kotlin.Char? [var] + CALL 'private final fun nextChar (): kotlin.Char? declared in ' type=kotlin.Char? origin=null + $receiver: GET_VAR ': java.io.Reader declared in .consumeRestOfQuotedSequence' type=java.io.Reader origin=null + WHILE label=null origin=WHILE_LOOP + condition: WHEN type=kotlin.Boolean origin=ANDAND + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: TYPE_OP type=kotlin.Char origin=IMPLICIT_CAST typeOperand=kotlin.Char + GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: GET_VAR 'quote: kotlin.Char declared in .consumeRestOfQuotedSequence' type=kotlin.Char origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Boolean type=kotlin.Boolean value=false + body: BLOCK type=kotlin.Unit origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + WHEN type=java.lang.StringBuilder? origin=IF + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: TYPE_OP type=kotlin.Char origin=IMPLICIT_CAST typeOperand=kotlin.Char + GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: CALL 'private final fun (): kotlin.Char declared in ' type=kotlin.Char origin=GET_PROPERTY + then: BLOCK type=java.lang.StringBuilder? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Char? [val] + CALL 'private final fun nextChar (): kotlin.Char? declared in ' type=kotlin.Char? origin=null + $receiver: GET_VAR ': java.io.Reader declared in .consumeRestOfQuotedSequence' type=java.io.Reader origin=null + WHEN type=java.lang.StringBuilder? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_1: kotlin.Char? [val] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let [inline] declared in kotlin' type=java.lang.StringBuilder? origin=null + : kotlin.Char + : java.lang.StringBuilder? + $receiver: GET_VAR 'val tmp_1: kotlin.Char? [val] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Char) returnType:java.lang.StringBuilder? + VALUE_PARAMETER name:it index:0 type:kotlin.Char + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Char): java.lang.StringBuilder? declared in .consumeRestOfQuotedSequence' + CALL 'public open fun append (p0: kotlin.Char): java.lang.StringBuilder? declared in java.lang.StringBuilder' type=java.lang.StringBuilder? origin=null + $this: GET_VAR 'sb: java.lang.StringBuilder declared in .consumeRestOfQuotedSequence' type=java.lang.StringBuilder origin=null + p0: GET_VAR 'it: kotlin.Char declared in .consumeRestOfQuotedSequence.' type=kotlin.Char origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun append (p0: kotlin.Char): java.lang.StringBuilder? declared in java.lang.StringBuilder' type=java.lang.StringBuilder? origin=null + $this: GET_VAR 'sb: java.lang.StringBuilder declared in .consumeRestOfQuotedSequence' type=java.lang.StringBuilder origin=null + p0: TYPE_OP type=kotlin.Char origin=IMPLICIT_CAST typeOperand=kotlin.Char + GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + SET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Unit origin=EQ + CALL 'private final fun nextChar (): kotlin.Char? declared in ' type=kotlin.Char? origin=null + $receiver: GET_VAR ': java.io.Reader declared in .consumeRestOfQuotedSequence' type=java.io.Reader origin=null diff --git a/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.kt b/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.kt new file mode 100644 index 00000000000..e6e377e2cde --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.kt @@ -0,0 +1,17 @@ +// WITH_RUNTIME +// FULL_JDK +import java.io.Reader +import java.io.StringReader + +private const val BACKSLASH = '\\' + +private fun Reader.nextChar(): Char? = + read().takeUnless { it == -1 }?.toChar() + +fun Reader.consumeRestOfQuotedSequence(sb: StringBuilder, quote: Char) { + var ch = nextChar() + while (ch != null && ch != quote) { + if (ch == BACKSLASH) nextChar()?.let { sb.append(it) } else sb.append(ch) + ch = nextChar() + } +} diff --git a/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.txt b/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.txt new file mode 100644 index 00000000000..0696ec0655c --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.txt @@ -0,0 +1,100 @@ +FILE fqName: fileName:/coercionToUnitForNestedWhen.kt + PROPERTY name:BACKSLASH visibility:private modality:FINAL [const,val] + FIELD PROPERTY_BACKING_FIELD name:BACKSLASH type:kotlin.Char visibility:private [final,static] + EXPRESSION_BODY + CONST Char type=kotlin.Char value='\\' + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> () returnType:kotlin.Char + correspondingProperty: PROPERTY name:BACKSLASH visibility:private modality:FINAL [const,val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): kotlin.Char declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:BACKSLASH type:kotlin.Char visibility:private [final,static]' type=kotlin.Char origin=null + FUN name:nextChar visibility:private modality:FINAL <> ($receiver:java.io.Reader) returnType:kotlin.Char? + $receiver: VALUE_PARAMETER name: type:java.io.Reader + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun nextChar (): kotlin.Char? declared in ' + BLOCK type=kotlin.Char? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int? [val] + CALL 'public final fun takeUnless (predicate: kotlin.Function1): T of kotlin.takeUnless? [inline] declared in kotlin' type=kotlin.Int? origin=null + : kotlin.Int + $receiver: CALL 'public open fun read (): kotlin.Int declared in java.io.Reader' type=kotlin.Int origin=null + $this: GET_VAR ': java.io.Reader declared in .nextChar' type=java.io.Reader origin=null + predicate: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Boolean + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Boolean declared in .nextChar' + CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'it: kotlin.Int declared in .nextChar.' type=kotlin.Int origin=null + arg1: CONST Int type=kotlin.Int value=-1 + WHEN type=kotlin.Char? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_0: kotlin.Int? [val] declared in .nextChar' type=kotlin.Int? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun toChar (): kotlin.Char declared in kotlin.Int' type=kotlin.Char origin=null + $this: GET_VAR 'val tmp_0: kotlin.Int? [val] declared in .nextChar' type=kotlin.Int? origin=null + FUN name:consumeRestOfQuotedSequence visibility:public modality:FINAL <> ($receiver:java.io.Reader, sb:java.lang.StringBuilder{ kotlin.text.StringBuilder }, quote:kotlin.Char) returnType:kotlin.Unit + $receiver: VALUE_PARAMETER name: type:java.io.Reader + VALUE_PARAMETER name:sb index:0 type:java.lang.StringBuilder{ kotlin.text.StringBuilder } + VALUE_PARAMETER name:quote index:1 type:kotlin.Char + BLOCK_BODY + VAR name:ch type:kotlin.Char? [var] + CALL 'private final fun nextChar (): kotlin.Char? declared in ' type=kotlin.Char? origin=null + $receiver: GET_VAR ': java.io.Reader declared in .consumeRestOfQuotedSequence' type=java.io.Reader origin=null + WHILE label=null origin=WHILE_LOOP + condition: WHEN type=kotlin.Boolean origin=ANDAND + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: GET_VAR 'quote: kotlin.Char declared in .consumeRestOfQuotedSequence' type=kotlin.Char origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Boolean type=kotlin.Boolean value=false + body: BLOCK type=kotlin.Unit origin=null + WHEN type=kotlin.Unit origin=IF + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: CALL 'private final fun (): kotlin.Char declared in ' type=kotlin.Char origin=GET_PROPERTY + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=@[FlexibleNullability] java.lang.StringBuilder? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Char? [val] + CALL 'private final fun nextChar (): kotlin.Char? declared in ' type=kotlin.Char? origin=null + $receiver: GET_VAR ': java.io.Reader declared in .consumeRestOfQuotedSequence' type=java.io.Reader origin=null + WHEN type=@[FlexibleNullability] java.lang.StringBuilder? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_1: kotlin.Char? [val] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let [inline] declared in kotlin' type=@[FlexibleNullability] java.lang.StringBuilder? origin=null + : kotlin.Char + : @[FlexibleNullability] java.lang.StringBuilder? + $receiver: GET_VAR 'val tmp_1: kotlin.Char? [val] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Char) returnType:@[FlexibleNullability] java.lang.StringBuilder? + VALUE_PARAMETER name:it index:0 type:kotlin.Char + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Char): @[FlexibleNullability] java.lang.StringBuilder? declared in .consumeRestOfQuotedSequence' + CALL 'public open fun append (p0: kotlin.Char): @[FlexibleNullability] java.lang.StringBuilder? declared in java.lang.StringBuilder' type=@[FlexibleNullability] java.lang.StringBuilder? origin=null + $this: GET_VAR 'sb: java.lang.StringBuilder{ kotlin.text.StringBuilder } declared in .consumeRestOfQuotedSequence' type=java.lang.StringBuilder{ kotlin.text.StringBuilder } origin=null + p0: GET_VAR 'it: kotlin.Char declared in .consumeRestOfQuotedSequence.' type=kotlin.Char origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public open fun append (p0: kotlin.Char): @[FlexibleNullability] java.lang.StringBuilder? declared in java.lang.StringBuilder' type=@[FlexibleNullability] java.lang.StringBuilder? origin=null + $this: GET_VAR 'sb: java.lang.StringBuilder{ kotlin.text.StringBuilder } declared in .consumeRestOfQuotedSequence' type=java.lang.StringBuilder{ kotlin.text.StringBuilder } origin=null + p0: GET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Char? origin=null + SET_VAR 'var ch: kotlin.Char? [var] declared in .consumeRestOfQuotedSequence' type=kotlin.Unit origin=EQ + CALL 'private final fun nextChar (): kotlin.Char? declared in ' type=kotlin.Char? origin=null + $receiver: GET_VAR ': java.io.Reader declared in .consumeRestOfQuotedSequence' type=java.io.Reader origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index c223eaa5e5a..d5ec6b0767e 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1751,6 +1751,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/firProblems/ClashResolutionDescriptor.kt"); } + @TestMetadata("coercionToUnitForNestedWhen.kt") + public void testCoercionToUnitForNestedWhen() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/coercionToUnitForNestedWhen.kt"); + } + @TestMetadata("DeepCopyIrTree.kt") public void testDeepCopyIrTree() throws Exception { runTest("compiler/testData/ir/irText/firProblems/DeepCopyIrTree.kt"); From f1fd3d6b5dd520a1ac46318418ca3cb5aae5d0e2 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sun, 25 Oct 2020 22:00:55 -0700 Subject: [PATCH 051/554] FIR2IR: avoid using constant -1 --- .../jetbrains/kotlin/fir/backend/ConversionUtils.kt | 3 ++- .../kotlin/fir/backend/Fir2IrClassifierStorage.kt | 3 ++- .../kotlin/fir/backend/Fir2IrDeclarationStorage.kt | 3 ++- .../fir/backend/generators/AdapterGenerator.kt | 5 +++-- .../backend/generators/CallAndReferenceGenerator.kt | 12 ++++++++++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 5c8b40313e5..e2434965f69 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrConst @@ -317,7 +318,7 @@ internal fun IrDeclarationParent.declareThisReceiverParameter( ) { symbol -> symbolTable.irFactory.createValueParameter( startOffset, endOffset, thisOrigin, symbol, - Name.special(""), -1, thisType, + Name.special(""), UNDEFINED_PARAMETER_INDEX, thisType, varargElementType = null, isCrossinline = false, isNoinline = false, isAssignable = false ).apply { this.parent = this@declareThisReceiverParameter diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index e56ecaf571b..f979e551b70 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedEnumEntryDescriptor @@ -338,7 +339,7 @@ class Fir2IrClassifierStorage( internal fun getCachedIrTypeParameter( typeParameter: FirTypeParameter, - index: Int = -1, + index: Int = UNDEFINED_PARAMETER_INDEX, typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrTypeParameter? { // Here transformation is a bit difficult because one FIR property type parameter diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 0ad64004aa7..598632f58b4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass @@ -844,7 +845,7 @@ class Fir2IrDeclarationStorage( internal fun createIrParameter( valueParameter: FirValueParameter, - index: Int = -1, + index: Int = UNDEFINED_PARAMETER_INDEX, useStubForDefaultValueStub: Boolean = true, typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrValueParameter { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt index 721a1134bf1..cb59bea9a29 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor @@ -221,7 +222,7 @@ internal class AdapterGenerator( createAdapterParameter( irAdapterFunction, Name.identifier("receiver"), - index = -1, + index = UNDEFINED_PARAMETER_INDEX, boundReceiver.type, IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE ) @@ -474,7 +475,7 @@ internal class AdapterGenerator( irAdapterFunction.extensionReceiverParameter = createAdapterParameter( irAdapterFunction, Name.identifier("callee"), - -1, + UNDEFINED_PARAMETER_INDEX, argumentType, IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION ) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 95e1f9f9970..17fc9961843 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -26,6 +26,8 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -527,7 +529,13 @@ class CallAndReferenceGenerator( if (parameter.isVararg && !argumentMapping.containsValue(parameter)) { val elementType = parameter.returnTypeRef.toIrType() putValueArgument( - index, IrVarargImpl(-1, -1, elementType, elementType.toArrayOrPrimitiveArrayType(irBuiltIns)) + index, + IrVarargImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + elementType, + elementType.toArrayOrPrimitiveArrayType(irBuiltIns) + ) ) } } @@ -540,7 +548,7 @@ class CallAndReferenceGenerator( parametersInActualOrder: Collection, valueParameters: List ): Boolean { - var lastValueParameterIndex = -1 + var lastValueParameterIndex = UNDEFINED_PARAMETER_INDEX for (parameter in parametersInActualOrder) { val index = valueParameters.indexOf(parameter) if (index < lastValueParameterIndex) { From 5f6d2c53624fd078008ae2c122267a7be6e043f1 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sun, 25 Oct 2020 22:09:31 -0700 Subject: [PATCH 052/554] FIR2IR: utilize argument conversions --- .../generators/CallAndReferenceGenerator.kt | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 17fc9961843..5a4365d0c0f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -450,13 +450,7 @@ class CallAndReferenceGenerator( } for ((index, argument) in call.arguments.withIndex()) { val valueParameter = valueParameters?.get(index) - val argumentExpression = - with(adapterGenerator) { - visitor.convertToIrExpression(argument) - .applySamConversionIfNeeded(argument, valueParameter) - .applySuspendConversionIfNeeded(argument, valueParameter) - .applyAssigningArrayElementsToVarargInNamedForm(argument, valueParameter) - } + val argumentExpression = convertArgument(argument, valueParameter) putValueArgument(index, argumentExpression) } } @@ -494,13 +488,7 @@ class CallAndReferenceGenerator( return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply { for ((argument, parameter) in argumentMapping) { val parameterIndex = valueParameters.indexOf(parameter) - val irArgument = - with(adapterGenerator) { - visitor.convertToIrExpression(argument) - .applySamConversionIfNeeded(argument, parameter) - .applySuspendConversionIfNeeded(argument, parameter) - .applyAssigningArrayElementsToVarargInNamedForm(argument, parameter) - } + val irArgument = convertArgument(argument, parameter) if (irArgument.hasNoSideEffects()) { putValueArgument(parameterIndex, irArgument) } else { @@ -515,13 +503,7 @@ class CallAndReferenceGenerator( } } else { for ((argument, parameter) in argumentMapping) { - val argumentExpression = - with(adapterGenerator) { - visitor.convertToIrExpression(argument, annotationMode) - .applySamConversionIfNeeded(argument, parameter) - .applySuspendConversionIfNeeded(argument, parameter) - .applyAssigningArrayElementsToVarargInNamedForm(argument, parameter) - } + val argumentExpression = convertArgument(argument, parameter, annotationMode) putValueArgument(valueParameters.indexOf(parameter), argumentExpression) } if (annotationMode) { @@ -559,6 +541,18 @@ class CallAndReferenceGenerator( return false } + private fun convertArgument( + argument: FirExpression, + parameter: FirValueParameter?, + annotationMode: Boolean = false + ): IrExpression = + with(adapterGenerator) { + visitor.convertToIrExpression(argument, annotationMode) + .applySamConversionIfNeeded(argument, parameter) + .applySuspendConversionIfNeeded(argument, parameter) + .applyAssigningArrayElementsToVarargInNamedForm(argument, parameter) + } + private fun IrExpression.applySamConversionIfNeeded( argument: FirExpression, parameter: FirValueParameter?, From 2424f2438cbc71d00a94629588dd80f4e414b97f Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sun, 25 Oct 2020 23:58:20 -0700 Subject: [PATCH 053/554] FIR2IR: towards comprehensive visits in implicit cast inserter --- .../fir/backend/Fir2IrImplicitCastInserter.kt | 198 ++++++++++++++++-- .../kotlin/fir/backend/Fir2IrVisitor.kt | 35 ++-- .../generators/CallAndReferenceGenerator.kt | 19 +- .../generators/ClassMemberGenerator.kt | 13 +- .../jetbrains/kotlin/fir/types/TypeUtils.kt | 3 + .../ir/irText/expressions/bangbang.fir.txt | 9 +- .../expressions/whenCoercedToUnit.fir.txt | 13 -- .../irText/expressions/whenCoercedToUnit.kt | 1 + .../ir/irText/stubs/builtinMap.fir.txt | 13 +- 9 files changed, 240 insertions(+), 64 deletions(-) delete mode 100644 compiler/testData/ir/irText/expressions/whenCoercedToUnit.fir.txt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index eb2f769db42..165f0162606 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -6,25 +6,22 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast -import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression -import org.jetbrains.kotlin.fir.references.FirReference -import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.* +import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.coerceToUnit import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.name.Name @@ -38,20 +35,184 @@ class Fir2IrImplicitCastInserter( private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() } override fun visitElement(element: FirElement, data: IrElement): IrElement { - TODO("Should not be here: ${element.render()}") + TODO("Should not be here: ${element::class}: ${element.render()}") } - // TODO: can be private once this visitor becomes more comprehensive, also generalized - internal fun IrExpression.insertImplicitNotNullCastIfNeeded(expression: FirExpression): IrExpression { - if (this is IrTypeOperatorCall && this.operator == IrTypeOperator.IMPLICIT_NOTNULL) { + override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: IrElement): IrElement = data + + override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: IrElement): IrElement = data + + override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: IrElement): IrElement = data + + override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: IrElement): IrElement = data + + // TODO: maybe a place to do coerceIntToAnotherIntegerType? + override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: IrElement): IrElement = data + + override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: IrElement): IrElement = data + + override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: IrElement): IrElement = data + + override fun visitConstExpression(constExpression: FirConstExpression, data: IrElement): IrElement = data + + override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: IrElement): IrElement = data + + override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: IrElement): IrElement = data + + override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: IrElement): IrElement = data + + override fun visitGetClassCall(getClassCall: FirGetClassCall, data: IrElement): IrElement = data + + override fun visitFunctionCall(functionCall: FirFunctionCall, data: IrElement): IrElement = data + + override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: IrElement): IrElement = data + + override fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject, data: IrElement): IrElement = data + + override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: IrElement): IrElement = data + + override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: IrElement): IrElement = data + + // TODO: element-wise cast? + override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: IrElement): IrElement = data + + // TODO: something to do w.r.t. SAM? + override fun visitLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression, data: IrElement): IrElement = data + + // TODO: element-wise cast? + override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression, data: IrElement): IrElement = data + + // TODO: element-wise cast? + override fun visitVarargArgumentsExpression(varargArgumentsExpression: FirVarargArgumentsExpression, data: IrElement): IrElement = data + + // TODO: element-wise cast? + override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: IrElement): IrElement = data + + // ================================================================================== + + override fun visitExpression(expression: FirExpression, data: IrElement): IrElement { + return when(expression) { + is FirBlock -> (data as IrContainerExpression).insertImplicitCasts() + is FirUnitExpression -> (data as IrExpression).let { it.coerceToUnitIfNeeded(it.type, irBuiltIns) } + else -> data + } + } + + override fun visitStatement(statement: FirStatement, data: IrElement): IrElement { + return when (statement) { + is FirTypeAlias -> data + FirStubStatement -> data + is FirUnitExpression -> (data as IrExpression).let { it.coerceToUnitIfNeeded(it.type, irBuiltIns) } + is FirBlock -> (data as IrContainerExpression).insertImplicitCasts() + else -> statement.accept(this, data) + } + } + + // ================================================================================== + + override fun visitWhenExpression(whenExpression: FirWhenExpression, data: IrElement): IrElement { + if (data is IrBlock) { + return data.insertImplicitCasts() + } + val irWhen = data as IrWhen + if (irWhen.branches.size != whenExpression.branches.size) { + return data + } + val firBranchMap = irWhen.branches.zip(whenExpression.branches).toMap() + irWhen.branches.replaceAll { + visitWhenBranch(firBranchMap[it]!!, it) + } + return data + } + + override fun visitWhenSubjectExpression(whenSubjectExpression: FirWhenSubjectExpression, data: IrElement): IrElement = data + + // TODO: cast `condition` expression to boolean? + override fun visitWhenBranch(whenBranch: FirWhenBranch, data: IrElement): IrBranch { + val irBranch = data as IrBranch + (irBranch.result as? IrContainerExpression)?.let { + irBranch.result = it.insertImplicitCasts() + } + return data + } + + // TODO: Need to visit lhs/rhs branches? + override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: IrElement): IrElement = data + + // ================================================================================== + + // TODO: cast `condition` expression to boolean? + override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: IrElement): IrElement { + val loop = data as IrDoWhileLoop + (loop.body as? IrContainerExpression)?.let { + loop.body = it.insertImplicitCasts() + } + return data + } + + // TODO: cast `condition` expression to boolean? + override fun visitWhileLoop(whileLoop: FirWhileLoop, data: IrElement): IrElement { + val loop = data as IrWhileLoop + (loop.body as? IrContainerExpression)?.let { + loop.body = it.insertImplicitCasts() + } + return data + } + + override fun visitBreakExpression(breakExpression: FirBreakExpression, data: IrElement): IrElement = data + + override fun visitContinueExpression(continueExpression: FirContinueExpression, data: IrElement): IrElement = data + + // ================================================================================== + + override fun visitTryExpression(tryExpression: FirTryExpression, data: IrElement): IrElement { + val irTry = data as IrTry + (irTry.finallyExpression as? IrContainerExpression)?.let { + irTry.finallyExpression = it.insertImplicitCasts() + } + return data + } + + override fun visitThrowExpression(throwExpression: FirThrowExpression, data: IrElement): IrElement = + (data as IrThrow).cast(throwExpression, throwExpression.exception.typeRef, throwExpression.typeRef) + + override fun visitBlock(block: FirBlock, data: IrElement): IrElement = + (data as? IrContainerExpression)?.insertImplicitCasts() ?: data + + override fun visitReturnExpression(returnExpression: FirReturnExpression, data: IrElement): IrElement { + val irReturn = data as IrReturn + val expectedType = returnExpression.target.labeledElement.returnTypeRef + irReturn.value = irReturn.value.cast(returnExpression.result, returnExpression.result.typeRef, expectedType) + return data + } + + // ================================================================================== + + internal fun IrExpression.cast(expression: FirExpression, valueType: FirTypeRef, expectedType: FirTypeRef): IrExpression { + if (this is IrTypeOperatorCall) { return this } - // TODO: Other conditions to check? + return when { + this is IrContainerExpression -> { + insertImplicitCasts() + } + expectedType.isUnit -> { + coerceToUnitIfNeeded(type, irBuiltIns) + } + // TODO: Not exactly matched with psi2ir yet... + valueType.hasEnhancedNullability() -> { + insertImplicitNotNullCastIfNeeded(expression) + } + // TODO: coerceIntToAnotherIntegerType + // TODO: even implicitCast call can be here? + else -> this + } + } + + private fun IrExpression.insertImplicitNotNullCastIfNeeded(expression: FirExpression): IrExpression { // [TypeOperatorLowering] will retrieve the source (from start offset to end offset) as an assertion message. // Avoid type casting if we can't determine the source for some reasons, e.g., implicit `this` receiver. - if (expression.source == null || - expression.typeRef.coneTypeSafe()?.hasEnhancedNullability != true - ) { + if (expression.source == null) { return this } return IrTypeOperatorCallImpl( @@ -64,8 +225,7 @@ class Fir2IrImplicitCastInserter( ) } - // TODO: can be private once this visitor becomes more comprehensive - internal fun IrContainerExpression.insertImplicitCasts(): IrContainerExpression { + private fun IrContainerExpression.insertImplicitCasts(): IrContainerExpression { if (statements.isEmpty()) return this val lastIndex = statements.lastIndex diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index da293eec1fc..7a9822c195a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -53,7 +53,7 @@ class Fir2IrVisitor( private val annotationGenerator = AnnotationGenerator(this) - private val implicitCastInserter = Fir2IrImplicitCastInserter(components, this) + internal val implicitCastInserter = Fir2IrImplicitCastInserter(components, this) private val memberGenerator = ClassMemberGenerator(components, this, conversionScope) @@ -64,7 +64,7 @@ class Fir2IrVisitor( private fun applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration) override fun visitElement(element: FirElement, data: Any?): IrElement { - TODO("Should not be here: ${element.render()}") + TODO("Should not be here: ${element::class} ${element.render()}") } override fun visitField(field: FirField, data: Any?): IrField { @@ -260,7 +260,10 @@ class Fir2IrVisitor( variable, conversionScope.parentFromStack(), if (isNextVariable) IrDeclarationOrigin.FOR_LOOP_VARIABLE else null ) if (initializer != null) { - irVariable.initializer = convertToIrExpression(initializer) + irVariable.initializer = + with(implicitCastInserter) { + convertToIrExpression(initializer).cast(initializer, initializer.typeRef, variable.returnTypeRef) + } } return irVariable } @@ -288,6 +291,8 @@ class Fir2IrVisitor( }, convertToIrExpression(result) ) + }.let { + returnExpression.accept(implicitCastInserter, it) } } @@ -470,10 +475,7 @@ class Fir2IrVisitor( } } }.let { - // TODO: expression(implicitCastInserter, it) as IrExpression - with(implicitCastInserter) { - it.insertImplicitNotNullCastIfNeeded(expression) - } + expression.accept(implicitCastInserter, it) as IrExpression } } @@ -563,11 +565,6 @@ class Fir2IrVisitor( startOffset, endOffset, type, origin, mapToIrStatements().filterNotNull() ) - }.also { - // TODO: can remove this once implicit cast inserter visits more expression kinds directly - with(implicitCastInserter) { - it.insertImplicitCasts() - } } } } @@ -655,7 +652,7 @@ class Fir2IrVisitor( val irBranches = whenExpression.branches.mapNotNullTo(mutableListOf()) { branch -> branch.takeIf { it.condition !is FirElseIfTrueCondition || it.result.statements.isNotEmpty() - }?.toIrWhenBranch() + }?.toIrWhenBranch(whenExpression.typeRef) } if (whenExpression.isExhaustive && whenExpression.branches.none { it.condition is FirElseIfTrueCondition }) { val irResult = IrCallImpl( @@ -677,6 +674,8 @@ class Fir2IrVisitor( ) whenExpression.typeRef.toIrType() else irBuiltIns.unitType ) } + }.also { + whenExpression.accept(implicitCastInserter, it) } } @@ -708,10 +707,12 @@ class Fir2IrVisitor( } } - private fun FirWhenBranch.toIrWhenBranch(): IrBranch { + private fun FirWhenBranch.toIrWhenBranch(whenExpressionType: FirTypeRef): IrBranch { return convertWithOffsets { startOffset, endOffset -> val condition = condition - val irResult = convertToIrExpression(result) + val irResult = with(implicitCastInserter) { + convertToIrExpression(result).cast(result, result.typeRef, whenExpressionType) + } if (condition is FirElseIfTrueCondition) { IrElseBranchImpl(IrConstImpl.boolean(irResult.startOffset, irResult.endOffset, irBuiltIns.booleanType, true), irResult) } else { @@ -741,6 +742,8 @@ class Fir2IrVisitor( condition = convertToIrExpression(doWhileLoop.condition) loopMap.remove(doWhileLoop) } + }.also { + doWhileLoop.accept(implicitCastInserter, it) } } @@ -756,6 +759,8 @@ class Fir2IrVisitor( body = whileLoop.block.convertToIrExpressionOrBlock(origin.takeIf { it != IrStatementOrigin.WHILE_LOOP }) loopMap.remove(whileLoop) } + }.also { + whileLoop.accept(implicitCastInserter, it) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 5a4365d0c0f..cb37189372f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -545,13 +545,20 @@ class CallAndReferenceGenerator( argument: FirExpression, parameter: FirValueParameter?, annotationMode: Boolean = false - ): IrExpression = - with(adapterGenerator) { - visitor.convertToIrExpression(argument, annotationMode) - .applySamConversionIfNeeded(argument, parameter) - .applySuspendConversionIfNeeded(argument, parameter) - .applyAssigningArrayElementsToVarargInNamedForm(argument, parameter) + ): IrExpression { + var irArgument = visitor.convertToIrExpression(argument, annotationMode) + if (parameter != null) { + with(visitor.implicitCastInserter) { + irArgument = irArgument.cast(argument, argument.typeRef, parameter.returnTypeRef) + } } + with(adapterGenerator) { + irArgument = irArgument.applySuspendConversionIfNeeded(argument, parameter) + } + return irArgument + .applySamConversionIfNeeded(argument, parameter) + .applyAssigningArrayElementsToVarargInNamedForm(argument, parameter) + } private fun IrExpression.applySamConversionIfNeeded( argument: FirExpression, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index d3a5aa1d379..bcf1a0fcc0d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -187,7 +187,18 @@ internal class ClassMemberGenerator( declarationStorage.enterScope(this@initializeBackingField) // NB: initializer can be already converted if (initializer == null && initializerExpression != null) { - initializer = irFactory.createExpressionBody(visitor.convertToIrExpression(initializerExpression)) + initializer = irFactory.createExpressionBody( + run { + val irExpression = visitor.convertToIrExpression(initializerExpression) + if (property.delegate == null) { + with(visitor.implicitCastInserter) { + irExpression.cast(initializerExpression, initializerExpression.typeRef, property.returnTypeRef) + } + } else { + irExpression + } + } + ) } declarationStorage.leaveScope(this@initializeBackingField) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index a5006fdf445..1cb4a74e206 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -183,6 +183,9 @@ fun FirTypeRef.isUnsafeVarianceType(session: FirSession): Boolean { return coneTypeSafe()?.isUnsafeVarianceType(session) == true } +fun FirTypeRef.hasEnhancedNullability(): Boolean = + coneTypeSafe()?.hasEnhancedNullability == true + // Unlike other cases, return types may be implicit, i.e. unresolved // But in that cases newType should also be `null` fun FirTypeRef.withReplacedReturnType(newType: ConeKotlinType?): FirTypeRef { diff --git a/compiler/testData/ir/irText/expressions/bangbang.fir.txt b/compiler/testData/ir/irText/expressions/bangbang.fir.txt index df073e2d155..cca5d161680 100644 --- a/compiler/testData/ir/irText/expressions/bangbang.fir.txt +++ b/compiler/testData/ir/irText/expressions/bangbang.fir.txt @@ -44,10 +44,11 @@ FILE fqName: fileName:/bangbang.kt BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null - then: CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String origin=EXCLEXCL - : kotlin.String - arg0: TYPE_OP type=kotlin.String? origin=IMPLICIT_CAST typeOperand=kotlin.String? - GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null + then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public final fun CHECK_NOT_NULL (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String origin=EXCLEXCL + : kotlin.String + arg0: TYPE_OP type=kotlin.String? origin=IMPLICIT_CAST typeOperand=kotlin.String? + GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null WHEN type=kotlin.Unit origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? diff --git a/compiler/testData/ir/irText/expressions/whenCoercedToUnit.fir.txt b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.fir.txt deleted file mode 100644 index 32ab6eefa35..00000000000 --- a/compiler/testData/ir/irText/expressions/whenCoercedToUnit.fir.txt +++ /dev/null @@ -1,13 +0,0 @@ -FILE fqName: fileName:/whenCoercedToUnit.kt - FUN name:foo visibility:public modality:FINAL <> (x:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER name:x index:0 type:kotlin.Int - BLOCK_BODY - BLOCK type=kotlin.Unit origin=WHEN - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val] - GET_VAR 'x: kotlin.Int declared in .foo' type=kotlin.Int origin=null - WHEN type=kotlin.Unit origin=WHEN - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_0: kotlin.Int [val] declared in .foo' type=kotlin.Int origin=null - arg1: CONST Int type=kotlin.Int value=0 - then: CONST Int type=kotlin.Int value=0 diff --git a/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt index cfbd1828b35..e556187c081 100644 --- a/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt +++ b/compiler/testData/ir/irText/expressions/whenCoercedToUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // WITH_RUNTIME fun foo(x: Int) { diff --git a/compiler/testData/ir/irText/stubs/builtinMap.fir.txt b/compiler/testData/ir/irText/stubs/builtinMap.fir.txt index 3b7d9ff78e6..26801e40c21 100644 --- a/compiler/testData/ir/irText/stubs/builtinMap.fir.txt +++ b/compiler/testData/ir/irText/stubs/builtinMap.fir.txt @@ -27,9 +27,10 @@ FILE fqName: fileName:/builtinMap.kt $receiver: VALUE_PARAMETER name: type:java.util.LinkedHashMap.plus?, V1 of .plus?> BLOCK_BODY RETURN type=kotlin.Nothing from='local final fun (): kotlin.Unit declared in .plus' - CALL 'public open fun put (p0: K of java.util.LinkedHashMap?, p1: V of java.util.LinkedHashMap?): V of java.util.LinkedHashMap? declared in java.util.LinkedHashMap' type=V1 of .plus? origin=null - $this: GET_VAR ': java.util.LinkedHashMap.plus?, V1 of .plus?> declared in .plus.' type=java.util.LinkedHashMap.plus?, V1 of .plus?> origin=null - p0: CALL 'public final fun (): A of kotlin.Pair declared in kotlin.Pair' type=K1 of .plus origin=GET_PROPERTY - $this: GET_VAR 'pair: kotlin.Pair.plus, V1 of .plus> declared in .plus' type=kotlin.Pair.plus, V1 of .plus> origin=null - p1: CALL 'public final fun (): B of kotlin.Pair declared in kotlin.Pair' type=V1 of .plus origin=GET_PROPERTY - $this: GET_VAR 'pair: kotlin.Pair.plus, V1 of .plus> declared in .plus' type=kotlin.Pair.plus, V1 of .plus> origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public open fun put (p0: K of java.util.LinkedHashMap?, p1: V of java.util.LinkedHashMap?): V of java.util.LinkedHashMap? declared in java.util.LinkedHashMap' type=V1 of .plus? origin=null + $this: GET_VAR ': java.util.LinkedHashMap.plus?, V1 of .plus?> declared in .plus.' type=java.util.LinkedHashMap.plus?, V1 of .plus?> origin=null + p0: CALL 'public final fun (): A of kotlin.Pair declared in kotlin.Pair' type=K1 of .plus origin=GET_PROPERTY + $this: GET_VAR 'pair: kotlin.Pair.plus, V1 of .plus> declared in .plus' type=kotlin.Pair.plus, V1 of .plus> origin=null + p1: CALL 'public final fun (): B of kotlin.Pair declared in kotlin.Pair' type=V1 of .plus origin=GET_PROPERTY + $this: GET_VAR 'pair: kotlin.Pair.plus, V1 of .plus> declared in .plus' type=kotlin.Pair.plus, V1 of .plus> origin=null From 80108444ec3704f8de7924899cffa14efa1b9de5 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 28 Oct 2020 13:33:06 +0300 Subject: [PATCH 054/554] FIR2IR: cleanup implicit cast inserter --- .../kotlin/fir/backend/Fir2IrImplicitCastInserter.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index 165f0162606..97db85112bf 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.util.coerceToUnit import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.name.Name @@ -91,7 +90,7 @@ class Fir2IrImplicitCastInserter( // ================================================================================== override fun visitExpression(expression: FirExpression, data: IrElement): IrElement { - return when(expression) { + return when (expression) { is FirBlock -> (data as IrContainerExpression).insertImplicitCasts() is FirUnitExpression -> (data as IrExpression).let { it.coerceToUnitIfNeeded(it.type, irBuiltIns) } else -> data @@ -120,7 +119,7 @@ class Fir2IrImplicitCastInserter( } val firBranchMap = irWhen.branches.zip(whenExpression.branches).toMap() irWhen.branches.replaceAll { - visitWhenBranch(firBranchMap[it]!!, it) + visitWhenBranch(firBranchMap.getValue(it), it) } return data } @@ -233,9 +232,8 @@ class Fir2IrImplicitCastInserter( if (irStatement !is IrErrorCallExpression && irStatement is IrExpression) { if (i != lastIndex) { statements[i] = irStatement.coerceToUnitIfNeeded(irStatement.type, irBuiltIns) - } else { - // TODO: for the last statement, need to cast to the return type if mismatched } + // TODO: for the last statement, need to cast to the return type if mismatched } } From 82984089f0881612019cda4a240df5c3ce300873 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Wed, 28 Oct 2020 14:07:34 +0300 Subject: [PATCH 055/554] KT-42274 Update `SOURCE_STUB_VERSION` This update should have been done in 4b7d34b53778aa9a80f943461c20db293468410d commit, as it is stated in the `KtTokens.MODIFIER_KEYWORDS_ARRAY` docs. Shifting all modifiers by one have led resulted in incorrect modifiers when stubs were read from the disk. Updating `SOURCE_STUB_VERSION` will make IDEA recreate all stubs from scratch ^KT-42274 Fixed --- .../src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt index 76c605c3f31..694de402d25 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt @@ -23,7 +23,7 @@ object KotlinStubVersions { // Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version // if you are not 100% sure it can be avoided. // Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version. - const val SOURCE_STUB_VERSION = 137 + const val SOURCE_STUB_VERSION = 138 // Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed // or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder). From 3a693e112b2b7b729bcfe01f0ab1b6c3ec70e1b1 Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Wed, 28 Oct 2020 09:35:53 -0400 Subject: [PATCH 056/554] Update ExperimentalPathApi annotation's SinceKotlin value to 1.4 --- libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt index 67f8f646f28..8425718e384 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/ExperimentalPathApi.kt @@ -33,5 +33,5 @@ import kotlin.annotation.AnnotationTarget.* TYPEALIAS ) @MustBeDocumented -@SinceKotlin("1.3") +@SinceKotlin("1.4") public annotation class ExperimentalPathApi From 2dc6467b5dfb4b258c95eb295d3ad1498735573b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 30 Sep 2020 13:52:17 +0300 Subject: [PATCH 057/554] [FIR] Modify signatures also from ERASED_COLLECTION_PARAMETER_SIGNATURES In this commit we change value parameter type of containsAll, removeAll, retainAll from Java collections. Originally it's Collection, we change it to Collection #KT-42340 Fixed --- .../kotlin/fir/Fir2IrTextTestGenerated.java | 5 + .../JavaClassMembersEnhancementScope.kt | 93 +-- .../codegen/box/bridges/objectClone.kt | 1 - .../box/classes/inheritSetAndHashSet.kt | 1 - compiler/testData/codegen/box/jdk/removeIf.kt | 1 - .../collectionOverrides/containsAll.fir.kt | 6 +- .../ir/irText/firProblems/MultiList.fir.txt | 579 +++++++++++++++++ .../ir/irText/firProblems/MultiList.kt | 11 + .../ir/irText/firProblems/MultiList.txt | 583 ++++++++++++++++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 5 + 10 files changed, 1244 insertions(+), 41 deletions(-) create mode 100644 compiler/testData/ir/irText/firProblems/MultiList.fir.txt create mode 100644 compiler/testData/ir/irText/firProblems/MultiList.kt create mode 100644 compiler/testData/ir/irText/firProblems/MultiList.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index c6cc25685c2..5083f864fde 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1777,6 +1777,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt"); } + @TestMetadata("MultiList.kt") + public void testMultiList() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/MultiList.kt"); + } + @TestMetadata("putIfAbsent.kt") public void testPutIfAbsent() throws Exception { runTest("compiler/testData/ir/irText/firProblems/putIfAbsent.kt"); diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt index 7ae0e0cb2b4..355d1f0a2d4 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.java.scopes +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration @@ -22,6 +23,10 @@ import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.load.java.SpecialGenericSignatures +import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_COLLECTION_PARAMETER_SIGNATURES +import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SHORT_NAMES +import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SIGNATURES +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -58,56 +63,74 @@ class JavaClassMembersEnhancementScope( private fun FirSimpleFunction.changeSignatureIfErasedValueParameter(): FirSimpleFunction { val typeParameters = owner.fir.typeParameters - if (typeParameters.isEmpty() || name !in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SHORT_NAMES) { + if (typeParameters.isEmpty() || name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) { return this } - val jvmDescriptor = this.computeJvmDescriptorReplacingKotlinToJava() - if (SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES.none { it.endsWith(jvmDescriptor) }) { + val jvmDescriptor = this.computeJvmDescriptorReplacingKotlinToJava().replace( + "kotlin/collections/Collection", + "java/util/Collection" + ) + if (ERASED_VALUE_PARAMETERS_SIGNATURES.none { it.endsWith(jvmDescriptor) }) { return this } val superClassIds = listOfNotNull(symbol.callableId.classId) + lookupSuperTypes(owner, lookupInterfaces = true, deep = true, useSiteSession = session).map { it.lookupTag.classId } for (superClassId in superClassIds) { val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(superClassId.asSingleFqName().toUnsafe()) ?: superClassId - val fqJvmDescriptor = "${javaClassId.asString()}.$jvmDescriptor" - if (fqJvmDescriptor in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES) { - val specialSignatureInfo = SpecialGenericSignatures.getSpecialSignatureInfo(fqJvmDescriptor) - if (!specialSignatureInfo.isObjectReplacedWithTypeParameter) { - return this - } - val newParameterTypes = valueParameters.mapIndexed { i, valueParameter -> - val classLikeType = - valueParameter.returnTypeRef.coneTypeSafe()?.lowerBoundIfFlexible().safeAs() - if (classLikeType?.lookupTag?.classId == StandardClassIds.Any) { - val typeParameterIndex = if (name.asString() == "containsValue") 1 else i - val typeParameter = typeParameters.getOrNull(typeParameterIndex) ?: typeParameters.first() - val type = ConeTypeParameterLookupTag(typeParameter.symbol).constructType( - emptyArray(), valueParameter.returnTypeRef.isMarkedNullable == true + val newParameterTypes: List = when (val fqJvmDescriptor = "${javaClassId.asString()}.$jvmDescriptor") { + in ERASED_COLLECTION_PARAMETER_SIGNATURES -> { + valueParameters.map { + val typeParameter = typeParameters.first() + ConeClassLikeLookupTagImpl(ClassId.topLevel(StandardNames.FqNames.collection)).constructClassType( + arrayOf( + ConeTypeParameterLookupTag(typeParameter.symbol).constructType(emptyArray(), isNullable = false) + ), isNullable = false ) - if (valueParameter.returnTypeRef.coneType is ConeFlexibleType) { - ConeFlexibleType(type, type.withNullability(ConeNullability.NULLABLE)) - } else { - type - } - } else { - null } } - if (newParameterTypes.none { it != null }) { - return this + in ERASED_VALUE_PARAMETERS_SIGNATURES -> { + val specialSignatureInfo = SpecialGenericSignatures.getSpecialSignatureInfo(fqJvmDescriptor) + if (!specialSignatureInfo.isObjectReplacedWithTypeParameter) { + return this + } + valueParameters.mapIndexed { i, valueParameter -> + val classLikeType = + valueParameter.returnTypeRef.coneTypeSafe()?.lowerBoundIfFlexible().safeAs() + if (classLikeType?.lookupTag?.classId == StandardClassIds.Any) { + val typeParameterIndex = if (name.asString() == "containsValue") 1 else i + val typeParameter = typeParameters.getOrNull(typeParameterIndex) ?: typeParameters.first() + val type = ConeTypeParameterLookupTag(typeParameter.symbol).constructType( + emptyArray(), valueParameter.returnTypeRef.isMarkedNullable == true + ) + if (valueParameter.returnTypeRef.coneType is ConeFlexibleType) { + ConeFlexibleType(type, type.withNullability(ConeNullability.NULLABLE)) + } else { + type + } + } else { + null + } + } } + else -> { + continue + } + } + if (newParameterTypes.none { it != null }) { + return this + } - return FirFakeOverrideGenerator.createCopyForFirFunction( - FirNamedFunctionSymbol(symbol.callableId), - this, - session, - FirDeclarationOrigin.Enhancement, - newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) -> - newType ?: valueParameter.returnTypeRef.coneType - }, + return FirFakeOverrideGenerator.createCopyForFirFunction( + FirNamedFunctionSymbol(symbol.callableId), + this, + session, + FirDeclarationOrigin.Enhancement, + newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) -> + newType ?: valueParameter.returnTypeRef.coneType + }, newDispatchReceiverType = dispatchReceiverType, ) - } + } return this } diff --git a/compiler/testData/codegen/box/bridges/objectClone.kt b/compiler/testData/codegen/box/bridges/objectClone.kt index e768b6a7f3e..773f66e04c4 100644 --- a/compiler/testData/codegen/box/bridges/objectClone.kt +++ b/compiler/testData/codegen/box/bridges/objectClone.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM import java.util.HashSet diff --git a/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt b/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt index 885e93727d6..fe221964d56 100644 --- a/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt +++ b/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // KJS_WITH_FULL_RUNTIME // IGNORE_BACKEND: NATIVE diff --git a/compiler/testData/codegen/box/jdk/removeIf.kt b/compiler/testData/codegen/box/jdk/removeIf.kt index d31d222dca8..17eb3f5578f 100644 --- a/compiler/testData/codegen/box/jdk/removeIf.kt +++ b/compiler/testData/codegen/box/jdk/removeIf.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // SKIP_JDK6 // TARGET_BACKEND: JVM // FULL_JDK diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAll.fir.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAll.fir.kt index 94b462adcc4..7b3f6352e90 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAll.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAll.fir.kt @@ -37,7 +37,7 @@ fun foo( cs: Collection, ca: Collection ) { a.containsAll(cs) - a.containsAll(ca) + a.containsAll(ca) b.containsAll(cs) b.containsAll(ca) @@ -46,11 +46,11 @@ fun foo( ic.containsAll(ca) ka.containsAll(cs) - ka.containsAll(ca) + ka.containsAll(ca) kb.containsAll(cs) kb.containsAll(ca) al.containsAll(cs) - al.containsAll(ca) + al.containsAll(ca) } diff --git a/compiler/testData/ir/irText/firProblems/MultiList.fir.txt b/compiler/testData/ir/irText/firProblems/MultiList.fir.txt new file mode 100644 index 00000000000..607bced201f --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/MultiList.fir.txt @@ -0,0 +1,579 @@ +FILE fqName: fileName:/MultiList.kt + CLASS CLASS name:Some modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Some.Some> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> (value:T of .Some) returnType:.Some.Some> [primary] + VALUE_PARAMETER name:value index:0 type:T of .Some + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Some modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:value visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final] + EXPRESSION_BODY + GET_VAR 'value: T of .Some declared in .Some.' type=T of .Some origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Some.Some>) returnType:T of .Some + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): T of .Some declared in .Some' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.' type=.Some.Some> origin=null + FUN name:component1 visibility:public modality:FINAL <> ($this:.Some.Some>) returnType:T of .Some + $this: VALUE_PARAMETER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): T of .Some declared in .Some' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.component1' type=.Some.Some> origin=null + FUN name:copy visibility:public modality:FINAL <> ($this:.Some.Some>, value:T of .Some) returnType:.Some.Some> + $this: VALUE_PARAMETER name: type:.Some.Some> + VALUE_PARAMETER name:value index:0 type:T of .Some + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.copy' type=.Some.Some> origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (value: T of .Some): .Some.Some> declared in .Some' + CONSTRUCTOR_CALL 'public constructor (value: T of .Some) [primary] declared in .Some' type=.Some.Some> origin=null + : kotlin.Any + value: GET_VAR 'value: T of .Some declared in .Some.copy' type=T of .Some origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Some.Some>, other:kotlin.Any?) returnType:kotlin.Boolean + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name: type:.Some.Some> + VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .Some.Some> declared in .Some.equals' type=.Some.Some> origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .Some.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in .Some' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.Some.Some> + GET_VAR 'other: kotlin.Any? declared in .Some.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in .Some' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Some.Some> [val] + TYPE_OP type=.Some.Some> origin=CAST typeOperand=.Some.Some> + GET_VAR 'other: kotlin.Any? declared in .Some.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.equals' type=.Some.Some> origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR 'val tmp_0: .Some.Some> [val] declared in .Some.equals' type=.Some.Some> origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in .Some' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in .Some' + CONST Boolean type=kotlin.Boolean value=true + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Some.Some>) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Some' + WHEN type=kotlin.Int origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.hashCode' type=.Some.Some> origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.hashCode' type=.Some.Some> origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Some.Some>) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Some' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="Some(" + CONST String type=kotlin.String value="value=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.toString' type=.Some.Some> origin=null + CONST String type=kotlin.String value=")" + CLASS INTERFACE name:MyList modality:ABSTRACT visibility:public superTypes:[kotlin.collections.List<.Some.MyList>>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyList.MyList> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + FUN FAKE_OVERRIDE name:contains visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, element:.Some.MyList>) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public abstract fun contains (element: E of kotlin.collections.List): kotlin.Boolean [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some.MyList> + FUN FAKE_OVERRIDE name:containsAll visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, elements:kotlin.collections.Collection<.Some.MyList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<.Some.MyList>> + FUN FAKE_OVERRIDE name:get visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, index:kotlin.Int) returnType:.Some.MyList> [fake_override,operator] + overridden: + public abstract fun get (index: kotlin.Int): E of kotlin.collections.List [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:indexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, element:.Some.MyList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun indexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some.MyList> + FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:iterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.collections.Iterator<.Some.MyList>> [fake_override,operator] + overridden: + public abstract fun iterator (): kotlin.collections.Iterator [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, element:.Some.MyList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun lastIndexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some.MyList> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.collections.ListIterator<.Some.MyList>> [fake_override] + overridden: + public abstract fun listIterator (): kotlin.collections.ListIterator declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, index:kotlin.Int) returnType:kotlin.collections.ListIterator<.Some.MyList>> [fake_override] + overridden: + public abstract fun listIterator (index: kotlin.Int): kotlin.collections.ListIterator declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:subList visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, fromIndex:kotlin.Int, toIndex:kotlin.Int) returnType:kotlin.collections.List<.Some.MyList>> [fake_override] + overridden: + public abstract fun subList (fromIndex: kotlin.Int, toIndex: kotlin.Int): kotlin.collections.List declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:fromIndex index:0 type:kotlin.Int + VALUE_PARAMETER name:toIndex index:1 type:kotlin.Int + PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + overridden: + public abstract fun (): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:SomeList modality:OPEN visibility:public superTypes:[.MyList.SomeList>; java.util.ArrayList<.Some.SomeList>>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.SomeList.SomeList> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> () returnType:.SomeList.SomeList> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in java.util.ArrayList' + : .Some.SomeList> + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:SomeList modality:OPEN visibility:public superTypes:[.MyList.SomeList>; java.util.ArrayList<.Some.SomeList>>]' + FUN FAKE_OVERRIDE name:contains visibility:public modality:OPEN <> ($this:kotlin.collections.List, element:.Some.SomeList>) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public abstract fun contains (element: .Some.MyList>): kotlin.Boolean [fake_override,operator] declared in .MyList + public open fun contains (p0: E of java.util.ArrayList?): kotlin.Boolean [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some.SomeList> + FUN FAKE_OVERRIDE name:containsAll visibility:public modality:OPEN <> ($this:kotlin.collections.List, elements:kotlin.collections.Collection<.Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection<.Some.MyList>>): kotlin.Boolean [fake_override] declared in .MyList + public open fun containsAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<.Some.SomeList>> + FUN FAKE_OVERRIDE name:get visibility:public modality:OPEN <> ($this:kotlin.collections.List, index:kotlin.Int) returnType:.Some.SomeList> [fake_override,operator] + overridden: + public abstract fun get (index: kotlin.Int): .Some.MyList> [fake_override,operator] declared in .MyList + public open fun get (p0: kotlin.Int): E of java.util.ArrayList? [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:indexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List, element:.Some.SomeList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun indexOf (element: .Some.MyList>): kotlin.Int [fake_override] declared in .MyList + public open fun indexOf (p0: E of java.util.ArrayList?): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some.SomeList> + FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:OPEN <> ($this:kotlin.collections.List) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.List + public open fun isEmpty (): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:iterator visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.collections.MutableIterator<.Some.SomeList>?> [fake_override,operator] + overridden: + public abstract fun iterator (): kotlin.collections.Iterator<.Some.MyList>> [fake_override,operator] declared in .MyList + public open fun iterator (): kotlin.collections.MutableIterator [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List, element:.Some.SomeList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun lastIndexOf (element: .Some.MyList>): kotlin.Int [fake_override] declared in .MyList + public open fun lastIndexOf (p0: E of java.util.ArrayList?): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some.SomeList> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.collections.MutableListIterator<.Some.SomeList>?> [fake_override] + overridden: + public abstract fun listIterator (): kotlin.collections.ListIterator<.Some.MyList>> [fake_override] declared in .MyList + public open fun listIterator (): kotlin.collections.MutableListIterator declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:kotlin.collections.MutableListIterator<.Some.SomeList>?> [fake_override] + overridden: + public abstract fun listIterator (index: kotlin.Int): kotlin.collections.ListIterator<.Some.MyList>> [fake_override] declared in .MyList + public open fun listIterator (p0: kotlin.Int): kotlin.collections.MutableListIterator declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:subList visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:kotlin.Int) returnType:kotlin.collections.MutableList<.Some.SomeList>?> [fake_override] + overridden: + public abstract fun subList (fromIndex: kotlin.Int, toIndex: kotlin.Int): kotlin.collections.List<.Some.MyList>> [fake_override] declared in .MyList + public open fun subList (p0: kotlin.Int, p1: kotlin.Int): kotlin.collections.MutableList declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:size visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Int [fake_override] + overridden: + public open fun size (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + overridden: + public abstract fun (): kotlin.Int declared in kotlin.collections.List + public abstract fun (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + public open fun equals (p0: kotlin.Any?): kotlin.Boolean [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + public open fun hashCode (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + public open fun toString (): kotlin.String declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:elementData visibility:public/*package*/ modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:.Some.SomeList>? [fake_override] + overridden: + public/*package*/ open fun elementData (p0: kotlin.Int): E of java.util.ArrayList? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:trimToSize visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Unit [fake_override] + overridden: + public open fun trimToSize (): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:ensureCapacity visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + public open fun ensureCapacity (p0: kotlin.Int): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:clone visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Any [fake_override] + overridden: + public open fun clone (): kotlin.Any declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Array? [fake_override] + overridden: + public open fun toArray (): kotlin.Array? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN ($this:java.util.ArrayList, p0:kotlin.Array.SomeList.toArray?>?) returnType:kotlin.Array.SomeList.toArray?>? [fake_override] + overridden: + public open fun toArray (p0: kotlin.Array?): kotlin.Array? declared in java.util.ArrayList + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Array.SomeList.toArray?>? + FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:.Some.SomeList>?) returnType:.Some.SomeList>? [fake_override,operator] + overridden: + public open fun set (p0: kotlin.Int, p1: E of java.util.ArrayList?): E of java.util.ArrayList? [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:.Some.SomeList>? + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:.Some.SomeList>?) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun add (p0: E of java.util.ArrayList?): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:.Some.SomeList>? + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:.Some.SomeList>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun add (p0: kotlin.Int, p1: E of java.util.ArrayList?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:.Some.SomeList>? + FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:.Some.SomeList>? [fake_override] + overridden: + public open fun remove (p0: kotlin.Int): E of java.util.ArrayList? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:.Some.SomeList>?) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun remove (p0: E of java.util.ArrayList?): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:.Some.SomeList>? + FUN FAKE_OVERRIDE name:clear visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Unit [fake_override] + overridden: + public open fun clear (): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.collections.Collection.Some.SomeList>?>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.collections.Collection.Some.SomeList>?> + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:kotlin.collections.Collection.Some.SomeList>?>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (p0: kotlin.Int, p1: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.collections.Collection.Some.SomeList>?> + FUN FAKE_OVERRIDE name:removeRange visibility:protected/*protected and package*/ modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + protected/*protected and package*/ open fun removeRange (p0: kotlin.Int, p1: kotlin.Int): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:removeAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.collections.Collection<.Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.collections.Collection<.Some.SomeList>> + FUN FAKE_OVERRIDE name:retainAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.collections.Collection<.Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun retainAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.collections.Collection<.Some.SomeList>> + FUN FAKE_OVERRIDE name:forEach visibility:public modality:OPEN <> ($this:java.lang.Iterable, p0:java.util.function.Consumer.Some.SomeList>?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun forEach (p0: java.util.function.Consumer.Some.MyList>?>?): kotlin.Unit declared in .MyList + public open fun forEach (p0: java.util.function.Consumer?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.lang.Iterable + VALUE_PARAMETER name:p0 index:0 type:java.util.function.Consumer.Some.SomeList>?>? + FUN FAKE_OVERRIDE name:spliterator visibility:public modality:OPEN <> ($this:java.util.Collection) returnType:java.util.Spliterator<.Some.SomeList>?> [fake_override] + overridden: + public open fun spliterator (): java.util.Spliterator<.Some.MyList>?> declared in .MyList + public open fun spliterator (): java.util.Spliterator declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.Collection + FUN FAKE_OVERRIDE name:removeIf visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:java.util.function.Predicate.Some.SomeList>?>?) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeIf (p0: java.util.function.Predicate?): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:java.util.function.Predicate.Some.SomeList>?>? + FUN FAKE_OVERRIDE name:replaceAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:java.util.function.UnaryOperator<.Some.SomeList>?>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun replaceAll (p0: java.util.function.UnaryOperator): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:java.util.function.UnaryOperator<.Some.SomeList>?> + FUN FAKE_OVERRIDE name:sort visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:java.util.Comparator.Some.SomeList>?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun sort (p0: java.util.Comparator?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:java.util.Comparator.Some.SomeList>?>? + FUN FAKE_OVERRIDE name:removeAt visibility:public modality:ABSTRACT <> ($this:kotlin.collections.MutableList, index:kotlin.Int) returnType:.Some.SomeList>? [fake_override] + overridden: + public abstract fun removeAt (index: kotlin.Int): E of kotlin.collections.MutableList declared in kotlin.collections.MutableList + $this: VALUE_PARAMETER name: type:kotlin.collections.MutableList + VALUE_PARAMETER name:index index:0 type:kotlin.Int + CLASS CLASS name:FinalList modality:FINAL visibility:public superTypes:[.SomeList] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.FinalList + CONSTRUCTOR visibility:public <> () returnType:.FinalList [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .SomeList' + : kotlin.String + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:FinalList modality:FINAL visibility:public superTypes:[.SomeList]' + FUN FAKE_OVERRIDE name:contains visibility:public modality:OPEN <> ($this:kotlin.collections.List, element:.Some) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public abstract fun contains (element: E of kotlin.collections.List): kotlin.Boolean [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some + FUN FAKE_OVERRIDE name:containsAll visibility:public modality:OPEN <> ($this:kotlin.collections.List, elements:kotlin.collections.Collection<.Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<.Some> + FUN FAKE_OVERRIDE name:get visibility:public modality:OPEN <> ($this:kotlin.collections.List, index:kotlin.Int) returnType:.Some [fake_override,operator] + overridden: + public abstract fun get (index: kotlin.Int): E of kotlin.collections.List [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:indexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List, element:.Some) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun indexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some + FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:OPEN <> ($this:kotlin.collections.List) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.List + public open fun isEmpty (): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:iterator visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.collections.MutableIterator<.Some?> [fake_override,operator] + overridden: + public open fun iterator (): kotlin.collections.MutableIterator [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List, element:.Some) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun lastIndexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List + VALUE_PARAMETER name:element index:0 type:.Some + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.collections.MutableListIterator<.Some?> [fake_override] + overridden: + public open fun listIterator (): kotlin.collections.MutableListIterator declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:kotlin.collections.MutableListIterator<.Some?> [fake_override] + overridden: + public open fun listIterator (p0: kotlin.Int): kotlin.collections.MutableListIterator declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:subList visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:kotlin.Int) returnType:kotlin.collections.MutableList<.Some?> [fake_override] + overridden: + public open fun subList (p0: kotlin.Int, p1: kotlin.Int): kotlin.collections.MutableList declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:size visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Int [fake_override] + overridden: + public open fun size (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + overridden: + public abstract fun (): kotlin.Int declared in kotlin.collections.List + public abstract fun (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + public open fun equals (p0: kotlin.Any?): kotlin.Boolean [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + public open fun hashCode (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + public open fun toString (): kotlin.String declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:elementData visibility:public/*package*/ modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:.Some? [fake_override] + overridden: + public/*package*/ open fun elementData (p0: kotlin.Int): E of java.util.ArrayList? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:trimToSize visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Unit [fake_override] + overridden: + public open fun trimToSize (): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:ensureCapacity visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + public open fun ensureCapacity (p0: kotlin.Int): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:clone visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Any [fake_override] + overridden: + public open fun clone (): kotlin.Any declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Array? [fake_override] + overridden: + public open fun toArray (): kotlin.Array? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN ($this:java.util.ArrayList, p0:kotlin.Array.FinalList.toArray?>?) returnType:kotlin.Array.FinalList.toArray?>? [fake_override] + overridden: + public open fun toArray (p0: kotlin.Array?): kotlin.Array? declared in java.util.ArrayList + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Array.FinalList.toArray?>? + FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:.Some?) returnType:.Some? [fake_override,operator] + overridden: + public open fun set (p0: kotlin.Int, p1: E of java.util.ArrayList?): E of java.util.ArrayList? [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:.Some? + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:.Some?) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun add (p0: E of java.util.ArrayList?): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:.Some? + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:.Some?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun add (p0: kotlin.Int, p1: E of java.util.ArrayList?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:.Some? + FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int) returnType:.Some? [fake_override] + overridden: + public open fun remove (p0: kotlin.Int): E of java.util.ArrayList? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:.Some?) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun remove (p0: E of java.util.ArrayList?): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:.Some? + FUN FAKE_OVERRIDE name:clear visibility:public modality:OPEN <> ($this:java.util.ArrayList) returnType:kotlin.Unit [fake_override] + overridden: + public open fun clear (): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.collections.Collection.Some?>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.collections.Collection.Some?> + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:kotlin.collections.Collection.Some?>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (p0: kotlin.Int, p1: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.collections.Collection.Some?> + FUN FAKE_OVERRIDE name:removeRange visibility:protected/*protected and package*/ modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.Int, p1:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + protected/*protected and package*/ open fun removeRange (p0: kotlin.Int, p1: kotlin.Int): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:removeAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.collections.Collection<.Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.collections.Collection<.Some> + FUN FAKE_OVERRIDE name:retainAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:kotlin.collections.Collection<.Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun retainAll (p0: kotlin.collections.Collection): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:kotlin.collections.Collection<.Some> + FUN FAKE_OVERRIDE name:forEach visibility:public modality:OPEN <> ($this:java.lang.Iterable, p0:java.util.function.Consumer.Some?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun forEach (p0: java.util.function.Consumer?): kotlin.Unit declared in java.lang.Iterable + $this: VALUE_PARAMETER name: type:java.lang.Iterable + VALUE_PARAMETER name:p0 index:0 type:java.util.function.Consumer.Some?>? + FUN FAKE_OVERRIDE name:spliterator visibility:public modality:OPEN <> ($this:java.util.Collection) returnType:java.util.Spliterator<.Some?> [fake_override] + overridden: + public open fun spliterator (): java.util.Spliterator declared in java.util.Collection + $this: VALUE_PARAMETER name: type:java.util.Collection + FUN FAKE_OVERRIDE name:removeIf visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:java.util.function.Predicate.Some?>?) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeIf (p0: java.util.function.Predicate?): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:java.util.function.Predicate.Some?>? + FUN FAKE_OVERRIDE name:replaceAll visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:java.util.function.UnaryOperator<.Some?>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun replaceAll (p0: java.util.function.UnaryOperator): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:java.util.function.UnaryOperator<.Some?> + FUN FAKE_OVERRIDE name:sort visibility:public modality:OPEN <> ($this:java.util.ArrayList, p0:java.util.Comparator.Some?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun sort (p0: java.util.Comparator?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList + VALUE_PARAMETER name:p0 index:0 type:java.util.Comparator.Some?>? + FUN FAKE_OVERRIDE name:removeAt visibility:public modality:ABSTRACT <> ($this:kotlin.collections.MutableList, index:kotlin.Int) returnType:.Some? [fake_override] + overridden: + public abstract fun removeAt (index: kotlin.Int): E of kotlin.collections.MutableList declared in kotlin.collections.MutableList + $this: VALUE_PARAMETER name: type:kotlin.collections.MutableList + VALUE_PARAMETER name:index index:0 type:kotlin.Int diff --git a/compiler/testData/ir/irText/firProblems/MultiList.kt b/compiler/testData/ir/irText/firProblems/MultiList.kt new file mode 100644 index 00000000000..fb3a141f113 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/MultiList.kt @@ -0,0 +1,11 @@ +// FULL_JDK + +import java.util.ArrayList + +data class Some(val value: T) + +interface MyList : List> + +open class SomeList : MyList, ArrayList>() + +class FinalList : SomeList() diff --git a/compiler/testData/ir/irText/firProblems/MultiList.txt b/compiler/testData/ir/irText/firProblems/MultiList.txt new file mode 100644 index 00000000000..c5eec0e61d2 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/MultiList.txt @@ -0,0 +1,583 @@ +FILE fqName: fileName:/MultiList.kt + CLASS CLASS name:Some modality:FINAL visibility:public [data] superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Some.Some> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> (value:T of .Some) returnType:.Some.Some> [primary] + VALUE_PARAMETER name:value index:0 type:T of .Some + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Some modality:FINAL visibility:public [data] superTypes:[kotlin.Any]' + PROPERTY name:value visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final] + EXPRESSION_BODY + GET_VAR 'value: T of .Some declared in .Some.' type=T of .Some origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Some.Some>) returnType:T of .Some + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): T of .Some declared in .Some' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.' type=.Some.Some> origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:.Some.Some>) returnType:T of .Some [operator] + $this: VALUE_PARAMETER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun component1 (): T of .Some [operator] declared in .Some' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.component1' type=.Some.Some> origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:.Some.Some>, value:T of .Some) returnType:.Some.Some> + $this: VALUE_PARAMETER name: type:.Some.Some> + VALUE_PARAMETER name:value index:0 type:T of .Some + EXPRESSION_BODY + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.copy' type=.Some.Some> origin=null + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun copy (value: T of .Some): .Some.Some> declared in .Some' + CONSTRUCTOR_CALL 'public constructor (value: T of .Some) [primary] declared in .Some' type=.Some.Some> origin=null + : T of .Some + value: GET_VAR 'value: T of .Some declared in .Some.copy' type=T of .Some origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Some.Some>) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Some' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="Some(" + CONST String type=kotlin.String value="value=" + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.toString' type=.Some.Some> origin=null + CONST String type=kotlin.String value=")" + FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Some.Some>) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Some.Some> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Some' + WHEN type=kotlin.Int origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.hashCode' type=.Some.Some> origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Int type=kotlin.Int value=0 + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.hashCode' type=.Some.Some> origin=null + FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Some.Some>, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:.Some.Some> + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ + arg0: GET_VAR ': .Some.Some> declared in .Some.equals' type=.Some.Some> origin=null + arg1: GET_VAR 'other: kotlin.Any? declared in .Some.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Some' + CONST Boolean type=kotlin.Boolean value=true + WHEN type=kotlin.Unit origin=null + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=.Some.Some> + GET_VAR 'other: kotlin.Any? declared in .Some.equals' type=kotlin.Any? origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Some' + CONST Boolean type=kotlin.Boolean value=false + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Some.Some> [val] + TYPE_OP type=.Some.Some> origin=CAST typeOperand=.Some.Some> + GET_VAR 'other: kotlin.Any? declared in .Some.equals' type=kotlin.Any? origin=null + WHEN type=kotlin.Unit origin=null + BRANCH + if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ + $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ + arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR ': .Some.Some> declared in .Some.equals' type=.Some.Some> origin=null + arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:T of .Some visibility:private [final]' type=T of .Some origin=null + receiver: GET_VAR 'val tmp_0: .Some.Some> [val] declared in .Some.equals' type=.Some.Some> origin=null + then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Some' + CONST Boolean type=kotlin.Boolean value=false + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Some' + CONST Boolean type=kotlin.Boolean value=true + CLASS INTERFACE name:MyList modality:ABSTRACT visibility:public superTypes:[kotlin.collections.List<.Some.MyList>>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyList.MyList> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + FUN FAKE_OVERRIDE name:contains visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, element:.Some.MyList>) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public abstract fun contains (element: E of kotlin.collections.List): kotlin.Boolean [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:element index:0 type:.Some.MyList> + FUN FAKE_OVERRIDE name:containsAll visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, elements:kotlin.collections.Collection<.Some.MyList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<.Some.MyList>> + FUN FAKE_OVERRIDE name:get visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, index:kotlin.Int) returnType:.Some.MyList> [fake_override,operator] + overridden: + public abstract fun get (index: kotlin.Int): E of kotlin.collections.List [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:indexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, element:.Some.MyList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun indexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:element index:0 type:.Some.MyList> + FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + FUN FAKE_OVERRIDE name:iterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>) returnType:kotlin.collections.Iterator<.Some.MyList>> [fake_override,operator] + overridden: + public abstract fun iterator (): kotlin.collections.Iterator [operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, element:.Some.MyList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun lastIndexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:element index:0 type:.Some.MyList> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>) returnType:kotlin.collections.ListIterator<.Some.MyList>> [fake_override] + overridden: + public abstract fun listIterator (): kotlin.collections.ListIterator declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, index:kotlin.Int) returnType:kotlin.collections.ListIterator<.Some.MyList>> [fake_override] + overridden: + public abstract fun listIterator (index: kotlin.Int): kotlin.collections.ListIterator declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:subList visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>, fromIndex:kotlin.Int, toIndex:kotlin.Int) returnType:kotlin.collections.List<.Some.MyList>> [fake_override] + overridden: + public abstract fun subList (fromIndex: kotlin.Int, toIndex: kotlin.Int): kotlin.collections.List declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + VALUE_PARAMETER name:fromIndex index:0 type:kotlin.Int + VALUE_PARAMETER name:toIndex index:1 type:kotlin.Int + PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<.Some.MyList>>) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val] + overridden: + public abstract fun (): kotlin.Int declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:forEach visibility:public modality:OPEN <> ($this:kotlin.collections.Iterable<.Some.MyList>>, p0:@[FlexibleNullability] java.util.function.Consumer.Some.MyList>?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun forEach (p0: @[FlexibleNullability] java.util.function.Consumer?): kotlin.Unit [fake_override] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.Iterable<.Some.MyList>> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.function.Consumer.Some.MyList>?>? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:parallelStream visibility:public modality:OPEN <> ($this:kotlin.collections.Collection<.Some.MyList>>) returnType:@[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.MyList>> [fake_override] + overridden: + public open fun parallelStream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] E of kotlin.collections.List> [fake_override] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.Collection<.Some.MyList>> + FUN FAKE_OVERRIDE name:spliterator visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.MyList>>) returnType:@[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] .Some.MyList>?> [fake_override] + overridden: + public open fun spliterator (): @[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] E of kotlin.collections.List?> declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.MyList>> + FUN FAKE_OVERRIDE name:stream visibility:public modality:OPEN <> ($this:kotlin.collections.Collection<.Some.MyList>>) returnType:@[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.MyList>> [fake_override] + overridden: + public open fun stream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] E of kotlin.collections.List> [fake_override] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.collections.Collection<.Some.MyList>> + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.List + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:SomeList modality:OPEN visibility:public superTypes:[.MyList.SomeList>; java.util.ArrayList<.Some.SomeList>>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.SomeList.SomeList> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> () returnType:.SomeList.SomeList> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in java.util.ArrayList' + : @[FlexibleNullability] .Some.SomeList>? + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:SomeList modality:OPEN visibility:public superTypes:[.MyList.SomeList>; java.util.ArrayList<.Some.SomeList>>]' + PROPERTY FAKE_OVERRIDE name:modCount visibility:protected/*protected and package*/ modality:FINAL [fake_override,var] + FUN FAKE_OVERRIDE name:removeRange visibility:protected/*protected and package*/ modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, p0:kotlin.Int, p1:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + protected/*protected and package*/ open fun removeRange (p0: kotlin.Int, p1: kotlin.Int): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:sort visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, p0:@[FlexibleNullability] java.util.Comparator.Some.SomeList>?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun sort (p0: @[FlexibleNullability] java.util.Comparator?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.Comparator.Some.SomeList>?>? + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN ($this:java.util.ArrayList<.Some.SomeList>>, p0:@[FlexibleNullability] kotlin.Array.SomeList.toArray?>?) returnType:@[FlexibleNullability] kotlin.Array.SomeList.toArray?>? [fake_override] + overridden: + public open fun toArray (p0: @[FlexibleNullability] kotlin.Array?): @[FlexibleNullability] kotlin.Array? declared in java.util.ArrayList + TYPE_PARAMETER name:T index:0 variance: superTypes:[@[FlexibleNullability] kotlin.Any?] + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] kotlin.Array.SomeList.toArray?>? + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, element:@[EnhancedNullability] .Some.SomeList>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun add (element: @[EnhancedNullability] E of java.util.ArrayList): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:element index:0 type:@[EnhancedNullability] .Some.SomeList> + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, index:kotlin.Int, element:@[EnhancedNullability] .Some.SomeList>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun add (index: kotlin.Int, element: @[EnhancedNullability] E of java.util.ArrayList): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + VALUE_PARAMETER name:element index:1 type:@[EnhancedNullability] .Some.SomeList> + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, elements:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (elements: @[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] E of java.util.ArrayList>): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:elements index:0 type:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>> + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, index:kotlin.Int, elements:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (index: kotlin.Int, elements: @[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] E of java.util.ArrayList>): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + VALUE_PARAMETER name:elements index:1 type:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>> + FUN FAKE_OVERRIDE name:clear visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun clear (): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + FUN FAKE_OVERRIDE name:clone visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>) returnType:@[EnhancedNullability] kotlin.Any [fake_override] + overridden: + public open fun clone (): @[EnhancedNullability] kotlin.Any declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + FUN FAKE_OVERRIDE name:ensureCapacity visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, p0:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + public open fun ensureCapacity (p0: kotlin.Int): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, element:@[EnhancedNullability] .Some.SomeList>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun remove (element: @[EnhancedNullability] E of java.util.ArrayList): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:element index:0 type:@[EnhancedNullability] .Some.SomeList> + FUN FAKE_OVERRIDE name:removeAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, elements:kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeAll (elements: kotlin.collections.Collection<@[EnhancedNullability] E of java.util.ArrayList>): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>> + FUN FAKE_OVERRIDE name:removeAt visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, p0:kotlin.Int) returnType:@[EnhancedNullability] .Some.SomeList> [fake_override] + overridden: + public open fun removeAt (p0: kotlin.Int): @[EnhancedNullability] E of java.util.ArrayList declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:removeIf visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, p0:@[EnhancedNullability] java.util.function.Predicate.Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeIf (p0: @[EnhancedNullability] java.util.function.Predicate): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] java.util.function.Predicate.Some.SomeList>> + FUN FAKE_OVERRIDE name:replaceAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, p0:@[EnhancedNullability] java.util.function.UnaryOperator<@[EnhancedNullability] .Some.SomeList>>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun replaceAll (p0: @[EnhancedNullability] java.util.function.UnaryOperator<@[EnhancedNullability] E of java.util.ArrayList>): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] java.util.function.UnaryOperator<@[EnhancedNullability] .Some.SomeList>> + FUN FAKE_OVERRIDE name:retainAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, elements:kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun retainAll (elements: kotlin.collections.Collection<@[EnhancedNullability] E of java.util.ArrayList>): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>> + FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, index:kotlin.Int, element:@[EnhancedNullability] .Some.SomeList>) returnType:@[EnhancedNullability] .Some.SomeList> [fake_override,operator] + overridden: + public open fun set (index: kotlin.Int, element: @[EnhancedNullability] E of java.util.ArrayList): @[EnhancedNullability] E of java.util.ArrayList [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + VALUE_PARAMETER name:element index:1 type:@[EnhancedNullability] .Some.SomeList> + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>) returnType:@[FlexibleNullability] kotlin.Array? [fake_override] + overridden: + public open fun toArray (): @[FlexibleNullability] kotlin.Array? declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + FUN FAKE_OVERRIDE name:trimToSize visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun trimToSize (): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + FUN FAKE_OVERRIDE name:contains visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>, element:.Some.SomeList>) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public abstract fun contains (element: .Some.MyList>): kotlin.Boolean [fake_override,operator] declared in .MyList + public open fun contains (element: @[EnhancedNullability] E of java.util.ArrayList): kotlin.Boolean [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + VALUE_PARAMETER name:element index:0 type:.Some.SomeList> + FUN FAKE_OVERRIDE name:containsAll visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>, elements:kotlin.collections.Collection<.Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection<.Some.MyList>>): kotlin.Boolean [fake_override] declared in .MyList + public open fun containsAll (elements: kotlin.collections.Collection<@[EnhancedNullability] E of java.util.ArrayList>): kotlin.Boolean [fake_override] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<.Some.SomeList>> + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .MyList + public open fun equals (other: @[EnhancedNullability] kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:forEach visibility:public modality:OPEN <> ($this:kotlin.collections.Iterable<.Some.SomeList>>, p0:@[FlexibleNullability] java.util.function.Consumer.Some.SomeList>?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun forEach (p0: @[FlexibleNullability] java.util.function.Consumer.Some.MyList>?>?): kotlin.Unit [fake_override] declared in .MyList + public open fun forEach (p0: @[FlexibleNullability] java.util.function.Consumer?): kotlin.Unit declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.Iterable<.Some.SomeList>> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.function.Consumer.Some.SomeList>?>? + FUN FAKE_OVERRIDE name:get visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>, index:kotlin.Int) returnType:.Some.SomeList> [fake_override,operator] + overridden: + public abstract fun get (index: kotlin.Int): .Some.MyList> [fake_override,operator] declared in .MyList + public open fun get (index: kotlin.Int): @[EnhancedNullability] E of java.util.ArrayList [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .MyList + public open fun hashCode (): kotlin.Int [fake_override] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:indexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>, element:.Some.SomeList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun indexOf (element: .Some.MyList>): kotlin.Int [fake_override] declared in .MyList + public open fun indexOf (element: @[EnhancedNullability] E of java.util.ArrayList): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + VALUE_PARAMETER name:element index:0 type:.Some.SomeList> + FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>) returnType:kotlin.Boolean [fake_override] + overridden: + public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in .MyList + public open fun isEmpty (): kotlin.Boolean declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + FUN FAKE_OVERRIDE name:iterator visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>) returnType:@[EnhancedNullability] kotlin.collections.MutableIterator<@[EnhancedNullability] .Some.SomeList>> [fake_override,operator] + overridden: + public abstract fun iterator (): kotlin.collections.Iterator<.Some.MyList>> [fake_override,operator] declared in .MyList + public open fun iterator (): @[EnhancedNullability] kotlin.collections.MutableIterator<@[EnhancedNullability] E of java.util.ArrayList> [operator] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>, element:.Some.SomeList>) returnType:kotlin.Int [fake_override] + overridden: + public abstract fun lastIndexOf (element: .Some.MyList>): kotlin.Int [fake_override] declared in .MyList + public open fun lastIndexOf (element: @[EnhancedNullability] E of java.util.ArrayList): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + VALUE_PARAMETER name:element index:0 type:.Some.SomeList> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>) returnType:@[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] .Some.SomeList>> [fake_override] + overridden: + public abstract fun listIterator (): kotlin.collections.ListIterator<.Some.MyList>> [fake_override] declared in .MyList + public open fun listIterator (): @[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] E of java.util.ArrayList> declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, index:kotlin.Int) returnType:@[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] .Some.SomeList>> [fake_override] + overridden: + public abstract fun listIterator (index: kotlin.Int): kotlin.collections.ListIterator<.Some.MyList>> [fake_override] declared in .MyList + public open fun listIterator (index: kotlin.Int): @[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] E of java.util.ArrayList> declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:parallelStream visibility:public modality:OPEN <> ($this:kotlin.collections.Collection<.Some.SomeList>>) returnType:@[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.SomeList>> [fake_override] + overridden: + public open fun parallelStream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.MyList>> [fake_override] declared in .MyList + public open fun parallelStream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] E of java.util.ArrayList> [fake_override] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.Collection<.Some.SomeList>> + FUN FAKE_OVERRIDE name:spliterator visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>) returnType:@[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] .Some.SomeList>?> [fake_override] + overridden: + public open fun spliterator (): @[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] .Some.MyList>?> [fake_override] declared in .MyList + public open fun spliterator (): @[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] E of java.util.ArrayList?> declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + FUN FAKE_OVERRIDE name:stream visibility:public modality:OPEN <> ($this:kotlin.collections.Collection<.Some.SomeList>>) returnType:@[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.SomeList>> [fake_override] + overridden: + public open fun stream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.MyList>> [fake_override] declared in .MyList + public open fun stream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] E of java.util.ArrayList> [fake_override] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.Collection<.Some.SomeList>> + FUN FAKE_OVERRIDE name:subList visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some.SomeList>>, fromIndex:kotlin.Int, toIndex:kotlin.Int) returnType:@[EnhancedNullability] kotlin.collections.MutableList<@[EnhancedNullability] .Some.SomeList>> [fake_override] + overridden: + public abstract fun subList (fromIndex: kotlin.Int, toIndex: kotlin.Int): kotlin.collections.List<.Some.MyList>> [fake_override] declared in .MyList + public open fun subList (fromIndex: kotlin.Int, toIndex: kotlin.Int): @[EnhancedNullability] kotlin.collections.MutableList<@[EnhancedNullability] E of java.util.ArrayList> declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some.SomeList>> + VALUE_PARAMETER name:fromIndex index:0 type:kotlin.Int + VALUE_PARAMETER name:toIndex index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .MyList + public open fun toString (): @[EnhancedNullability] kotlin.String [fake_override] declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.Any + PROPERTY FAKE_OVERRIDE name:size visibility:public modality:OPEN [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some.SomeList>>) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:size visibility:public modality:OPEN [fake_override,val] + overridden: + public abstract fun (): kotlin.Int [fake_override] declared in .MyList + public open fun (): kotlin.Int declared in java.util.ArrayList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some.SomeList>> + CLASS CLASS name:FinalList modality:FINAL visibility:public superTypes:[.SomeList] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.FinalList + CONSTRUCTOR visibility:public <> () returnType:.FinalList [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .SomeList' + : kotlin.String + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:FinalList modality:FINAL visibility:public superTypes:[.SomeList]' + PROPERTY FAKE_OVERRIDE name:modCount visibility:protected/*protected and package*/ modality:FINAL [fake_override,var] + FUN FAKE_OVERRIDE name:removeRange visibility:protected/*protected and package*/ modality:OPEN <> ($this:java.util.ArrayList<.Some>, p0:kotlin.Int, p1:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + protected/*protected and package*/ open fun removeRange (p0: kotlin.Int, p1: kotlin.Int): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:sort visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, p0:@[FlexibleNullability] java.util.Comparator.Some?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun sort (p0: @[FlexibleNullability] java.util.Comparator.Some.SomeList>?>?): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.Comparator.Some?>? + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN ($this:java.util.ArrayList<.Some>, p0:@[FlexibleNullability] kotlin.Array.FinalList.toArray?>?) returnType:@[FlexibleNullability] kotlin.Array.FinalList.toArray?>? [fake_override] + overridden: + public open fun toArray (p0: @[FlexibleNullability] kotlin.Array.SomeList.toArray?>?): @[FlexibleNullability] kotlin.Array.SomeList.toArray?>? [fake_override] declared in .SomeList + TYPE_PARAMETER name:T index:0 variance: superTypes:[@[FlexibleNullability] kotlin.Any?] + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] kotlin.Array.FinalList.toArray?>? + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, element:@[EnhancedNullability] .Some) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun add (element: @[EnhancedNullability] .Some.SomeList>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:element index:0 type:@[EnhancedNullability] .Some + FUN FAKE_OVERRIDE name:add visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, index:kotlin.Int, element:@[EnhancedNullability] .Some) returnType:kotlin.Unit [fake_override] + overridden: + public open fun add (index: kotlin.Int, element: @[EnhancedNullability] .Some.SomeList>): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + VALUE_PARAMETER name:element index:1 type:@[EnhancedNullability] .Some + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, elements:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (elements: @[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:elements index:0 type:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some> + FUN FAKE_OVERRIDE name:addAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, index:kotlin.Int, elements:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun addAll (index: kotlin.Int, elements: @[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + VALUE_PARAMETER name:elements index:1 type:@[EnhancedNullability] kotlin.collections.Collection<@[EnhancedNullability] .Some> + FUN FAKE_OVERRIDE name:clear visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun clear (): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + FUN FAKE_OVERRIDE name:clone visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>) returnType:@[EnhancedNullability] kotlin.Any [fake_override] + overridden: + public open fun clone (): @[EnhancedNullability] kotlin.Any [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + FUN FAKE_OVERRIDE name:contains visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>, element:.Some) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun contains (element: .Some.SomeList>): kotlin.Boolean [fake_override,operator] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + VALUE_PARAMETER name:element index:0 type:.Some + FUN FAKE_OVERRIDE name:containsAll visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>, elements:kotlin.collections.Collection<.Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun containsAll (elements: kotlin.collections.Collection<.Some.SomeList>>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<.Some> + FUN FAKE_OVERRIDE name:ensureCapacity visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, p0:kotlin.Int) returnType:kotlin.Unit [fake_override] + overridden: + public open fun ensureCapacity (p0: kotlin.Int): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:forEach visibility:public modality:OPEN <> ($this:kotlin.collections.Iterable<.Some>, p0:@[FlexibleNullability] java.util.function.Consumer.Some?>?) returnType:kotlin.Unit [fake_override] + overridden: + public open fun forEach (p0: @[FlexibleNullability] java.util.function.Consumer.Some.SomeList>?>?): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.Iterable<.Some> + VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] java.util.function.Consumer.Some?>? + FUN FAKE_OVERRIDE name:get visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>, index:kotlin.Int) returnType:.Some [fake_override,operator] + overridden: + public open fun get (index: kotlin.Int): .Some.SomeList> [fake_override,operator] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:indexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>, element:.Some) returnType:kotlin.Int [fake_override] + overridden: + public open fun indexOf (element: .Some.SomeList>): kotlin.Int [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + VALUE_PARAMETER name:element index:0 type:.Some + FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun isEmpty (): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + FUN FAKE_OVERRIDE name:iterator visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>) returnType:@[EnhancedNullability] kotlin.collections.MutableIterator<@[EnhancedNullability] .Some> [fake_override,operator] + overridden: + public open fun iterator (): @[EnhancedNullability] kotlin.collections.MutableIterator<@[EnhancedNullability] .Some.SomeList>> [fake_override,operator] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>, element:.Some) returnType:kotlin.Int [fake_override] + overridden: + public open fun lastIndexOf (element: .Some.SomeList>): kotlin.Int [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + VALUE_PARAMETER name:element index:0 type:.Some + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>) returnType:@[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] .Some> [fake_override] + overridden: + public open fun listIterator (): @[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] .Some.SomeList>> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + FUN FAKE_OVERRIDE name:listIterator visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, index:kotlin.Int) returnType:@[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] .Some> [fake_override] + overridden: + public open fun listIterator (index: kotlin.Int): @[EnhancedNullability] kotlin.collections.MutableListIterator<@[EnhancedNullability] .Some.SomeList>> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:parallelStream visibility:public modality:OPEN <> ($this:kotlin.collections.Collection<.Some>) returnType:@[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some> [fake_override] + overridden: + public open fun parallelStream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.SomeList>> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.Collection<.Some> + FUN FAKE_OVERRIDE name:remove visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, element:@[EnhancedNullability] .Some) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun remove (element: @[EnhancedNullability] .Some.SomeList>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:element index:0 type:@[EnhancedNullability] .Some + FUN FAKE_OVERRIDE name:removeAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, elements:kotlin.collections.Collection<@[EnhancedNullability] .Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeAll (elements: kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[EnhancedNullability] .Some> + FUN FAKE_OVERRIDE name:removeAt visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, p0:kotlin.Int) returnType:@[EnhancedNullability] .Some [fake_override] + overridden: + public open fun removeAt (p0: kotlin.Int): @[EnhancedNullability] .Some.SomeList> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + FUN FAKE_OVERRIDE name:removeIf visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, p0:@[EnhancedNullability] java.util.function.Predicate.Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun removeIf (p0: @[EnhancedNullability] java.util.function.Predicate.Some.SomeList>>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] java.util.function.Predicate.Some> + FUN FAKE_OVERRIDE name:replaceAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, p0:@[EnhancedNullability] java.util.function.UnaryOperator<@[EnhancedNullability] .Some>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun replaceAll (p0: @[EnhancedNullability] java.util.function.UnaryOperator<@[EnhancedNullability] .Some.SomeList>>): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:p0 index:0 type:@[EnhancedNullability] java.util.function.UnaryOperator<@[EnhancedNullability] .Some> + FUN FAKE_OVERRIDE name:retainAll visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, elements:kotlin.collections.Collection<@[EnhancedNullability] .Some>) returnType:kotlin.Boolean [fake_override] + overridden: + public open fun retainAll (elements: kotlin.collections.Collection<@[EnhancedNullability] .Some.SomeList>>): kotlin.Boolean [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[EnhancedNullability] .Some> + FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, index:kotlin.Int, element:@[EnhancedNullability] .Some) returnType:@[EnhancedNullability] .Some [fake_override,operator] + overridden: + public open fun set (index: kotlin.Int, element: @[EnhancedNullability] .Some.SomeList>): @[EnhancedNullability] .Some.SomeList> [fake_override,operator] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:index index:0 type:kotlin.Int + VALUE_PARAMETER name:element index:1 type:@[EnhancedNullability] .Some + FUN FAKE_OVERRIDE name:spliterator visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>) returnType:@[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] .Some?> [fake_override] + overridden: + public open fun spliterator (): @[EnhancedNullability] java.util.Spliterator<@[FlexibleNullability] .Some.SomeList>?> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> + FUN FAKE_OVERRIDE name:stream visibility:public modality:OPEN <> ($this:kotlin.collections.Collection<.Some>) returnType:@[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some> [fake_override] + overridden: + public open fun stream (): @[EnhancedNullability] java.util.stream.Stream<@[EnhancedNullability] .Some.SomeList>> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.Collection<.Some> + FUN FAKE_OVERRIDE name:subList visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>, fromIndex:kotlin.Int, toIndex:kotlin.Int) returnType:@[EnhancedNullability] kotlin.collections.MutableList<@[EnhancedNullability] .Some> [fake_override] + overridden: + public open fun subList (fromIndex: kotlin.Int, toIndex: kotlin.Int): @[EnhancedNullability] kotlin.collections.MutableList<@[EnhancedNullability] .Some.SomeList>> [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + VALUE_PARAMETER name:fromIndex index:0 type:kotlin.Int + VALUE_PARAMETER name:toIndex index:1 type:kotlin.Int + FUN FAKE_OVERRIDE name:toArray visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>) returnType:@[FlexibleNullability] kotlin.Array? [fake_override] + overridden: + public open fun toArray (): @[FlexibleNullability] kotlin.Array? [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:trimToSize visibility:public modality:OPEN <> ($this:java.util.ArrayList<.Some>) returnType:kotlin.Unit [fake_override] + overridden: + public open fun trimToSize (): kotlin.Unit [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:java.util.ArrayList<.Some> + PROPERTY FAKE_OVERRIDE name:size visibility:public modality:OPEN [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:OPEN <> ($this:kotlin.collections.List<.Some>) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:size visibility:public modality:OPEN [fake_override,val] + overridden: + public open fun (): kotlin.Int [fake_override] declared in .SomeList + $this: VALUE_PARAMETER name: type:kotlin.collections.List<.Some> diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index d5ec6b0767e..aa61fda0983 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1776,6 +1776,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/firProblems/InnerClassInAnonymous.kt"); } + @TestMetadata("MultiList.kt") + public void testMultiList() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/MultiList.kt"); + } + @TestMetadata("putIfAbsent.kt") public void testPutIfAbsent() throws Exception { runTest("compiler/testData/ir/irText/firProblems/putIfAbsent.kt"); From 60141ccbaa3e111ce5b610f00e022487db288bd8 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 28 Oct 2020 11:53:51 +0300 Subject: [PATCH 058/554] [FIR] Fix Substitution scope key to avoid accidental matches --- .../kotlin/fir/Fir2IrTextTestGenerated.java | 5 + .../kotlin/fir/resolve/SupertypeUtils.kt | 9 +- .../DelegationAndInheritanceFromJava.fir.txt | 171 ++++++++++++++++++ .../DelegationAndInheritanceFromJava.kt | 18 ++ .../DelegationAndInheritanceFromJava.txt | 156 ++++++++++++++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 5 + 6 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt create mode 100644 compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.kt create mode 100644 compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index 5083f864fde..d063e15a6b1 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1762,6 +1762,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/firProblems/DeepCopyIrTree.kt"); } + @TestMetadata("DelegationAndInheritanceFromJava.kt") + public void testDelegationAndInheritanceFromJava() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.kt"); + } + @TestMetadata("deprecated.kt") public void testDeprecated() throws Exception { runTest("compiler/testData/ir/irText/firProblems/deprecated.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt index 4ef186f110e..50098901189 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.model.CaptureStatus abstract class SupertypeSupplier { @@ -59,7 +60,11 @@ inline fun scopeSessionKey(): ScopeSes val USE_SITE = scopeSessionKey, FirTypeScope>() -data class SubstitutionScopeKey(val type: ConeClassLikeType) : ScopeSessionKey, FirClassSubstitutionScope>() +data class SubstitutionScopeKey( + val type: ConeClassLikeType, + // This property is necessary. Otherwise we may have accidental matching when two classes have the same supertype + val derivedClassId: ClassId +) : ScopeSessionKey, FirClassSubstitutionScope>() /* TODO REMOVE */ fun createSubstitution( @@ -93,7 +98,7 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed( derivedClass: FirRegularClass ): FirTypeScope { if (this.typeArguments.isEmpty()) return useSiteMemberScope - return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) { + return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this, derivedClass.symbol.classId)) { val typeParameters = (declaration as? FirTypeParameterRefsOwner)?.typeParameters.orEmpty() val originalSubstitution = createSubstitution(typeParameters, this, session) val platformClass = session.platformClassMapper.getCorrespondingPlatformClass(declaration) diff --git a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt new file mode 100644 index 00000000000..62dfe155ea2 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt @@ -0,0 +1,171 @@ +FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt + CLASS CLASS name:Impl modality:FINAL visibility:public superTypes:[.Foo.A; .Foo.B] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Impl + CONSTRUCTOR visibility:public <> (b:.Foo.B) returnType:.Impl [primary] + VALUE_PARAMETER name:b index:0 type:.Foo.B + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Impl modality:FINAL visibility:public superTypes:[.Foo.A; .Foo.B]' + SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=kotlin.Unit origin=EQ + receiver: GET_VAR ': .Impl declared in .Impl' type=.Impl origin=null + value: GET_VAR 'b: .Foo.B declared in .Impl.' type=.Foo.B origin=null + FUN DELEGATED_MEMBER name:add visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean + overridden: + public abstract fun add (element: E of kotlin.collections.MutableSet): kotlin.Boolean declared in kotlin.collections.MutableSet + public abstract fun add (element: kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:element index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun add (element: kotlin.String?): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun add (element: kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.add' type=.Impl origin=null + element: GET_VAR 'element: kotlin.String? declared in .Impl.add' type=kotlin.String? origin=null + FUN DELEGATED_MEMBER name:addAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean + overridden: + public abstract fun addAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.MutableSet + public abstract fun addAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun addAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun addAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.addAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection declared in .Impl.addAll' type=kotlin.collections.Collection origin=null + FUN DELEGATED_MEMBER name:clear visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Unit + overridden: + public abstract fun clear (): kotlin.Unit declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + CALL 'public abstract fun clear (): kotlin.Unit declared in kotlin.collections.MutableSet' type=kotlin.Unit origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.clear' type=.Impl origin=null + FUN DELEGATED_MEMBER name:iterator visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.collections.MutableIterator [operator] + overridden: + public abstract fun iterator (): kotlin.collections.MutableIterator [operator] declared in kotlin.collections.MutableSet + public abstract fun iterator (): kotlin.collections.MutableIterator [fake_override,operator] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun iterator (): kotlin.collections.MutableIterator [operator] declared in .Impl' + CALL 'public abstract fun iterator (): kotlin.collections.MutableIterator [fake_override,operator] declared in .Foo.B' type=kotlin.collections.MutableIterator origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.iterator' type=.Impl origin=null + FUN DELEGATED_MEMBER name:remove visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean + overridden: + public abstract fun remove (element: E of kotlin.collections.MutableSet): kotlin.Boolean declared in kotlin.collections.MutableSet + public abstract fun remove (element: kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:element index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun remove (element: kotlin.String?): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun remove (element: kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.remove' type=.Impl origin=null + element: GET_VAR 'element: kotlin.String? declared in .Impl.remove' type=kotlin.String? origin=null + FUN DELEGATED_MEMBER name:removeAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean + overridden: + public abstract fun removeAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.MutableSet + public abstract fun removeAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun removeAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun removeAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.removeAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection declared in .Impl.removeAll' type=kotlin.collections.Collection origin=null + FUN DELEGATED_MEMBER name:retainAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean + overridden: + public abstract fun retainAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.MutableSet + public abstract fun retainAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun retainAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun retainAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.retainAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection declared in .Impl.retainAll' type=kotlin.collections.Collection origin=null + FUN DELEGATED_MEMBER name:contains visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean [operator] + overridden: + public abstract fun contains (element: E of kotlin.collections.Set): kotlin.Boolean [operator] declared in kotlin.collections.Set + public abstract fun contains (element: kotlin.String?): kotlin.Boolean [fake_override,operator] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:element index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun contains (element: kotlin.String?): kotlin.Boolean [operator] declared in .Impl' + CALL 'public abstract fun contains (element: kotlin.String?): kotlin.Boolean [fake_override,operator] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.contains' type=.Impl origin=null + element: GET_VAR 'element: kotlin.String? declared in .Impl.contains' type=kotlin.String? origin=null + FUN DELEGATED_MEMBER name:containsAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in kotlin.collections.MutableSet + public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.containsAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection declared in .Impl.containsAll' type=kotlin.collections.Collection origin=null + FUN DELEGATED_MEMBER name:isEmpty visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Boolean + overridden: + public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.Set + public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun isEmpty (): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.isEmpty' type=.Impl origin=null + FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Impl, other:kotlin.Any?) returnType:kotlin.Boolean [operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Impl' + CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.MutableSet' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.equals' type=.Impl origin=null + other: GET_VAR 'other: kotlin.Any? declared in .Impl.equals' type=kotlin.Any? origin=null + FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Int + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Impl' + CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.hashCode' type=.Impl origin=null + FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.String + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Impl' + CALL 'public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.String origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.toString' type=.Impl origin=null + PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val] + FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Int + correspondingProperty: PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val] + overridden: + public abstract fun (): kotlin.Int declared in kotlin.collections.Set + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): kotlin.Int declared in .Impl' + CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.Set' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.' type=.Impl origin=null + FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final] + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + CONST String type=kotlin.String value="OK" diff --git a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.kt b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.kt new file mode 100644 index 00000000000..a7fb7c1c24f --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.kt @@ -0,0 +1,18 @@ +// FILE: Foo.java + +import java.util.Set; + +public class Foo { + public interface A extends Set {} + + public interface B extends Set {} +} + +// FILE: DelegationAndInheritanceFromJava.kt + +import Foo.* +import java.util.HashSet + +class Impl(b: B): A, B by b + +fun box() = "OK" diff --git a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.txt b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.txt new file mode 100644 index 00000000000..fd4b1eee2d3 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.txt @@ -0,0 +1,156 @@ +FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt + CLASS CLASS name:Impl modality:FINAL visibility:public superTypes:[.Foo.A; .Foo.B] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Impl + CONSTRUCTOR visibility:public <> (b:.Foo.B) returnType:.Impl [primary] + VALUE_PARAMETER name:b index:0 type:.Foo.B + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Impl modality:FINAL visibility:public superTypes:[.Foo.A; .Foo.B]' + FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final] + EXPRESSION_BODY + GET_VAR 'b: .Foo.B declared in .Impl.' type=.Foo.B origin=null + FUN DELEGATED_MEMBER name:add visibility:public modality:OPEN <> ($this:.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean + overridden: + public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.add' type=.Impl origin=null + element: GET_VAR 'element: @[FlexibleNullability] kotlin.String? declared in .Impl.add' type=@[FlexibleNullability] kotlin.String? origin=null + FUN DELEGATED_MEMBER name:addAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean + overridden: + public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.addAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> declared in .Impl.addAll' type=kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> origin=null + FUN DELEGATED_MEMBER name:clear visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Unit + overridden: + public abstract fun clear (): kotlin.Unit [fake_override] declared in .Foo.A + public abstract fun clear (): kotlin.Unit [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + CALL 'public abstract fun clear (): kotlin.Unit [fake_override] declared in .Foo.B' type=kotlin.Unit origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.clear' type=.Impl origin=null + FUN DELEGATED_MEMBER name:contains visibility:public modality:OPEN <> ($this:.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean [operator] + overridden: + public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in .Foo.A + public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [operator] declared in .Impl' + CALL 'public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.contains' type=.Impl origin=null + element: GET_VAR 'element: @[FlexibleNullability] kotlin.String? declared in .Impl.contains' type=@[FlexibleNullability] kotlin.String? origin=null + FUN DELEGATED_MEMBER name:containsAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean + overridden: + public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.containsAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> declared in .Impl.containsAll' type=kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> origin=null + FUN DELEGATED_MEMBER name:isEmpty visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Boolean + overridden: + public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun isEmpty (): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.isEmpty' type=.Impl origin=null + FUN DELEGATED_MEMBER name:iterator visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [operator] + overridden: + public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in .Foo.A + public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [operator] declared in .Impl' + CALL 'public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in .Foo.B' type=kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.iterator' type=.Impl origin=null + FUN DELEGATED_MEMBER name:remove visibility:public modality:OPEN <> ($this:.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean + overridden: + public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.remove' type=.Impl origin=null + element: GET_VAR 'element: @[FlexibleNullability] kotlin.String? declared in .Impl.remove' type=@[FlexibleNullability] kotlin.String? origin=null + FUN DELEGATED_MEMBER name:removeAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean + overridden: + public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.removeAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> declared in .Impl.removeAll' type=kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> origin=null + FUN DELEGATED_MEMBER name:retainAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean + overridden: + public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.A + public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean declared in .Impl' + CALL 'public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in .Foo.B' type=kotlin.Boolean origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.retainAll' type=.Impl origin=null + elements: GET_VAR 'elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> declared in .Impl.retainAll' type=kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> origin=null + PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val] + FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Int + correspondingProperty: PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val] + overridden: + public abstract fun (): kotlin.Int [fake_override] declared in .Foo.A + public abstract fun (): kotlin.Int [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:.Impl + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): kotlin.Int declared in .Impl' + CALL 'public abstract fun (): kotlin.Int [fake_override] declared in .Foo.B' type=kotlin.Int origin=null + $this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:.Foo.B visibility:private [final]' type=.Foo.B origin=null + receiver: GET_VAR ': .Impl declared in .Impl.' type=.Impl origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Foo.A + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Foo.B + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Foo.A + public open fun hashCode (): kotlin.Int [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Foo.A + public open fun toString (): kotlin.String [fake_override] declared in .Foo.B + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + CONST String type=kotlin.String value="OK" diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index aa61fda0983..6888e08b8a0 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1761,6 +1761,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/firProblems/DeepCopyIrTree.kt"); } + @TestMetadata("DelegationAndInheritanceFromJava.kt") + public void testDelegationAndInheritanceFromJava() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.kt"); + } + @TestMetadata("deprecated.kt") public void testDeprecated() throws Exception { runTest("compiler/testData/ir/irText/firProblems/deprecated.kt"); From 4a3a2ef72a35c8fe38aa3e9fb05a07722dce1487 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 28 Oct 2020 16:02:51 +0300 Subject: [PATCH 059/554] [FIR2IR] Test data fix after rebase (regular + delegated supertype) --- .../DelegationAndInheritanceFromJava.fir.txt | 56 +++++-------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt index 62dfe155ea2..d72caa18324 100644 --- a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt +++ b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt @@ -12,7 +12,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:add visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean overridden: public abstract fun add (element: E of kotlin.collections.MutableSet): kotlin.Boolean declared in kotlin.collections.MutableSet - public abstract fun add (element: kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:element index:0 type:kotlin.String? BLOCK_BODY @@ -24,7 +23,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:addAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean overridden: public abstract fun addAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.MutableSet - public abstract fun addAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection BLOCK_BODY @@ -44,7 +42,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:iterator visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.collections.MutableIterator [operator] overridden: public abstract fun iterator (): kotlin.collections.MutableIterator [operator] declared in kotlin.collections.MutableSet - public abstract fun iterator (): kotlin.collections.MutableIterator [fake_override,operator] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun iterator (): kotlin.collections.MutableIterator [operator] declared in .Impl' @@ -54,7 +51,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:remove visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean overridden: public abstract fun remove (element: E of kotlin.collections.MutableSet): kotlin.Boolean declared in kotlin.collections.MutableSet - public abstract fun remove (element: kotlin.String?): kotlin.Boolean [fake_override] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:element index:0 type:kotlin.String? BLOCK_BODY @@ -66,7 +62,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:removeAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean overridden: public abstract fun removeAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.MutableSet - public abstract fun removeAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection BLOCK_BODY @@ -78,7 +73,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:retainAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean overridden: public abstract fun retainAll (elements: kotlin.collections.Collection): kotlin.Boolean declared in kotlin.collections.MutableSet - public abstract fun retainAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection BLOCK_BODY @@ -90,7 +84,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:contains visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean [operator] overridden: public abstract fun contains (element: E of kotlin.collections.Set): kotlin.Boolean [operator] declared in kotlin.collections.Set - public abstract fun contains (element: kotlin.String?): kotlin.Boolean [fake_override,operator] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:element index:0 type:kotlin.String? BLOCK_BODY @@ -102,7 +95,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:containsAll visibility:public modality:OPEN <> ($this:.Impl, elements:kotlin.collections.Collection) returnType:kotlin.Boolean overridden: public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in kotlin.collections.MutableSet - public abstract fun containsAll (elements: kotlin.collections.Collection): kotlin.Boolean [fake_override] declared in .Foo.B $this: VALUE_PARAMETER name: type:.Impl VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection BLOCK_BODY @@ -114,45 +106,12 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt FUN DELEGATED_MEMBER name:isEmpty visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Boolean overridden: public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.Set - public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in kotlin.collections.MutableSet $this: VALUE_PARAMETER name: type:.Impl BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun isEmpty (): kotlin.Boolean declared in .Impl' CALL 'public abstract fun isEmpty (): kotlin.Boolean [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.Boolean origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null receiver: GET_VAR ': .Impl declared in .Impl.isEmpty' type=.Impl origin=null - FUN DELEGATED_MEMBER name:equals visibility:public modality:OPEN <> ($this:.Impl, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any - public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.MutableSet - $this: VALUE_PARAMETER name: type:.Impl - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in .Impl' - CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.MutableSet' type=kotlin.Boolean origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null - receiver: GET_VAR ': .Impl declared in .Impl.equals' type=.Impl origin=null - other: GET_VAR 'other: kotlin.Any? declared in .Impl.equals' type=kotlin.Any? origin=null - FUN DELEGATED_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet - $this: VALUE_PARAMETER name: type:.Impl - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in .Impl' - CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null - receiver: GET_VAR ': .Impl declared in .Impl.hashCode' type=.Impl origin=null - FUN DELEGATED_MEMBER name:toString visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.MutableSet - $this: VALUE_PARAMETER name: type:.Impl - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in .Impl' - CALL 'public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.String origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null - receiver: GET_VAR ': .Impl declared in .Impl.toString' type=.Impl origin=null PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Impl) returnType:kotlin.Int correspondingProperty: PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val] @@ -161,10 +120,23 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt $this: VALUE_PARAMETER name: type:.Impl BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun (): kotlin.Int declared in .Impl' - CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.Set' type=kotlin.Int origin=null + CALL 'public abstract fun (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet' type=kotlin.Int origin=null $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null receiver: GET_VAR ': .Impl declared in .Impl.' type=.Impl origin=null FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final] + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in kotlin.collections.MutableSet + $this: VALUE_PARAMETER name: type:kotlin.Any FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' From ad5b6da273f8d14ed196b9ad0fd54d042450038d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 26 Oct 2020 19:08:00 +0100 Subject: [PATCH 060/554] JVM IR: substitute generic type for inline class replacement function calls The main change here is in `JvmInlineClassLowering.visitFunctionAccess`, where we now store the substituted return type of the function as the type of the call expression. Without it, the call could have a meaningless type, e.g. some `T` which is inaccessible at that place, and that could backfire in subsequent lowerings in codegen. For example, in the `stringPlus.kt` test, it would prevent the code in `FlattenStringConcatenationLowering.isStringPlusCall` from recognizing and replacing the `String.plus` call, leading to a codegen exception. Other changes are mostly cosmetics to make the code similar to `visitFunctionReference`, and preventive optimizations for the case when the substitution map is empty. --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++++ .../jetbrains/kotlin/ir/util/IrTypeUtils.kt | 2 +- .../jvm/lower/JvmInlineClassLowering.kt | 21 ++++++++++++------- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 13 ++++++++---- .../codegen/box/inlineClasses/stringPlus.kt | 9 ++++++++ .../funInterface/string.kt | 4 +--- .../unboxGenericParameter/lambda/string.kt | 4 +--- .../objectLiteral/string.kt | 4 +--- .../funInterface/string.kt | 6 +----- .../unboxGenericParameter/lambda/string.kt | 6 +----- .../objectLiteral/string.kt | 6 +----- .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../LightAnalysisModeTestGenerated.java | 5 +++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++++ .../IrJsCodegenBoxTestGenerated.java | 5 +++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++++ 17 files changed, 73 insertions(+), 37 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/stringPlus.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 4038fbeb5c4..aa7402b0887 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 @@ -14117,6 +14117,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt"); diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt index 7a2a75d9ebc..94958d2ccbf 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt @@ -80,7 +80,7 @@ fun IrType.substitute(params: List, arguments: List): I substitute(params.map { it.symbol }.zip(arguments).toMap()) fun IrType.substitute(substitutionMap: Map): IrType { - if (this !is IrSimpleType) return this + if (this !is IrSimpleType || substitutionMap.isEmpty()) return this val newAnnotations = annotations.map { it.deepCopyWithSymbols() } 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 a06311f4e95..3ff1811d2f7 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 @@ -277,15 +277,16 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F if (expression.origin == InlineClassAbi.UNMANGLED_FUNCTION_REFERENCE) return super.visitFunctionReference(expression) - val function = context.inlineClassReplacements.getReplacementFunction(expression.symbol.owner) + val function = expression.symbol.owner + val replacement = context.inlineClassReplacements.getReplacementFunction(function) ?: return super.visitFunctionReference(expression) return IrFunctionReferenceImpl( expression.startOffset, expression.endOffset, expression.type, - function.symbol, function.typeParameters.size, - function.valueParameters.size, expression.reflectionTarget, expression.origin + replacement.symbol, replacement.typeParameters.size, + replacement.valueParameters.size, expression.reflectionTarget, expression.origin ).apply { - buildReplacement(expression.symbol.owner, expression, function) + buildReplacement(function, expression, replacement) }.copyAttributes(expression) } @@ -293,10 +294,14 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F val function = expression.symbol.owner val replacement = context.inlineClassReplacements.getReplacementFunction(function) ?: return super.visitFunctionAccess(expression) - return context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) - .irCall(replacement, expression.origin, expression.safeAs()?.superQualifierSymbol).apply { - buildReplacement(function, expression, replacement) - } + + return IrCallImpl( + expression.startOffset, expression.endOffset, function.returnType.substitute(expression.typeSubstitutionMap), + replacement.symbol, replacement.typeParameters.size, replacement.valueParameters.size, + expression.origin, (expression as? IrCall)?.superQualifierSymbol + ).apply { + buildReplacement(function, expression, replacement) + } } private fun coerceInlineClasses(argument: IrExpression, from: IrType, to: IrType) = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index cb63dd7e753..2a292d4b02d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -16,7 +16,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isAny +import org.jetbrains.kotlin.ir.types.isSubtypeOf import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.utils.DFS @@ -512,10 +515,12 @@ val IrFunction.allTypeParameters: List else typeParameters -fun IrMemberAccessExpression<*>.getTypeSubstitutionMap(irFunction: IrFunction): Map = - irFunction.allTypeParameters.withIndex().associate { +fun IrMemberAccessExpression<*>.getTypeSubstitutionMap(irFunction: IrFunction): Map { + val typeParameters = irFunction.allTypeParameters + return if (typeParameters.isEmpty()) emptyMap() else typeParameters.withIndex().associate { it.value.symbol to getTypeArgument(it.index)!! } +} val IrFunctionReference.typeSubstitutionMap: Map get() = getTypeSubstitutionMap(symbol.owner) @@ -536,4 +541,4 @@ val IrFunction.originalFunction: IrFunction get() = (this as? IrAttributeContainer)?.attributeOwnerId as? IrFunction ?: this val IrProperty.originalProperty: IrProperty - get() = attributeOwnerId as? IrProperty ?: this \ No newline at end of file + get() = attributeOwnerId as? IrProperty ?: this diff --git a/compiler/testData/codegen/box/inlineClasses/stringPlus.kt b/compiler/testData/codegen/box/inlineClasses/stringPlus.kt new file mode 100644 index 00000000000..37fd5117c83 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/stringPlus.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +InlineClasses + +fun foo(a: IC): T = a.value as T + +inline class IC(val value: String) + +fun box(): String { + return foo(IC("O")) + "K" +} diff --git a/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/string.kt b/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/string.kt index fda16c3a330..9d84cf1a01c 100644 --- a/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/string.kt +++ b/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/string.kt @@ -1,6 +1,4 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR fun underlying(a: IC): T = bar(a) { it.value as T @@ -48,4 +46,4 @@ fun box(): String { if (res != "OK") return "FAIL 3: $res" return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/string.kt b/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/string.kt index c8ec62c787c..0922f4ef605 100644 --- a/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/string.kt +++ b/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/string.kt @@ -1,6 +1,4 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR fun underlying(a: IC): T = bar(a) { it.value as T @@ -44,4 +42,4 @@ fun box(): String { if (res != "OK") return "FAIL 3: $res" return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/string.kt b/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/string.kt index a44ea4108e5..2a911bc1760 100644 --- a/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/string.kt +++ b/compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/string.kt @@ -1,6 +1,4 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR fun underlying(a: IC): T = bar(a, object : IFace { override fun call(ic: IC): T = ic.value as T @@ -48,4 +46,4 @@ fun box(): String { if (res != "OK") return "FAIL 3: $res" return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/funInterface/string.kt b/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/funInterface/string.kt index cbe2a024d65..7cb7cea35e1 100644 --- a/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/funInterface/string.kt +++ b/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/funInterface/string.kt @@ -1,8 +1,4 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD - // FILE: inline.kt inline class IC(val value: String) { @@ -47,4 +43,4 @@ fun box(): String { if (res != "OK") return "FAIL 3: $res" return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/lambda/string.kt b/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/lambda/string.kt index 3c5cf7bed69..0072106d1cc 100644 --- a/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/lambda/string.kt +++ b/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/lambda/string.kt @@ -1,8 +1,4 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD - // FILE: inline.kt inline class IC(val value: String) { @@ -43,4 +39,4 @@ fun box(): String { if (res != "OK") return "FAIL 3: $res" return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/objectLiteral/string.kt b/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/objectLiteral/string.kt index f8293ece19c..bdf6307c30c 100644 --- a/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/objectLiteral/string.kt +++ b/compiler/testData/codegen/boxInline/inlineClasses/unboxGenericParameter/objectLiteral/string.kt @@ -1,8 +1,4 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD - // FILE: inline.kt inline class IC(val value: String) { @@ -47,4 +43,4 @@ fun box(): String { if (res != "OK") return "FAIL 3: $res" return "OK" -} \ No newline at end of file +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 8c27483ec16..00157a261f5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15517,6 +15517,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 78065a1b245..1f2fc652b38 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15522,6 +15522,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 23a26d18b43..cd98efd9952 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -14117,6 +14117,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.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 aba203116e1..08459ac10cf 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 @@ -12122,6 +12122,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.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 a9114f89e89..ffe5f59dd02 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 @@ -12122,6 +12122,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.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 c947e3968e9..94a0680eaae 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 @@ -12187,6 +12187,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/smartCastOnThisOfInlineClassType.kt"); } + @TestMetadata("stringPlus.kt") + public void testStringPlus() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/stringPlus.kt"); + } + @TestMetadata("toStringCallingPrivateFun.kt") public void testToStringCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/toStringCallingPrivateFun.kt"); From d4d93b709138b682efb7a5b1c5cd13965c4ec881 Mon Sep 17 00:00:00 2001 From: Anton Yalyshev Date: Wed, 28 Oct 2020 21:56:24 +0300 Subject: [PATCH 061/554] Add change-notes for 1.4.20 --- idea/resources-descriptors/META-INF/plugin.xml | 13 +++++++++++++ idea/resources-descriptors/META-INF/plugin.xml.193 | 13 +++++++++++++ idea/resources-descriptors/META-INF/plugin.xml.202 | 13 +++++++++++++ .../resources-descriptors/META-INF/plugin.xml.as40 | 13 +++++++++++++ .../resources-descriptors/META-INF/plugin.xml.as41 | 13 +++++++++++++ .../resources-descriptors/META-INF/plugin.xml.as42 | 14 +++++++++++++- 6 files changed, 78 insertions(+), 1 deletion(-) diff --git a/idea/resources-descriptors/META-INF/plugin.xml b/idea/resources-descriptors/META-INF/plugin.xml index bf474888223..8f5c88df3b5 100644 --- a/idea/resources-descriptors/META-INF/plugin.xml +++ b/idea/resources-descriptors/META-INF/plugin.xml @@ -16,6 +16,19 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. 1.4.20 +
    +
  • Kotlin/JS: New project templates, improved Gradle plugin, experimental compilation with errors mode in the IR compiler.
  • +
  • Kotlin/Native: New escape analysis mechanism, wrapping of Objective-C exceptions, various functional and performance improvements.
  • +
  • IDE: Experimental support for Code Vision, the Redirect input from option in Kotlin run configurations, and more.
  • +
  • JEP 280 (invokedynamic) string concatenation is available on the JVM.
  • +
  • Changes to the layout of multiplatform projects.
  • +
  • Improved CocoaPods support.
  • +
  • Standard library improvements: Extensions for java.nio.file.Path and performance optimizations.
  • +
  • Deprecation of the kotlin-android-extensions compiler plugin. Parcelable implementation generator has moved to the new kotlin-parcelize plugin.
  • +
+ For more details, see What’s New in Kotlin 1.4.20 and this blog post. +

1.4.0

Released: August 17, 2020