AA: introduce new APIs to get containing file (symbol) and JvmClassName

^KTIJ-27686
This commit is contained in:
Jinseong Jeon
2023-11-17 11:08:21 -08:00
committed by Space Team
parent 5b6363b0df
commit 797174ee1f
24 changed files with 891 additions and 37 deletions
@@ -6,12 +6,12 @@
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.checkContainingFileSymbol
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.checkContainingJvmClassName
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtScriptSymbol
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScriptInitializer
import org.jetbrains.kotlin.psi.KtVisitorVoid
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
@@ -19,7 +19,9 @@ import org.jetbrains.kotlin.test.services.assertions
abstract class AbstractContainingDeclarationProviderByPsiTest : AbstractAnalysisApiSingleFileTest() {
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
val currentPath = mutableListOf<KtDeclaration>()
val ktClasses = mutableListOf<KtClassOrObject>()
analyseForTest(ktFile.declarations.first()) {
val expectedFileSymbol = ktFile.getFileSymbol()
ktFile.accept(object : KtVisitorVoid() {
override fun visitElement(element: PsiElement) {
element.acceptChildren(this)
@@ -39,9 +41,20 @@ abstract class AbstractContainingDeclarationProviderByPsiTest : AbstractAnalysis
}
}
checkContainingFileSymbol(expectedFileSymbol, currentDeclarationSymbol, testServices)
if (currentDeclarationSymbol is KtCallableSymbol) {
checkContainingJvmClassName(ktFile, ktClasses.lastOrNull(), currentDeclarationSymbol, testServices)
}
currentPath.add(dcl)
if (dcl is KtClassOrObject) {
ktClasses.add(dcl)
}
super.visitDeclaration(dcl)
currentPath.removeLast()
if (dcl is KtClassOrObject) {
ktClasses.removeLast()
}
}
})
}
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclarationRendererForDebug
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
@@ -35,9 +36,12 @@ abstract class AbstractMultiModuleSymbolByPsiTest : AbstractAnalysisApiBasedTest
prettyPrinter.appendLine(fileDirective)
analyseForTest(file) {
val fileSymbol = file.getFileSymbol()
file.forEachDescendantOfType<KtDeclaration>(predicate = { it.isValidForSymbolCreation }) { declaration ->
val symbol = declaration.getSymbol()
checkContainingFileSymbol(fileSymbol, symbol, testServices)
debugPrinter.appendLine(debugRenderer.render(symbol))
debugPrinter.appendLine()
@@ -91,6 +91,9 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiSingleFileTest() {
val pointersWithRendered = executeOnPooledThreadInReadAction {
analyseForTest(ktFile) {
val (symbols, symbolForPrettyRendering) = collectSymbols(ktFile, testServices)
for (symbol in symbols) {
checkContainingFileSymbol(ktFile.getFileSymbol(), symbol, testServices)
}
val pointerWithRenderedSymbol = symbols
.asSequence()
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2023 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.analysis.api.impl.base.test.cases.symbols
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
context(KtAnalysisSession)
internal fun checkContainingFileSymbol(
ktFileSymbol: KtFileSymbol,
symbol: KtSymbol,
testServices: TestServices
) {
if (symbol.origin != KtSymbolOrigin.SOURCE) return
val containingFileSymbol = symbol.getContainingFileSymbol()
testServices.assertions.assertEquals(ktFileSymbol, containingFileSymbol) {
"Invalid file for $symbol, expected $ktFileSymbol but $containingFileSymbol found"
}
}
context(KtAnalysisSession)
internal fun checkContainingJvmClassName(
ktFile: KtFile,
ktClass: KtClassOrObject?,
symbol: KtCallableSymbol,
testServices: TestServices
) {
if (ktFile.isScript()) return
val expectedClassName = when {
symbol.symbolKind == KtSymbolKind.LOCAL ->
null
ktClass != null ->
// member
ktClass.getClassId()?.let { JvmClassName.byClassId(it) }
else ->
// top-level
JvmClassName.byFqNameWithoutInnerClasses(ktFile.javaFileFacadeFqName)
}
val actualClassName = symbol.getContainingJvmClassName()
testServices.assertions.assertEquals(expectedClassName, actualClassName) {
"Invalid JvmClassName for $symbol, expected $expectedClassName but $actualClassName found"
}
}