[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> {
|
||||
model("getOrBuildFir")
|
||||
}
|
||||
|
||||
testClass<AbstractFileBasedKotlinDeclarationProviderTest> {
|
||||
model("fileBasedDeclarationProvider")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup(
|
||||
|
||||
Reference in New Issue
Block a user