FIR IDE: Add tests for resolving compiled declarations
Also, use correct index to find source for properties in `FirIdeDeserializedDeclarationSourceProvider` - this bug was revealed by the tests
This commit is contained in:
+3
@@ -1072,6 +1072,9 @@ fun main(args: Array<String>) {
|
||||
testClass<AbstractFirLazyDeclarationResolveTest> {
|
||||
model("lazyResolve")
|
||||
}
|
||||
testClass<AbstractFirLibraryModuleDeclarationResolveTest> {
|
||||
model("libraryModuleResolve", recursive = false)
|
||||
}
|
||||
testClass<AbstractProjectWideOutOfBlockKotlinModificationTrackerTest> {
|
||||
model("outOfBlockProjectWide")
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package library
|
||||
|
||||
fun topLevelFunction() {}
|
||||
|
||||
fun topLevelFunction(s: String) {}
|
||||
|
||||
val topLevelProperty: Int = 0
|
||||
|
||||
class TopLevelClass() {
|
||||
|
||||
constructor(s: String) : this() {}
|
||||
|
||||
fun memberFunction() {}
|
||||
|
||||
fun memberFunction(s: String) {}
|
||||
|
||||
val memberProperty: Int = 0
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.TopLevelClass
|
||||
|
||||
fun usage() {
|
||||
TopLevelClass().<caret>memberFunction()
|
||||
}
|
||||
idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/memberFunctionNoArgs.txt
Vendored
+1
@@ -0,0 +1 @@
|
||||
public final [BODY_RESOLVE] fun memberFunction(): R|kotlin/Unit|
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.TopLevelClass
|
||||
|
||||
fun usage() {
|
||||
TopLevelClass().<caret>memberFunction("")
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public final [BODY_RESOLVE] fun memberFunction([BODY_RESOLVE] s: R|kotlin/String|): R|kotlin/Unit|
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.TopLevelClass
|
||||
|
||||
fun usage() {
|
||||
val a = TopLevelClass().<caret>memberProperty
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
public final [BODY_RESOLVE] val memberProperty: R|kotlin/Int|
|
||||
[BODY_RESOLVE] public get(): R|kotlin/Int|
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.TopLevelClass
|
||||
|
||||
fun usage() {
|
||||
val a: <caret>TopLevelClass
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
public final [BODY_RESOLVE] class TopLevelClass : R|kotlin/Any| {
|
||||
public final [BODY_RESOLVE] fun memberFunction(): R|kotlin/Unit|
|
||||
|
||||
public final [BODY_RESOLVE] fun memberFunction([BODY_RESOLVE] s: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
public final [BODY_RESOLVE] val memberProperty: R|kotlin/Int|
|
||||
[BODY_RESOLVE] public get(): R|kotlin/Int|
|
||||
|
||||
public [BODY_RESOLVE] constructor([BODY_RESOLVE] s: R|kotlin/String|): R|library/TopLevelClass|
|
||||
|
||||
public [BODY_RESOLVE] constructor(): R|library/TopLevelClass|
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.TopLevelClass
|
||||
|
||||
fun usage() {
|
||||
val a = <caret>TopLevelClass()
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public [BODY_RESOLVE] constructor(): R|library/TopLevelClass|
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.TopLevelClass
|
||||
|
||||
fun usage() {
|
||||
val a = <caret>TopLevelClass("arg")
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public [BODY_RESOLVE] constructor([BODY_RESOLVE] s: R|kotlin/String|): R|library/TopLevelClass|
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.topLevelFunction
|
||||
|
||||
fun usage() {
|
||||
<caret>topLevelFunction()
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public final [BODY_RESOLVE] fun topLevelFunction(): R|kotlin/Unit|
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.topLevelFunction
|
||||
|
||||
fun usage() {
|
||||
<caret>topLevelFunction("")
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public final [BODY_RESOLVE] fun topLevelFunction([BODY_RESOLVE] s: R|kotlin/String|): R|kotlin/Unit|
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
import library.topLevelProperty
|
||||
|
||||
fun usage() {
|
||||
val a = <caret>topLevelProperty
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
public final [BODY_RESOLVE] val topLevelProperty: R|kotlin/Int|
|
||||
[BODY_RESOLVE] public get(): R|kotlin/Int|
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.low.level.api
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.SdkAndMockLibraryProjectDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirLibraryModuleDeclarationResolveTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
override fun isFirPlugin(): Boolean = true
|
||||
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor {
|
||||
val pathToLibraryFiles = File(testDataPath).resolve("_library")
|
||||
assertExists(pathToLibraryFiles)
|
||||
|
||||
return SdkAndMockLibraryProjectDescriptor(pathToLibraryFiles.toString(), true)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to check that resolving 'compiled' PSI-elements (i.e. elements from libraries)
|
||||
* works as expected.
|
||||
*
|
||||
* Compiled PSI-elements might come from indices, for example, and we need to be able to work with them
|
||||
* and to resolve them to FIR declarations.
|
||||
*/
|
||||
fun doTest(path: String) {
|
||||
val testDataFile = File(path)
|
||||
val expectedFile = File(path.removeSuffix(".kt") + ".txt")
|
||||
|
||||
val ktFile = myFixture.configureByFile(testDataFile.name) as KtFile
|
||||
|
||||
val caretResolutionTarget = myFixture.elementAtCaret
|
||||
|
||||
require(caretResolutionTarget is KtDeclaration) {
|
||||
"Element at caret should be referencing some declaration, but referenced ${caretResolutionTarget::class} instead"
|
||||
}
|
||||
|
||||
// We intentionally use ktFile here as a context element, because resolving
|
||||
// from compiled PSI-elements (e.g. caretResolutionTarget) is not yet supported
|
||||
resolveWithClearCaches(ktFile) { resolveState ->
|
||||
val renderedDeclaration = caretResolutionTarget.withFirDeclaration(resolveState) { firDeclaration ->
|
||||
firDeclaration.render(FirRenderer.RenderMode.WithResolvePhases)
|
||||
}
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, renderedDeclaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.low.level.api;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class FirLibraryModuleDeclarationResolveTestGenerated extends AbstractFirLibraryModuleDeclarationResolveTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInLibraryModuleResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve"), Pattern.compile("^(.+)\\.kt$"), null, false);
|
||||
}
|
||||
|
||||
@TestMetadata("memberFunctionNoArgs.kt")
|
||||
public void testMemberFunctionNoArgs() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/memberFunctionNoArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("memberFunctionWithArgs.kt")
|
||||
public void testMemberFunctionWithArgs() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/memberFunctionWithArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("memberProperty.kt")
|
||||
public void testMemberProperty() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/memberProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelClass.kt")
|
||||
public void testTopLevelClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/topLevelClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelClassPrimaryConstructor.kt")
|
||||
public void testTopLevelClassPrimaryConstructor() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/topLevelClassPrimaryConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelClassSecondaryConstructor.kt")
|
||||
public void testTopLevelClassSecondaryConstructor() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/topLevelClassSecondaryConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelFunctionNoArgs.kt")
|
||||
public void testTopLevelFunctionNoArgs() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/topLevelFunctionNoArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelFunctionWithArgs.kt")
|
||||
public void testTopLevelFunctionWithArgs() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/topLevelFunctionWithArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelProperty.kt")
|
||||
public void testTopLevelProperty() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/libraryModuleResolve/topLevelProperty.kt");
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSession
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyFqnNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasFqNameIndex
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
@@ -55,7 +56,7 @@ object FirIdeDeserializedDeclarationSourceProvider {
|
||||
|
||||
private fun provideSourceForProperty(property: FirProperty, project: Project): PsiElement? {
|
||||
val candidates = if (property.isTopLevel) {
|
||||
KotlinTopLevelFunctionFqnNameIndex.getInstance().get(
|
||||
KotlinTopLevelPropertyFqnNameIndex.getInstance().get(
|
||||
property.symbol.callableId.asSingleFqName().asString(),
|
||||
project,
|
||||
property.scope(project)
|
||||
|
||||
Reference in New Issue
Block a user