From dcc22d3e5d9da25533471848e77becc4bcfcdc05 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Tue, 8 Sep 2020 15:06:16 +0300 Subject: [PATCH] FIR IDE: Fix completion in property setters Property consists of getter and setter (both optional). The setter have a single `value` parameter with type Because of it, we have to make a separate 'frankenstein setter' with original resolved header, but with the body of the fake one It seems that getters does not have such issues --- .../builder/FirPropertyAccessorBuilder.kt | 22 ++++++++++++ .../fir/tree/generator/BuilderConfigurator.kt | 1 + .../topLevelPropertyGetterBodyCompletion.kt | 10 ++++++ ...LevelPropertyGetterExpressionCompletion.kt | 8 +++++ .../topLevelPropertyGetterTypeCompletion.kt | 8 +++++ .../topLevelPropertyInitializerCompletion.kt | 7 ++++ .../topLevelPropertySetterBodyCompletion.kt | 11 ++++++ ...LevelPropertySetterExpressionCompletion.kt | 9 +++++ .../topLevelPropertyTypeCompletion.kt | 7 ++++ .../test/JSBasicCompletionTestGenerated.java | 35 +++++++++++++++++++ .../test/JvmBasicCompletionTestGenerated.java | 35 +++++++++++++++++++ ...hLevelJvmBasicCompletionTestGenerated.java | 35 +++++++++++++++++++ .../fir/low/level/api/LowLevelFirApiFacade.kt | 17 ++++++++- 13 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt create mode 100644 idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt 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 20ad8fcd160..7d8309b3825 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 @@ -79,3 +79,25 @@ inline fun buildPropertyAccessor(init: FirPropertyAccessorBuilder.() -> Unit): F } return FirPropertyAccessorBuilder().apply(init).build() } + +@OptIn(ExperimentalContracts::class) +inline fun buildPropertyAccessorCopy(original: FirPropertyAccessor, init: FirPropertyAccessorBuilder.() -> Unit): FirPropertyAccessor { + contract { + callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + val copyBuilder = FirPropertyAccessorBuilder() + copyBuilder.source = original.source + copyBuilder.session = original.session + copyBuilder.resolvePhase = original.resolvePhase + copyBuilder.origin = original.origin + copyBuilder.returnTypeRef = original.returnTypeRef + copyBuilder.valueParameters.addAll(original.valueParameters) + copyBuilder.body = original.body + copyBuilder.contractDescription = original.contractDescription + copyBuilder.symbol = original.symbol + copyBuilder.isGetter = original.isGetter + copyBuilder.status = original.status + copyBuilder.annotations.addAll(original.annotations) + copyBuilder.typeParameters.addAll(original.typeParameters) + return copyBuilder.apply(init).build() +} 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 a3b6ffc78bf..e7a2f5fec4e 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 @@ -206,6 +206,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree defaultNull("body") default("contractDescription", "FirEmptyContractDescription") useTypes(emptyContractDescriptionType) + withCopy() } builder(whenExpression) { diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt new file mode 100644 index 00000000000..021816f8940 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt @@ -0,0 +1,10 @@ +// FIR_COMPARISON + +fun localFun(): Int {} + +val property: Int + get() { + + } + +// EXIST: localFun \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt new file mode 100644 index 00000000000..6fa26c674b7 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt @@ -0,0 +1,8 @@ +// FIR_COMPARISON + +fun localFun(): Int {} + +val property: Int + get() = + +// EXIST: localFun \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt new file mode 100644 index 00000000000..cd64e7f576c --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt @@ -0,0 +1,8 @@ +// FIR_COMPARISON + +class LocalType + +val property + get(): + +// EXIST: LocalType \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt new file mode 100644 index 00000000000..952b33d8ecf --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt @@ -0,0 +1,7 @@ +// FIR_COMPARISON + +fun localFun(): Int {} + +val property = + +// EXIST: localFun \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt new file mode 100644 index 00000000000..4a79c73f10b --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt @@ -0,0 +1,11 @@ +// FIR_COMPARISON + +fun localFun() {} + +var property: Int + get() = 1 + set(value) { + + } + +// EXIST: localFun \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt new file mode 100644 index 00000000000..98af212692c --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt @@ -0,0 +1,9 @@ +// FIR_COMPARISON + +fun localFun() {} + +var property: Int + get() = 1 + set(value) = + +// EXIST: localFun \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt new file mode 100644 index 00000000000..c500ccdc0b6 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt @@ -0,0 +1,7 @@ +// FIR_COMPARISON + +class LocalType + +val property: + +// EXIST: LocalType \ 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 0ca57e2e1dc..080c63b35b6 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 @@ -2362,6 +2362,41 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelClasses.kt"); } + @TestMetadata("topLevelPropertyGetterBodyCompletion.kt") + public void testTopLevelPropertyGetterBodyCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt"); + } + + @TestMetadata("topLevelPropertyGetterExpressionCompletion.kt") + public void testTopLevelPropertyGetterExpressionCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt"); + } + + @TestMetadata("topLevelPropertyGetterTypeCompletion.kt") + public void testTopLevelPropertyGetterTypeCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt"); + } + + @TestMetadata("topLevelPropertyInitializerCompletion.kt") + public void testTopLevelPropertyInitializerCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt"); + } + + @TestMetadata("topLevelPropertySetterBodyCompletion.kt") + public void testTopLevelPropertySetterBodyCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt"); + } + + @TestMetadata("topLevelPropertySetterExpressionCompletion.kt") + public void testTopLevelPropertySetterExpressionCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt"); + } + + @TestMetadata("topLevelPropertyTypeCompletion.kt") + public void testTopLevelPropertyTypeCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt"); + } + @TestMetadata("topLevelVariablesAndFunctions.kt") public void testTopLevelVariablesAndFunctions() throws Exception { runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelVariablesAndFunctions.kt"); 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 762b0edbc0f..7a18e4ff642 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 @@ -2362,6 +2362,41 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelClasses.kt"); } + @TestMetadata("topLevelPropertyGetterBodyCompletion.kt") + public void testTopLevelPropertyGetterBodyCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt"); + } + + @TestMetadata("topLevelPropertyGetterExpressionCompletion.kt") + public void testTopLevelPropertyGetterExpressionCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt"); + } + + @TestMetadata("topLevelPropertyGetterTypeCompletion.kt") + public void testTopLevelPropertyGetterTypeCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt"); + } + + @TestMetadata("topLevelPropertyInitializerCompletion.kt") + public void testTopLevelPropertyInitializerCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt"); + } + + @TestMetadata("topLevelPropertySetterBodyCompletion.kt") + public void testTopLevelPropertySetterBodyCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt"); + } + + @TestMetadata("topLevelPropertySetterExpressionCompletion.kt") + public void testTopLevelPropertySetterExpressionCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt"); + } + + @TestMetadata("topLevelPropertyTypeCompletion.kt") + public void testTopLevelPropertyTypeCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt"); + } + @TestMetadata("topLevelVariablesAndFunctions.kt") public void testTopLevelVariablesAndFunctions() throws Exception { runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelVariablesAndFunctions.kt"); 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 8eab1d38aaf..e987af8d50a 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 @@ -2362,6 +2362,41 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelClasses.kt"); } + @TestMetadata("topLevelPropertyGetterBodyCompletion.kt") + public void testTopLevelPropertyGetterBodyCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterBodyCompletion.kt"); + } + + @TestMetadata("topLevelPropertyGetterExpressionCompletion.kt") + public void testTopLevelPropertyGetterExpressionCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterExpressionCompletion.kt"); + } + + @TestMetadata("topLevelPropertyGetterTypeCompletion.kt") + public void testTopLevelPropertyGetterTypeCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyGetterTypeCompletion.kt"); + } + + @TestMetadata("topLevelPropertyInitializerCompletion.kt") + public void testTopLevelPropertyInitializerCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyInitializerCompletion.kt"); + } + + @TestMetadata("topLevelPropertySetterBodyCompletion.kt") + public void testTopLevelPropertySetterBodyCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterBodyCompletion.kt"); + } + + @TestMetadata("topLevelPropertySetterExpressionCompletion.kt") + public void testTopLevelPropertySetterExpressionCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertySetterExpressionCompletion.kt"); + } + + @TestMetadata("topLevelPropertyTypeCompletion.kt") + public void testTopLevelPropertyTypeCompletion() throws Exception { + runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelPropertyTypeCompletion.kt"); + } + @TestMetadata("topLevelVariablesAndFunctions.kt") public void testTopLevelVariablesAndFunctions() throws Exception { runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelVariablesAndFunctions.kt"); diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt index 4b43d62597e..388bdc51c82 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessorCopy import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy import org.jetbrains.kotlin.fir.expressions.FirStatement @@ -110,8 +111,22 @@ object LowLevelFirApiFacade { val frankensteinProperty = buildPropertyCopy(originalProperty) { symbol = builtProperty.symbol + + // getter does not have parameters to resolve getter = builtProperty.getter - setter = builtProperty.setter + + val originalSetter = setter + val builtSetter = builtProperty.setter + if (originalSetter != null && builtSetter != null) { + setter = buildPropertyAccessorCopy(originalSetter) { + body = builtSetter.body + symbol = builtSetter.symbol + resolvePhase = minOf(builtSetter.resolvePhase, FirResolvePhase.DECLARATIONS) + source = builtSetter.source + session = state.firIdeSourcesSession + } + } + resolvePhase = minOf(originalProperty.resolvePhase, FirResolvePhase.DECLARATIONS) source = builtProperty.source session = state.firIdeSourcesSession