From 0870ded05403cc02e0cc38376da5419ccc947fa6 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 13 Jul 2020 15:28:11 +0300 Subject: [PATCH] FIR IDE: introduce KtFirArrayAccessReference --- .../kotlin/fir/builder/RawFirBuilder.kt | 5 ++- .../jetbrains/kotlin/fir/FirSourceElement.kt | 3 ++ .../FirReferenceResolveTestGenerated.java | 23 +++++++++++ ...deDeserializedDeclarationSourceProvider.kt | 2 +- .../org/jetbrains/kotlin/idea/fir/FirUtils.kt | 2 +- .../KotlinFirReferenceContributor.kt | 1 + .../references/KtFirArrayAccessReference.kt | 39 +++++++++++++++++++ .../resolve/references/arrayAccess/get.kt | 7 ++++ .../resolve/references/arrayAccess/set.kt | 7 ++++ .../ReferenceResolveTestGenerated.java | 23 +++++++++++ 10 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirArrayAccessReference.kt create mode 100644 idea/testData/resolve/references/arrayAccess/get.kt create mode 100644 idea/testData/resolve/references/arrayAccess/set.kt 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 8c31c29a866..da23518720f 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 @@ -1790,16 +1790,17 @@ class RawFirBuilder( if (getArgument != null) { calleeReference = buildSimpleNamedReference { source = expression.parent.toFirSourceElement() - this.source = source + this.source = source.fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) name = OperatorNameConventions.SET } } else { source = expression.toFirSourceElement() calleeReference = buildSimpleNamedReference { - this.source = source + this.source = source.fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) name = OperatorNameConventions.GET } } + this.source = source explicitReceiver = arrayExpression.toFirExpression("No array expression") argumentList = buildArgumentList { for (indexExpression in expression.indexExpressions) { diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt index acbe8e78de9..cdcd6bae8cc 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt @@ -139,6 +139,9 @@ sealed class FirFakeSourceElementKind : FirSourceElementKind() { // where `val $subj = a` has a fake source object WhenGeneratedSubject : FirFakeSourceElementKind() + // list[0] -> list.get(0) where name reference will have a fake source element + object ArrayAccessNameReference : FirFakeSourceElementKind() + // super.foo() --> super.foo() // where `Supertype` has a fake source object SuperCallImplicitType : FirFakeSourceElementKind() diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java index 842cd318930..c26d10c7225 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java @@ -418,6 +418,29 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv runTest("idea/testData/resolve/references/WrongNumberOfTypeArgumentsInSupertype.kt"); } + @TestMetadata("idea/testData/resolve/references/arrayAccess") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ArrayAccess extends AbstractFirReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInArrayAccess() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/arrayAccess"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("get.kt") + public void testGet() throws Exception { + runTest("idea/testData/resolve/references/arrayAccess/get.kt"); + } + + @TestMetadata("set.kt") + public void testSet() throws Exception { + runTest("idea/testData/resolve/references/arrayAccess/set.kt"); + } + } + @TestMetadata("idea/testData/resolve/references/delegatedPropertyAccessors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) 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 b15006d32b2..b3db547560f 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 @@ -116,7 +116,7 @@ object FirIdeDeserializedDeclarationSourceProvider { } private fun FirCallableDeclaration<*>.containingKtClass(project: Project): KtClassOrObject? = - symbol.callableId.classId?.let { classByClassId(it, scope(project), project) } + unrollFakeOverrides().symbol.callableId.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 } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt index a83a9a4b10c..5802d0cf4a4 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt @@ -63,7 +63,7 @@ fun FirFunctionCall.getCalleeSymbol(): FirBasedSymbol<*>? = fun FirReference.getResolvedSymbolOfNameReference(): FirBasedSymbol<*>? = (this as? FirResolvedNamedReference)?.resolvedSymbol -inline fun D.unrollFakeOverrides(): D where D : FirDeclaration, D : FirSymbolOwner { +inline fun D.unrollFakeOverrides(): D where D : FirDeclaration, D : FirSymbolOwner<*> { val symbol = symbol if (symbol !is PossiblyFirFakeOverrideSymbol<*, *>) return this if (!symbol.isFakeOverride) return this diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt index 9834361bb72..01b8f5859e3 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt @@ -13,6 +13,7 @@ class KotlinFirReferenceContributor : KotlinReferenceProviderContributor { registerProvider(factory = ::KtFirInvokeFunctionReference) registerProvider(factory = ::KtFirPropertyDelegationMethodsReference) registerProvider(factory = ::KtFirDestructuringDeclarationReference) + registerProvider(factory = ::KtFirArrayAccessReference) } } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirArrayAccessReference.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirArrayAccessReference.kt new file mode 100644 index 00000000000..45b8eaa844c --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirArrayAccessReference.kt @@ -0,0 +1,39 @@ +/* + * 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.references + +import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.idea.fir.getCalleeSymbol +import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtExpression + +class KtFirArrayAccessReference( + expression: KtArrayAccessExpression +) : KtArrayAccessReference(expression), KtFirReference { + override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection { + check(analysisSession is KtFirAnalysisSession) + val fir = element.getOrBuildFirSafe(analysisSession.firResolveState) ?: return emptyList() + return listOfNotNull(fir.getCalleeSymbol()?.fir?.buildSymbol(analysisSession.firSymbolBuilder)) + } + + override fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) { + TODO("Not yet implemented") + } + + override fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression): Boolean { + TODO("Not yet implemented") + } + + override fun doRenameImplicitConventionalCall(newName: String?): KtExpression { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/idea/testData/resolve/references/arrayAccess/get.kt b/idea/testData/resolve/references/arrayAccess/get.kt new file mode 100644 index 00000000000..186bafd6dc0 --- /dev/null +++ b/idea/testData/resolve/references/arrayAccess/get.kt @@ -0,0 +1,7 @@ +fun a () { + val list = mutableListOf(1) + println(list[0]) +} + +// REF: (in kotlin.collections.List).get(kotlin.Int) + diff --git a/idea/testData/resolve/references/arrayAccess/set.kt b/idea/testData/resolve/references/arrayAccess/set.kt new file mode 100644 index 00000000000..78f9af3e08f --- /dev/null +++ b/idea/testData/resolve/references/arrayAccess/set.kt @@ -0,0 +1,7 @@ +fun a () { + val list = mutableListOf(1) + list[0] = 1 +} + +// REF: (in kotlin.collections.MutableList).set(kotlin.Int, E) + diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java index 27463ca5dfa..d181ad5bf93 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java @@ -418,6 +418,29 @@ public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest runTest("idea/testData/resolve/references/WrongNumberOfTypeArgumentsInSupertype.kt"); } + @TestMetadata("idea/testData/resolve/references/arrayAccess") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ArrayAccess extends AbstractReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInArrayAccess() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/arrayAccess"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("get.kt") + public void testGet() throws Exception { + runTest("idea/testData/resolve/references/arrayAccess/get.kt"); + } + + @TestMetadata("set.kt") + public void testSet() throws Exception { + runTest("idea/testData/resolve/references/arrayAccess/set.kt"); + } + } + @TestMetadata("idea/testData/resolve/references/delegatedPropertyAccessors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)