FIR resolution API: fix handling of expressions inside imports

This commit is contained in:
Mikhail Glukhikh
2019-07-30 12:42:48 +03:00
parent 14e9404afd
commit 869e970bfd
9 changed files with 75 additions and 19 deletions
@@ -97,6 +97,17 @@ fun KtClassOrObject.getOrBuildFir(
return firClass
}
fun KtFile.getOrBuildFir(
state: FirResolveState,
phase: FirResolvePhase = FirResolvePhase.DECLARATIONS
): FirFile {
val session = state.getSession(this)
val firProvider = FirProvider.getInstance(session) as IdeFirProvider
val firFile = firProvider.getOrBuildFile(this)
firFile.runResolve(firFile, firProvider, phase, state)
return firFile
}
private fun FirDeclaration.runResolve(
file: FirFile,
firProvider: IdeFirProvider,
@@ -108,21 +119,23 @@ private fun FirDeclaration.runResolve(
if (toPhase > nonLazyPhase) {
val designation = mutableListOf<FirElement>()
designation += file
val id = when (this) {
is FirCallableDeclaration<*> -> {
this.symbol.callableId.classId
if (this !is FirFile) {
val id = when (this) {
is FirCallableDeclaration<*> -> {
this.symbol.callableId.classId
}
is FirRegularClass -> {
this.symbol.classId
}
else -> error("Unsupported: ${render()}")
}
is FirRegularClass -> {
this.symbol.classId
val outerClasses = generateSequence(id) { classId ->
classId.outerClassId
}.mapTo(mutableListOf()) { firProvider.getFirClassifierByFqName(it)!! }
designation += outerClasses.asReversed()
if (this is FirCallableDeclaration<*>) {
designation += this
}
else -> error("Unsupported: ${render()}")
}
val outerClasses = generateSequence(id) { classId ->
classId.outerClassId
}.mapTo(mutableListOf()) { firProvider.getFirClassifierByFqName(it)!! }
designation += outerClasses.asReversed()
if (this is FirCallableDeclaration<*>) {
designation += this
}
val transformer = FirDesignatedBodyResolveTransformer(
designation.iterator(), state.getSession(psi as KtElement),
@@ -132,12 +145,12 @@ private fun FirDeclaration.runResolve(
}
}
private fun KtElement.containingNonLocalDeclaration(): KtDeclaration {
private fun KtElement.containingNonLocalDeclaration(): KtDeclaration? {
var container = this.containingDeclarationForPseudocode
while (container != null && KtPsiUtil.isLocal(container)) {
container = container.containingDeclarationForPseudocode
}
return container ?: error("No containing non-local declaration: $text")
return container
}
fun KtElement.getOrBuildFir(
@@ -148,6 +161,7 @@ fun KtElement.getOrBuildFir(
when (val container = this.containingNonLocalDeclaration()) {
is KtCallableDeclaration -> container.getOrBuildFir(state, phase)
is KtClassOrObject -> container.getOrBuildFir(state, phase)
null -> containingKtFile.getOrBuildFir(state, phase)
else -> error("Unsupported: ${container.text}")
}
+3
View File
@@ -0,0 +1,3 @@
package bar
fun barbar(): Int = 13
+4
View File
@@ -0,0 +1,4 @@
FILE: bar.kt
public final fun barbar(): R|kotlin/Int| {
^barbar Int(13)
}
+7
View File
@@ -0,0 +1,7 @@
package foo
import bar.<caret>barbar
fun foofoo(): Int {
return barbar()
}
+4
View File
@@ -0,0 +1,4 @@
FILE: main.kt
public final fun foofoo(): R|kotlin/Int| {
^foofoo R|bar/barbar|()
}
+3
View File
@@ -0,0 +1,3 @@
{
"mainFile": "foo/main.kt"
}
+1
View File
@@ -0,0 +1 @@
import bar.barbar
@@ -13,6 +13,7 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.search.FileTypeIndex
import com.intellij.testFramework.LightProjectDescriptor
import junit.framework.TestCase
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.idea.KotlinFileType
@@ -63,9 +64,23 @@ abstract class AbstractFirLazyResolveTest : KotlinLightCodeInsightFixtureTestCas
} as KtExpression
val resolveState = expressionToResolve.firResolveState()
val firExpression = expressionToResolve.getOrBuildFir(resolveState)
val resultsDump = firExpression.render()
val resultsDump = when (val firElement = expressionToResolve.getOrBuildFir(resolveState)) {
is FirResolvedImport -> buildString {
append("import ")
append(firElement.packageFqName)
val className = firElement.relativeClassName
if (className != null) {
append("/")
append(className)
}
val name = firElement.importedName
if (name != null) {
append(".")
append(name)
}
}
else -> firElement.render()
}
KotlinTestUtils.assertEqualsToFile(File(testFile.parent, "results.txt"), resultsDump)
fun expectedTxtPath(virtualFile: VirtualFile): String {
@@ -73,7 +88,7 @@ abstract class AbstractFirLazyResolveTest : KotlinLightCodeInsightFixtureTestCas
var result: String? = null
val root = File(path).parentFile
for (file in root.walkTopDown()) {
if (!file.isDirectory && virtualPath in file.absolutePath) {
if (!file.isDirectory && virtualPath in file.absolutePath.replace("\\", "/")) {
result = file.absolutePath.replace(".kt", ".txt")
}
}
@@ -34,6 +34,11 @@ public class FirLazyResolveTestGenerated extends AbstractFirLazyResolveTest {
runTest("idea/testData/fir/lazyResolve/elvis/elvis.test");
}
@TestMetadata("import/import.test")
public void testImport_Import() throws Exception {
runTest("idea/testData/fir/lazyResolve/import/import.test");
}
@TestMetadata("inInit/inInit.test")
public void testInInit_InInit() throws Exception {
runTest("idea/testData/fir/lazyResolve/inInit/inInit.test");