[LL API] Add tests for 'FileBasedKotlinDeclarationProvider'
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// CLASS: Foo
|
||||||
|
// CLASS: Foo.Bar
|
||||||
|
// FUNCTION: /#foo
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
object Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// FUNCTION: test/#foo
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
fun bar() {
|
||||||
|
fun baz() {
|
||||||
|
class Foo
|
||||||
|
object Bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// CLASS: test/Foo
|
||||||
|
// CLASS: test/Bar
|
||||||
|
// CLASS: test/Bar.Baz
|
||||||
|
// CLASS: test/Bar.Boo
|
||||||
|
// CLASS: test/Bar.Bok
|
||||||
|
// FUNCTION: test/#foo
|
||||||
|
// PROPERTY: test/#foo
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
interface Foo
|
||||||
|
typealias Foo = Foo
|
||||||
|
enum class Foo
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
class Baz
|
||||||
|
object Boo
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Bar {
|
||||||
|
object Baz
|
||||||
|
interface Bok
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
|
fun foo(a: Int) {}
|
||||||
|
|
||||||
|
val foo: String = "foo"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// CLASS: test/app/Foo
|
||||||
|
// CLASS: test/app/Foo.Bar
|
||||||
|
// CLASS: test/app/Foo.Bar.Baz
|
||||||
|
// TYPE_ALIAS: test/app/MyString
|
||||||
|
// FUNCTION: test/app/#foo
|
||||||
|
// PROPERTY: test/app/#bar
|
||||||
|
|
||||||
|
package test.app
|
||||||
|
|
||||||
|
interface Foo {
|
||||||
|
class Bar {
|
||||||
|
object Baz
|
||||||
|
}
|
||||||
|
|
||||||
|
fun nested() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias MyString = String
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
|
|
||||||
|
val bar: String = "bar"
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* 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.low.level.api.fir
|
||||||
|
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.FileBasedKotlinDeclarationProvider
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
|
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
||||||
|
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||||
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
import kotlin.test.assertContains
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
|
abstract class AbstractFileBasedKotlinDeclarationProviderTest : AbstractLowLevelApiSingleFileTest() {
|
||||||
|
override val configurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
|
||||||
|
|
||||||
|
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||||
|
super.configureTest(builder)
|
||||||
|
with(builder) {
|
||||||
|
useDirectives(Directives)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||||
|
val provider = FileBasedKotlinDeclarationProvider(ktFile)
|
||||||
|
assertContains(provider.findFilesForFacadeByPackage(ktFile.packageFqName), ktFile)
|
||||||
|
|
||||||
|
checkByDirectives(moduleStructure, provider)
|
||||||
|
checkByVisitor(ktFile, provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkByDirectives(moduleStructure: TestModuleStructure, provider: FileBasedKotlinDeclarationProvider) {
|
||||||
|
for (directive in moduleStructure.allDirectives[Directives.CLASS]) {
|
||||||
|
val classId = ClassId.fromString(directive)
|
||||||
|
assert(provider.getAllClassesByClassId(classId).isNotEmpty()) { "Class $classId not found" }
|
||||||
|
assertNotNull(provider.getClassLikeDeclarationByClassId(classId)) { "Class-like declaration $classId not found" }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (directive in moduleStructure.allDirectives[Directives.TYPE_ALIAS]) {
|
||||||
|
val classId = ClassId.fromString(directive)
|
||||||
|
assert(provider.getAllTypeAliasesByClassId(classId).isNotEmpty()) { "Type alias $classId not found" }
|
||||||
|
assertNotNull(provider.getClassLikeDeclarationByClassId(classId)) { "Class-like declaration $classId not found" }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (directive in moduleStructure.allDirectives[Directives.FUNCTION]) {
|
||||||
|
val callableId = parseCallableId(directive)
|
||||||
|
assert(provider.getTopLevelFunctions(callableId).isNotEmpty()) { "Function $callableId not found" }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (directive in moduleStructure.allDirectives[Directives.PROPERTY]) {
|
||||||
|
val callableId = parseCallableId(directive)
|
||||||
|
assert(provider.getTopLevelProperties(callableId).isNotEmpty()) { "Property $callableId not found" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkByVisitor(ktFile: KtFile, provider: FileBasedKotlinDeclarationProvider) {
|
||||||
|
ktFile.accept(object : KtTreeVisitorVoid() {
|
||||||
|
override fun visitClass(klass: KtClass) {
|
||||||
|
super.visitClass(klass)
|
||||||
|
processClassLikeDeclaration(klass)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
|
||||||
|
super.visitTypeAlias(typeAlias)
|
||||||
|
processClassLikeDeclaration(typeAlias)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processClassLikeDeclaration(declaration: KtClassLikeDeclaration) {
|
||||||
|
val classId = declaration.getClassId() ?: return
|
||||||
|
val shortName = classId.shortClassName
|
||||||
|
|
||||||
|
if (!classId.isNestedClass) {
|
||||||
|
assertContains(provider.getTopLevelKotlinClassLikeDeclarationNamesInPackage(classId.packageFqName), shortName)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (declaration) {
|
||||||
|
is KtClassOrObject -> assertContains(provider.getAllClassesByClassId(classId), declaration)
|
||||||
|
is KtTypeAlias -> assertContains(provider.getAllTypeAliasesByClassId(classId), declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||||
|
super.visitNamedFunction(function)
|
||||||
|
processCallableDeclaration(function)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(property: KtProperty) {
|
||||||
|
super.visitProperty(property)
|
||||||
|
processCallableDeclaration(property)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processCallableDeclaration(declaration: KtCallableDeclaration) {
|
||||||
|
val callableId = declaration.callableId ?: return
|
||||||
|
|
||||||
|
if (callableId.classId == null) {
|
||||||
|
assertContains(provider.getTopLevelCallableFiles(callableId), ktFile)
|
||||||
|
assertContains(provider.getTopLevelCallableNamesInPackage(callableId.packageName), callableId.callableName)
|
||||||
|
|
||||||
|
when (declaration) {
|
||||||
|
is KtFunction -> assertContains(provider.getTopLevelFunctions(callableId), declaration)
|
||||||
|
is KtProperty -> assertContains(provider.getTopLevelProperties(callableId), declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
object Directives : SimpleDirectivesContainer() {
|
||||||
|
val CLASS by stringDirective("ClassId of a class or object to be checked for presence")
|
||||||
|
val TYPE_ALIAS by stringDirective("ClassId of a type alias to be checked for presence")
|
||||||
|
val FUNCTION by stringDirective("CallableId of a function to be checked for presence")
|
||||||
|
val PROPERTY by stringDirective("CallableId of a property to be checked for presence")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val KtCallableDeclaration.callableId: CallableId?
|
||||||
|
get() {
|
||||||
|
val callableName = this.nameAsName ?: return null
|
||||||
|
when (val owner = PsiTreeUtil.getParentOfType(this, KtDeclaration::class.java, KtFile::class.java)) {
|
||||||
|
is KtClassOrObject -> {
|
||||||
|
val classId = owner.getClassId() ?: return null
|
||||||
|
return CallableId(classId, callableName)
|
||||||
|
}
|
||||||
|
is KtFile -> {
|
||||||
|
return CallableId(owner.packageFqName, callableName)
|
||||||
|
}
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseCallableId(rawString: String): CallableId {
|
||||||
|
val chunks = rawString.split('#')
|
||||||
|
assert(chunks.size == 2) { "Invalid CallableId string format: $rawString" }
|
||||||
|
|
||||||
|
val rawQualifier = chunks[0]
|
||||||
|
val rawCallableName = chunks[1]
|
||||||
|
|
||||||
|
val callableName = Name.identifier(rawCallableName)
|
||||||
|
|
||||||
|
return when {
|
||||||
|
rawQualifier.endsWith('/') -> CallableId(FqName(rawQualifier.dropLast(1).replace('/', '.')), callableName)
|
||||||
|
else -> CallableId(ClassId.fromString(rawQualifier, false), callableName)
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.low.level.api.fir;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("analysis/low-level-api-fir/testdata/fileBasedDeclarationProvider")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FileBasedKotlinDeclarationProviderTestGenerated extends AbstractFileBasedKotlinDeclarationProviderTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInFileBasedDeclarationProvider() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/fileBasedDeclarationProvider"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("defaultPackage.kt")
|
||||||
|
public void testDefaultPackage() throws Exception {
|
||||||
|
runTest("analysis/low-level-api-fir/testdata/fileBasedDeclarationProvider/defaultPackage.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("local.kt")
|
||||||
|
public void testLocal() throws Exception {
|
||||||
|
runTest("analysis/low-level-api-fir/testdata/fileBasedDeclarationProvider/local.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("sameNames.kt")
|
||||||
|
public void testSameNames() throws Exception {
|
||||||
|
runTest("analysis/low-level-api-fir/testdata/fileBasedDeclarationProvider/sameNames.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("analysis/low-level-api-fir/testdata/fileBasedDeclarationProvider/simple.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -86,6 +86,10 @@ internal fun TestGroupSuite.generateFirLowLevelApiTests() {
|
|||||||
testClass<AbstractOutOfContentRootGetOrBuildFirTest> {
|
testClass<AbstractOutOfContentRootGetOrBuildFirTest> {
|
||||||
model("getOrBuildFir")
|
model("getOrBuildFir")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractFileBasedKotlinDeclarationProviderTest> {
|
||||||
|
model("fileBasedDeclarationProvider")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testGroup(
|
testGroup(
|
||||||
|
|||||||
Reference in New Issue
Block a user