diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/LazyBodyRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/LazyBodyRawFirBuilder.kt index 66bda39033b..42cb4800330 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/LazyBodyRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/LazyBodyRawFirBuilder.kt @@ -31,7 +31,6 @@ class RawFirFragmentForLazyBodiesBuilder private constructor( designation: List, declaration: KtDeclaration, ): FirDeclaration { - require(declaration is KtNamedFunction || declaration is KtProperty) { "Not implemented for ${declaration::class.qualifiedName}" } val builder = RawFirFragmentForLazyBodiesBuilder(session, baseScopeProvider, declaration) builder.context.packageFqName = declaration.containingKtFile.packageFqName return builder.moveNext(designation.iterator()) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index a921c741d9e..69873f3bcce 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -365,6 +365,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor } doTransformTypeParameters(typeAlias) typeAlias.transformAnnotations(transformer, data) + transformer.onBeforeDeclarationContentResolve(typeAlias) typeAlias.transformExpandedTypeRef(transformer, data) return typeAlias } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirRegularClassBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirRegularClassBuilder.kt index 5895913f15a..7ce1818fdac 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirRegularClassBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirRegularClassBuilder.kt @@ -81,3 +81,27 @@ inline fun buildRegularClass(init: FirRegularClassBuilder.() -> Unit): FirRegula } return FirRegularClassBuilder().apply(init).build() } + +@OptIn(ExperimentalContracts::class) +inline fun buildRegularClassCopy(original: FirRegularClass, init: FirRegularClassBuilder.() -> Unit): FirRegularClass { + contract { + callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + val copyBuilder = FirRegularClassBuilder() + copyBuilder.source = original.source + copyBuilder.session = original.session + copyBuilder.resolvePhase = original.resolvePhase + copyBuilder.origin = original.origin + copyBuilder.attributes = original.attributes.copy() + copyBuilder.annotations.addAll(original.annotations) + copyBuilder.typeParameters.addAll(original.typeParameters) + copyBuilder.status = original.status + copyBuilder.classKind = original.classKind + copyBuilder.declarations.addAll(original.declarations) + copyBuilder.scopeProvider = original.scopeProvider + copyBuilder.name = original.name + copyBuilder.symbol = original.symbol + copyBuilder.companionObject = original.companionObject + copyBuilder.superTypeRefs.addAll(original.superTypeRefs) + return copyBuilder.apply(init).build() +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirTypeAliasBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirTypeAliasBuilder.kt index 4458c690cab..7a129a48833 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirTypeAliasBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirTypeAliasBuilder.kt @@ -68,3 +68,23 @@ inline fun buildTypeAlias(init: FirTypeAliasBuilder.() -> Unit): FirTypeAlias { } return FirTypeAliasBuilder().apply(init).build() } + +@OptIn(ExperimentalContracts::class) +inline fun buildTypeAliasCopy(original: FirTypeAlias, init: FirTypeAliasBuilder.() -> Unit): FirTypeAlias { + contract { + callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + val copyBuilder = FirTypeAliasBuilder() + copyBuilder.source = original.source + copyBuilder.session = original.session + copyBuilder.resolvePhase = original.resolvePhase + copyBuilder.origin = original.origin + copyBuilder.attributes = original.attributes.copy() + copyBuilder.status = original.status + copyBuilder.typeParameters.addAll(original.typeParameters) + copyBuilder.name = original.name + copyBuilder.symbol = original.symbol + copyBuilder.expandedTypeRef = original.expandedTypeRef + copyBuilder.annotations.addAll(original.annotations) + return copyBuilder.apply(init).build() +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt index 11564545ba9..efcbda74821 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt @@ -28,7 +28,7 @@ inline fun FirTypeRef.coneTypeSafe(): T? { return (this as? FirResolvedTypeRef)?.type as? T } -inline val FirTypeRef.coneType: ConeKotlinType +val FirTypeRef.coneType: ConeKotlinType get() = coneTypeSafe() ?: error("Expected FirResolvedTypeRef with ConeKotlinType but was ${this::class.simpleName} ${render()}") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt index ce1e85360c7..803a2afcaaf 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt @@ -37,6 +37,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree parents += typeParameterRefsOwnerBuilder defaultNull("companionObject") openBuilder() + withCopy() } val qualifiedAccessBuilder by builder { @@ -95,6 +96,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree builder(typeAlias) { parents += typeParametersOwnerBuilder + withCopy() } builder(annotationCall) { diff --git a/idea/idea-completion/testData/basic/common/ExtendClassName.kt b/idea/idea-completion/testData/basic/common/ExtendClassName.kt index c4ae4f6575d..c4469ad42b1 100644 --- a/idea/idea-completion/testData/basic/common/ExtendClassName.kt +++ b/idea/idea-completion/testData/basic/common/ExtendClassName.kt @@ -11,3 +11,4 @@ class A() : My { } // EXIST: MySecondClass, MyFirstClass +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/InObjectInDelegationSpecifier.kt b/idea/idea-completion/testData/basic/common/InObjectInDelegationSpecifier.kt index 99b6abf2a2c..17f86a68cc8 100644 --- a/idea/idea-completion/testData/basic/common/InObjectInDelegationSpecifier.kt +++ b/idea/idea-completion/testData/basic/common/InObjectInDelegationSpecifier.kt @@ -8,4 +8,5 @@ class ChromePageManager(): PageManager(object : Runnable { }) { } -// EXIST: Tab \ No newline at end of file +// EXIST: Tab +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/InTypeAnnotation.kt b/idea/idea-completion/testData/basic/common/InTypeAnnotation.kt index b4f6904c5f0..eb39faa5831 100644 --- a/idea/idea-completion/testData/basic/common/InTypeAnnotation.kt +++ b/idea/idea-completion/testData/basic/common/InTypeAnnotation.kt @@ -11,4 +11,5 @@ public class Test : String { // EXIST: StringMy // EXIST: String -// ABSENT: StringMethod \ No newline at end of file +// ABSENT: StringMethod +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt b/idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt new file mode 100644 index 00000000000..ef926e79ef3 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt @@ -0,0 +1,7 @@ +class X { + init { + val y = 1 + + } +} +// EXIST: y \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/inInitBlock/property.kt b/idea/idea-completion/testData/basic/common/inInitBlock/property.kt new file mode 100644 index 00000000000..8dcf7e26645 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inInitBlock/property.kt @@ -0,0 +1,9 @@ +class X { + val x: Int = 10 + + init { + + } +} +// EXIST: x +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt b/idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt new file mode 100644 index 00000000000..fdb8ef9de25 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt @@ -0,0 +1,5 @@ +open class Base +class A : + +// EXIST: Base +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt b/idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt new file mode 100644 index 00000000000..872c49fb8c9 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt @@ -0,0 +1,5 @@ +open class Base +class A : B + +// EXIST: Base +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt b/idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt new file mode 100644 index 00000000000..5a83eb660b6 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt @@ -0,0 +1,5 @@ +open class Base +class A : Base<> + +// EXIST: U +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/inTypeAlias/member.kt b/idea/idea-completion/testData/basic/common/inTypeAlias/member.kt new file mode 100644 index 00000000000..4a70f36857f --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inTypeAlias/member.kt @@ -0,0 +1,8 @@ +class X { + typealias Y = +} + +class Z + +// EXIST: Z +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt b/idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt new file mode 100644 index 00000000000..001a47ff668 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt @@ -0,0 +1,5 @@ +typealias Y = +class Z + +// EXIST: Z +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt b/idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt new file mode 100644 index 00000000000..b428c436bbd --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt @@ -0,0 +1,6 @@ +val y = 10 + +class X(val x: Int = ) + +// EXIST: y +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt b/idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt new file mode 100644 index 00000000000..6af65bcf818 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt @@ -0,0 +1,4 @@ +class X(val y: Int, val x: Int = ) + +// EXIST: y +// FIR_COMPARISON diff --git a/idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt b/idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt new file mode 100644 index 00000000000..2bab168e872 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt @@ -0,0 +1,6 @@ +class Y + +class X(val x: ) + +// EXIST: Y +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt b/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt index 5eaa3319e6c..0eaf28cd0be 100644 --- a/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt +++ b/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt @@ -4,4 +4,5 @@ annotation class SomeAnnotation class Complete(@set:Some var field: Int) -// ELEMENT: SomeAnnotation \ No newline at end of file +// ELEMENT: SomeAnnotation +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt.after b/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt.after index 04f7c6393e8..2e0072f8a51 100644 --- a/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt.after +++ b/idea/idea-completion/testData/handlers/basic/annotation/KT12077.kt.after @@ -4,4 +4,5 @@ annotation class SomeAnnotation class Complete(@set:SomeAnnotation var field: Int) -// ELEMENT: SomeAnnotation \ No newline at end of file +// ELEMENT: SomeAnnotation +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/KT12077-1.kt b/idea/idea-completion/testData/handlers/multifile/KT12077-1.kt index e1dd78a140b..458cadbbdcf 100644 --- a/idea/idea-completion/testData/handlers/multifile/KT12077-1.kt +++ b/idea/idea-completion/testData/handlers/multifile/KT12077-1.kt @@ -1,3 +1,4 @@ package some class Complete(@set:SomeAnn var field: Int) +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/KT12077.kt.after b/idea/idea-completion/testData/handlers/multifile/KT12077.kt.after index 9bff4ea8689..04a0e4f1e0f 100644 --- a/idea/idea-completion/testData/handlers/multifile/KT12077.kt.after +++ b/idea/idea-completion/testData/handlers/multifile/KT12077.kt.after @@ -3,3 +3,4 @@ package some import other.SomeAnnotation class Complete(@set:SomeAnnotation var field: Int) +// FIR_COMPARISON \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 3b99db7bbd7..1469defe3b5 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -1677,6 +1677,29 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes } } + @TestMetadata("idea/idea-completion/testData/basic/common/inInitBlock") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InInitBlock extends AbstractJSBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInInitBlock() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inInitBlock"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("localVariable.kt") + public void testLocalVariable() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt"); + } + + @TestMetadata("property.kt") + public void testProperty() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inInitBlock/property.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/inStringLiterals") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -1720,6 +1743,57 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes } } + @TestMetadata("idea/idea-completion/testData/basic/common/inSuperTypes") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InSuperTypes extends AbstractJSBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInSuperTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("baseClass.kt") + public void testBaseClass() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt"); + } + + @TestMetadata("baseClassWithPrefix.kt") + public void testBaseClassWithPrefix() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt"); + } + + @TestMetadata("typeParameter.kt") + public void testTypeParameter() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt"); + } + } + + @TestMetadata("idea/idea-completion/testData/basic/common/inTypeAlias") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InTypeAlias extends AbstractJSBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInTypeAlias() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inTypeAlias"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("member.kt") + public void testMember() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inTypeAlias/member.kt"); + } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -2231,6 +2305,34 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes } } + @TestMetadata("idea/idea-completion/testData/basic/common/primaryConstructor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PrimaryConstructor extends AbstractJSBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPrimaryConstructor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/primaryConstructor"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("parameterDefaultValue.kt") + public void testParameterDefaultValue() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt"); + } + + @TestMetadata("previousParameter.kt") + public void testPreviousParameter() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt"); + } + + @TestMetadata("propertyType.kt") + public void testPropertyType() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/primitiveCompletion") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index bf05d90ea1b..b3d3a766fe4 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -1677,6 +1677,29 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT } } + @TestMetadata("idea/idea-completion/testData/basic/common/inInitBlock") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InInitBlock extends AbstractJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInInitBlock() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inInitBlock"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("localVariable.kt") + public void testLocalVariable() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt"); + } + + @TestMetadata("property.kt") + public void testProperty() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inInitBlock/property.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/inStringLiterals") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -1720,6 +1743,57 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT } } + @TestMetadata("idea/idea-completion/testData/basic/common/inSuperTypes") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InSuperTypes extends AbstractJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInSuperTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("baseClass.kt") + public void testBaseClass() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt"); + } + + @TestMetadata("baseClassWithPrefix.kt") + public void testBaseClassWithPrefix() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt"); + } + + @TestMetadata("typeParameter.kt") + public void testTypeParameter() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt"); + } + } + + @TestMetadata("idea/idea-completion/testData/basic/common/inTypeAlias") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InTypeAlias extends AbstractJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInTypeAlias() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inTypeAlias"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("member.kt") + public void testMember() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inTypeAlias/member.kt"); + } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -2231,6 +2305,34 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT } } + @TestMetadata("idea/idea-completion/testData/basic/common/primaryConstructor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PrimaryConstructor extends AbstractJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPrimaryConstructor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/primaryConstructor"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("parameterDefaultValue.kt") + public void testParameterDefaultValue() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt"); + } + + @TestMetadata("previousParameter.kt") + public void testPreviousParameter() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt"); + } + + @TestMetadata("propertyType.kt") + public void testPropertyType() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/primitiveCompletion") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/completion/HighLevelJvmBasicCompletionTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/completion/HighLevelJvmBasicCompletionTestGenerated.java index 23cf21ee62b..b5a804313ef 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/completion/HighLevelJvmBasicCompletionTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/completion/HighLevelJvmBasicCompletionTestGenerated.java @@ -1677,6 +1677,29 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ } } + @TestMetadata("idea/idea-completion/testData/basic/common/inInitBlock") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InInitBlock extends AbstractHighLevelJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInInitBlock() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inInitBlock"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("localVariable.kt") + public void testLocalVariable() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt"); + } + + @TestMetadata("property.kt") + public void testProperty() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inInitBlock/property.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/inStringLiterals") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -1720,6 +1743,57 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ } } + @TestMetadata("idea/idea-completion/testData/basic/common/inSuperTypes") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InSuperTypes extends AbstractHighLevelJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInSuperTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("baseClass.kt") + public void testBaseClass() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt"); + } + + @TestMetadata("baseClassWithPrefix.kt") + public void testBaseClassWithPrefix() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt"); + } + + @TestMetadata("typeParameter.kt") + public void testTypeParameter() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt"); + } + } + + @TestMetadata("idea/idea-completion/testData/basic/common/inTypeAlias") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InTypeAlias extends AbstractHighLevelJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInInTypeAlias() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inTypeAlias"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("member.kt") + public void testMember() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inTypeAlias/member.kt"); + } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + runTest("idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -2231,6 +2305,34 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ } } + @TestMetadata("idea/idea-completion/testData/basic/common/primaryConstructor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PrimaryConstructor extends AbstractHighLevelJvmBasicCompletionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPrimaryConstructor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/primaryConstructor"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("parameterDefaultValue.kt") + public void testParameterDefaultValue() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt"); + } + + @TestMetadata("previousParameter.kt") + public void testPreviousParameter() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt"); + } + + @TestMetadata("propertyType.kt") + public void testPropertyType() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt"); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/primitiveCompletion") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt index b63ebf0008b..9bc7e4664f3 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt @@ -8,14 +8,11 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.api import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.builder.RawFirFragmentForLazyBodiesBuilder import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessorCopy -import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy +import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.expressions.FirReturnExpression import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.* object DeclarationCopyBuilder { fun createDeclarationCopy( @@ -24,26 +21,36 @@ object DeclarationCopyBuilder { state: FirModuleResolveState, ): FirDeclaration { return when (fakeKtDeclaration) { - is KtNamedFunction -> buildFunctionCopy( + is KtNamedFunction -> createFunctionCopy( fakeKtDeclaration, originalFirDeclaration as FirSimpleFunction, state ) - is KtProperty -> buildPropertyCopy( + is KtProperty -> createPropertyCopy( fakeKtDeclaration, originalFirDeclaration as FirProperty, state ) + is KtClassOrObject -> createClassCopy( + fakeKtDeclaration, + originalFirDeclaration as FirRegularClass, + state + ) + is KtTypeAlias -> createTypeAliasCopy( + fakeKtDeclaration, + originalFirDeclaration as FirTypeAlias, + state + ) else -> error("Unsupported declaration ${fakeKtDeclaration::class.simpleName}") } } - private fun buildFunctionCopy( + private fun createFunctionCopy( element: KtNamedFunction, originalFunction: FirSimpleFunction, state: FirModuleResolveState, ): FirSimpleFunction { - val builtFunction = createCopy(element, originalFunction) as FirSimpleFunction + val builtFunction = createCopy(element, originalFunction) // right now we can't resolve builtFunction header properly, as it built right in air, // without file, which is now required for running stages other then body resolve, so we @@ -57,12 +64,45 @@ object DeclarationCopyBuilder { }.apply { reassignAllReturnTargets(builtFunction) } } - private fun buildPropertyCopy( + private fun createClassCopy( + fakeKtClassOrObject: KtClassOrObject, + originalFirClass: FirRegularClass, + state: FirModuleResolveState, + ): FirRegularClass { + val builtClass = createCopy(fakeKtClassOrObject, originalFirClass) + + return buildRegularClassCopy(originalFirClass) { + declarations.clear() + declarations.addAll(builtClass.declarations) + symbol = builtClass.symbol + resolvePhase = minOf(originalFirClass.resolvePhase, FirResolvePhase.DECLARATIONS) + source = builtClass.source + session = state.rootModuleSession + } + } + + private fun createTypeAliasCopy( + fakeKtTypeAlias: KtTypeAlias, + originalFirTypeAlias: FirTypeAlias, + state: FirModuleResolveState, + ): FirTypeAlias { + val builtTypeAlias = createCopy(fakeKtTypeAlias, originalFirTypeAlias) + + return buildTypeAliasCopy(originalFirTypeAlias) { + expandedTypeRef = builtTypeAlias.expandedTypeRef + symbol = builtTypeAlias.symbol + resolvePhase = minOf(originalFirTypeAlias.resolvePhase, FirResolvePhase.DECLARATIONS) + source = builtTypeAlias.source + session = state.rootModuleSession + } + } + + private fun createPropertyCopy( element: KtProperty, originalProperty: FirProperty, state: FirModuleResolveState ): FirProperty { - val builtProperty = createCopy(element, originalProperty) as FirProperty + val builtProperty = createCopy(element, originalProperty) val originalSetter = originalProperty.setter val builtSetter = builtProperty.setter @@ -80,7 +120,7 @@ object DeclarationCopyBuilder { builtSetter } - return org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy(originalProperty) { + return buildPropertyCopy(originalProperty) { symbol = builtProperty.symbol initializer = builtProperty.initializer @@ -93,16 +133,16 @@ object DeclarationCopyBuilder { } } - fun createCopy( + internal inline fun createCopy( fakeKtDeclaration: KtDeclaration, - originalFirDeclaration: FirDeclaration, - ): FirDeclaration { + originalFirDeclaration: T, + ): T { return RawFirFragmentForLazyBodiesBuilder.build( session = originalFirDeclaration.session, baseScopeProvider = originalFirDeclaration.session.firIdeProvider.kotlinScopeProvider, designation = originalFirDeclaration.collectDesignation().fullDesignation, declaration = fakeKtDeclaration - ) + ) as T } private fun FirFunction<*>.reassignAllReturnTargets(from: FirFunction<*>) { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirTowerDataContextCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirTowerDataContextCollector.kt index a46643a93d6..fba75d0674d 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirTowerDataContextCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirTowerDataContextCollector.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext +import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration import org.jetbrains.kotlin.psi.* @ThreadSafeMutableState @@ -36,11 +37,21 @@ class FirTowerDataContextCollector { } fun FirTowerDataContextCollector.getClosestAvailableParentContext(element: KtElement): FirTowerDataContext? { - var current: KtElement = element - while (true) { - getContext(current)?.let { return it } - current = current.parent as? KtElement ?: return null + var current: PsiElement? = element + while (current != null) { + if (current is KtElement) { + getContext(current)?.let { return it } + } + if (current is KtDeclaration) { + val originalDeclaration = current.originalDeclaration + originalDeclaration?.let { getContext(it) }?.let { return it } + } + if (current is KtFile) { + break + } + current = current.parent } + return null } private tailrec fun PsiElement.closestBlockLevelOrInitializerExpression(): KtExpression? = diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt index adce97caa3c..35c6a4b75ed 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt @@ -80,7 +80,7 @@ internal class ReanalyzableFunctionStructureElement( towerDataContextCollector: FirTowerDataContextCollector, ): ReanalyzableFunctionStructureElement { val originalFunction = firSymbol.fir as FirSimpleFunction - val newFunction = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalFunction) as FirSimpleFunction + val newFunction = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalFunction) return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalFunction, newFunction) { firLazyDeclarationResolver.lazyResolveDeclaration( @@ -122,7 +122,7 @@ internal class ReanalyzablePropertyStructureElement( towerDataContextCollector: FirTowerDataContextCollector, ): ReanalyzablePropertyStructureElement { val originalProperty = firSymbol.fir - val newProperty = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalProperty) as FirProperty + val newProperty = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalProperty) return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalProperty, newProperty) { firLazyDeclarationResolver.lazyResolveDeclaration( diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/EnclosingDeclarationContext.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/EnclosingDeclarationContext.kt index 11b9e0a4295..b1782ebf8f8 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/EnclosingDeclarationContext.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/EnclosingDeclarationContext.kt @@ -34,8 +34,8 @@ internal sealed class EnclosingDeclarationContext { ktDeclaration.canBeEnclosingDeclaration() } if (fakeKtDeclaration != null) { - val originalDeclaration = originalFile.findDeclarationOfTypeAt(fakeKtDeclaration.textOffset, fakeKtDeclaration::class) - ?: error("Cannot find original function matching to ${fakeKtDeclaration.getElementTextInContext()} in $originalFile") + val originalDeclaration = findMatchingElementInCopy(fakeKtDeclaration, originalFile) + ?: error("Cannot find original declaration matching to ${fakeKtDeclaration.getElementTextInContext()} in $originalFile") recordOriginalDeclaration(originalDeclaration, fakeKtDeclaration) return EnclosingDeclarationContextImpl(fakeKtDeclaration, originalDeclaration) } @@ -62,7 +62,6 @@ internal class EnclosingDeclarationContextImpl( ) : EnclosingDeclarationContext() - internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile: FirFile, firResolveState: FirModuleResolveState) { LowLevelFirApiFacadeForCompletion.recordCompletionContextForDeclaration( originalFirFile, @@ -73,7 +72,8 @@ internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile ) } -private fun KtFile.findDeclarationOfTypeAt(offset: Int, declarationType: KClass): T? { - val elementAtOffset = findElementAt(offset) ?: return null - return PsiTreeUtil.getParentOfType(elementAtOffset, declarationType.java, false)?.takeIf { it.textOffset == offset } +fun findMatchingElementInCopy(element: T, copy: KtFile): T? { + val elementOffset = element.textOffset + val elementAtOffset = copy.findElementAt(elementOffset) ?: return null + return PsiTreeUtil.getParentOfType(elementAtOffset, element::class.java, false)?.takeIf { it.textOffset == elementOffset } } \ No newline at end of file