[LL FIR] ClassId: add more tests

^KTIJ-26848
^KTIJ-26896
^KTIJ-26902
This commit is contained in:
Dmitrii Gridin
2023-09-04 16:55:42 +02:00
committed by Space Team
parent f51b7faa1b
commit 2421d3cdf1
18 changed files with 395 additions and 2 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils.offsetToLineAndColumn
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.test.directives.model.Directive
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
inline fun <T> runReadAction(crossinline runnable: () -> T): T {
return ApplicationManager.getApplication().runReadAction(Computable { runnable() })
@@ -53,3 +55,24 @@ fun PsiReference.unwrapMultiReferences(): List<PsiReference> = when (this) {
is PsiMultiReference -> references.flatMap { it.unwrapMultiReferences() }
else -> error("Unexpected reference $this")
}
/**
* [AfterAnalysisChecker][org.jetbrains.kotlin.test.model.AfterAnalysisChecker] should be the preferred option
*/
fun RegisteredDirectives.ignoreExceptionIfIgnoreDirectivePresent(ignoreDirective: Directive, action: () -> Unit) {
var exception: Throwable? = null
try {
action()
} catch (e: Throwable) {
exception = e
}
if (ignoreDirective in this) {
if (exception != null) return
error("$ignoreDirective is redundant")
}
if (exception != null) {
throw exception
}
}
@@ -24,3 +24,5 @@
foo {
/* ClassId: null */class E
}
// IGNORE_CONSISTENCY_CHECK: KTIJ-26902
@@ -1,3 +1,4 @@
// IGNORE_CONSISTENCY_CHECK: KTIJ-26902
package one.two
/* ClassId: one/two/TopLevelObject */object TopLevelObject
+10
View File
@@ -0,0 +1,10 @@
package one
/* ClassId: one/MyEnum */enum class MyEnum {
;
/* ClassId: one/MyEnum.InsideEnum */class InsideEnum
/* ClassId: one/MyEnum.ObjectInsideEnum */object ObjectInsideEnum {
/* ClassId: one/MyEnum.ObjectInsideEnum.Nested */typealias Nested
}
}
+12
View File
@@ -0,0 +1,12 @@
package one
/* ClassId: one/MyEnum */enum class MyEnum {
;
/* ClassId: one/MyEnum.InsideEnum */class InsideEnum
/* ClassId: one/MyEnum.ObjectInsideEnum */object ObjectInsideEnum {
/* ClassId: one/MyEnum.ObjectInsideEnum.Nested */typealias Nested
}
}
// IGNORE_CONSISTENCY_CHECK: KTIJ-26902
@@ -0,0 +1,14 @@
package one
/* ClassId: one/MyEnum */enum class MyEnum {
/* ClassId: null */Entry {
fun foo() = Unit
/* ClassId: null */class ClassInsideEntry
},
/* ClassId: null */Entry2,
/* ClassId: null */Entry3 {
}
}
// IGNORE_CONSISTENCY_CHECK: KtEnumEntry have FqName, but doesn't have ClassId
@@ -0,0 +1,14 @@
package one
/* ClassId: one/MyEnum */enum class MyEnum {
/* ClassId: null */Entry {
fun foo() = Unit
/* ClassId: null */class ClassInsideEntry
},
/* ClassId: null */Entry2,
/* ClassId: null */Entry3 {
}
}
// IGNORE_CONSISTENCY_CHECK: KtEnumEntry have FqName, but doesn't have ClassId
@@ -0,0 +1,19 @@
package one.two
/* ClassId: one/two/<no name provided> */class
/* ClassId: one/two/<no name provided> */object
/* ClassId: one/two/<no name provided> */typealias
/* ClassId: one/two/A */class A {
/* ClassId: one/two/A.<no name provided> */class
/* ClassId: one/two/A.<no name provided> */object
/* ClassId: one/two/A.<no name provided> */typealias
}
/* ClassId: one/two/B */object B {
/* ClassId: one/two/B.<no name provided> */class
/* ClassId: one/two/B.<no name provided> */object
/* ClassId: one/two/B.<no name provided> */typealias
}
// IGNORE_CONSISTENCY_CHECK: KTIJ-26848
@@ -0,0 +1,18 @@
// IGNORE_CONSISTENCY_CHECK: KTIJ-26902
package one.two
/* ClassId: one/two/<no name provided> */class
/* ClassId: one/two/<no name provided> */object
/* ClassId: one/two/<no name provided> */typealias
/* ClassId: one/two/A */class A {
/* ClassId: one/two/A.<no name provided> */class
/* ClassId: one/two/A.<no name provided> */object
/* ClassId: one/two/A.<no name provided> */typealias
}
/* ClassId: one/two/B */object B {
/* ClassId: one/two/B.<no name provided> */class
/* ClassId: one/two/B.<no name provided> */object
/* ClassId: one/two/B.<no name provided> */typealias
}
@@ -0,0 +1,15 @@
package one.two
/* ClassId: one/two/<no name provided> */class {
/* ClassId: one/two/<no name provided>.<no name provided> */class
/* ClassId: one/two/<no name provided>.<no name provided> */object
/* ClassId: one/two/<no name provided>.<no name provided> */typealias
}
/* ClassId: one/two/<no name provided> */object {
/* ClassId: one/two/<no name provided>.<no name provided> */class
/* ClassId: one/two/<no name provided>.<no name provided> */object
/* ClassId: one/two/<no name provided>.<no name provided> */typealias
}
// IGNORE_CONSISTENCY_CHECK: KTIJ-26896
@@ -0,0 +1,15 @@
package one.two
/* ClassId: one/two/<no name provided> */class {
/* ClassId: one/two/<no name provided>.<no name provided> */class
/* ClassId: one/two/<no name provided>.<no name provided> */object
/* ClassId: one/two/<no name provided>.<no name provided> */typealias
}
/* ClassId: null */object {
/* ClassId: null */class
/* ClassId: null */object
/* ClassId: null */typealias
}
// IGNORE_CONSISTENCY_CHECK: KTIJ-26896
@@ -0,0 +1,51 @@
/*
* 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 org.jetbrains.kotlin.analysis.low.level.api.fir.AbstractClassIdConsistencyTest.Directives.IGNORE_CONSISTENCY_CHECK
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirScriptTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.utils.ignoreExceptionIfIgnoreDirectivePresent
import org.jetbrains.kotlin.psi.KtClassLikeDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.safeFqNameForLazyResolve
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 org.jetbrains.kotlin.test.services.assertions
abstract class AbstractClassIdConsistencyTest : AbstractLowLevelApiSingleFileTest() {
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
moduleStructure.allDirectives.ignoreExceptionIfIgnoreDirectivePresent(IGNORE_CONSISTENCY_CHECK) {
ktFile.forEachDescendantOfType<KtClassLikeDeclaration> { declaration ->
val classId = declaration.getClassId()
val fqName = declaration.safeFqNameForLazyResolve()
testServices.assertions.assertEquals(fqName, classId?.asSingleFqName())
}
}
}
private object Directives : SimpleDirectivesContainer() {
val IGNORE_CONSISTENCY_CHECK by stringDirective("Temporary disable test until the issue is fixed")
}
override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder)
builder.useDirectives(Directives)
}
}
abstract class AbstractSourceClassIdConsistencyTest : AbstractClassIdConsistencyTest() {
override val configurator: AnalysisApiTestConfigurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
}
abstract class AbstractScriptClassIdConsistencyTest : AbstractClassIdConsistencyTest() {
override val configurator: AnalysisApiTestConfigurator = AnalysisApiFirScriptTestConfigurator(analyseInDependentSession = false)
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLeve
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirScriptTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClassLikeDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.services.TestModuleStructure
@@ -35,7 +36,13 @@ abstract class AbstractClassIdTest : AbstractLowLevelApiSingleFileTest() {
element.acceptChildren(this)
}
override fun visitComment(comment: PsiComment) {}
override fun visitComment(comment: PsiComment) {
if (comment.tokenType == KtTokens.BLOCK_COMMENT) {
return
}
super.visitComment(comment)
}
})
}
@@ -0,0 +1,62 @@
/*
* 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/classId")
@TestDataPath("$PROJECT_ROOT")
public class ScriptClassIdConsistencyTestGenerated extends AbstractScriptClassIdConsistencyTest {
@Test
public void testAllFilesPresentInClassId() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/classId"), Pattern.compile("^(.+)\\.(kts)$"), null, true);
}
@Test
@TestMetadata("classWithMembers.kts")
public void testClassWithMembers() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/classWithMembers.kts");
}
@Test
@TestMetadata("classWithMembersWithPackage.kts")
public void testClassWithMembersWithPackage() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/classWithMembersWithPackage.kts");
}
@Test
@TestMetadata("enum.kts")
public void testEnum() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enum.kts");
}
@Test
@TestMetadata("enumEntry.kts")
public void testEnumEntry() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enumEntry.kts");
}
@Test
@TestMetadata("namelessClasses.kts")
public void testNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessClasses.kts");
}
@Test
@TestMetadata("namelessInsideNamelessClasses.kts")
public void testNamelessInsideNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessInsideNamelessClasses.kts");
}
}
@@ -35,4 +35,28 @@ public class ScriptClassIdTestGenerated extends AbstractScriptClassIdTest {
public void testClassWithMembersWithPackage() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/classWithMembersWithPackage.kts");
}
@Test
@TestMetadata("enum.kts")
public void testEnum() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enum.kts");
}
@Test
@TestMetadata("enumEntry.kts")
public void testEnumEntry() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enumEntry.kts");
}
@Test
@TestMetadata("namelessClasses.kts")
public void testNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessClasses.kts");
}
@Test
@TestMetadata("namelessInsideNamelessClasses.kts")
public void testNamelessInsideNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessInsideNamelessClasses.kts");
}
}
@@ -0,0 +1,74 @@
/*
* 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/classId")
@TestDataPath("$PROJECT_ROOT")
public class SourceClassIdConsistencyTestGenerated extends AbstractSourceClassIdConsistencyTest {
@Test
public void testAllFilesPresentInClassId() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/classId"), Pattern.compile("^(.+)\\.(kt)$"), null, true);
}
@Test
@TestMetadata("classWithMembers.kt")
public void testClassWithMembers() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/classWithMembers.kt");
}
@Test
@TestMetadata("enum.kt")
public void testEnum() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enum.kt");
}
@Test
@TestMetadata("enumEntry.kt")
public void testEnumEntry() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enumEntry.kt");
}
@Test
@TestMetadata("localClassInsideFunctionLiteral.kt")
public void testLocalClassInsideFunctionLiteral() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/localClassInsideFunctionLiteral.kt");
}
@Test
@TestMetadata("localClassInsideLambdaCallInsideStringTemplate.kt")
public void testLocalClassInsideLambdaCallInsideStringTemplate() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/localClassInsideLambdaCallInsideStringTemplate.kt");
}
@Test
@TestMetadata("localClassInsideSuperEntryCall.kt")
public void testLocalClassInsideSuperEntryCall() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/localClassInsideSuperEntryCall.kt");
}
@Test
@TestMetadata("namelessClasses.kt")
public void testNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessClasses.kt");
}
@Test
@TestMetadata("namelessInsideNamelessClasses.kt")
public void testNamelessInsideNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessInsideNamelessClasses.kt");
}
}
@@ -30,6 +30,18 @@ public class SourceClassIdTestGenerated extends AbstractSourceClassIdTest {
runTest("analysis/low-level-api-fir/testdata/classId/classWithMembers.kt");
}
@Test
@TestMetadata("enum.kt")
public void testEnum() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enum.kt");
}
@Test
@TestMetadata("enumEntry.kt")
public void testEnumEntry() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/enumEntry.kt");
}
@Test
@TestMetadata("localClassInsideFunctionLiteral.kt")
public void testLocalClassInsideFunctionLiteral() throws Exception {
@@ -47,4 +59,16 @@ public class SourceClassIdTestGenerated extends AbstractSourceClassIdTest {
public void testLocalClassInsideSuperEntryCall() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/localClassInsideSuperEntryCall.kt");
}
@Test
@TestMetadata("namelessClasses.kt")
public void testNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessClasses.kt");
}
@Test
@TestMetadata("namelessInsideNamelessClasses.kt")
public void testNamelessInsideNamelessClasses() throws Exception {
runTest("analysis/low-level-api-fir/testdata/classId/namelessInsideNamelessClasses.kt");
}
}
@@ -175,6 +175,14 @@ internal fun TestGroupSuite.generateFirLowLevelApiTests() {
model("classId", pattern = TestGeneratorUtil.KTS)
}
testClass<AbstractSourceClassIdConsistencyTest> {
model("classId", pattern = TestGeneratorUtil.KT)
}
testClass<AbstractScriptClassIdConsistencyTest> {
model("classId", pattern = TestGeneratorUtil.KTS)
}
testClass<AbstractCompilationPeerAnalysisTest> {
model("compilationPeers")
}