[FIR] Find the correct FIR file in Java finder for file with JvmName

#KT-57802
This commit is contained in:
Ivan Kylchik
2023-07-10 12:55:59 +02:00
committed by Space Team
parent 8c7c44f9f5
commit a45bb8d92b
11 changed files with 92 additions and 14 deletions
@@ -18,8 +18,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.isOverridable
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.java.findJvmNameAnnotation
import org.jetbrains.kotlin.fir.resolve.getContainingClass
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.name.JvmStandardClassIds
@@ -57,12 +57,6 @@ object FirJvmNameChecker : FirBasicDeclarationChecker() {
}
}
private fun FirDeclaration.findJvmNameAnnotation(): FirAnnotation? {
return annotations.firstOrNull {
it.annotationTypeRef.coneType.classId == JvmStandardClassIds.Annotations.JvmName
}
}
private fun CheckerContext.isRenamableFunction(function: FirFunction): Boolean {
val containingClass = function.getContainingClassSymbol(session)
return containingClass != null || !function.symbol.callableId.isLocal
@@ -29261,6 +29261,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@Test
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
@Test
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -29261,6 +29261,12 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@Test
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
@Test
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -29261,6 +29261,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@Test
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
@Test
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -19,6 +19,7 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
@@ -26,11 +27,12 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
@@ -65,6 +67,11 @@ class FirJavaElementFinder(
session.collectAllDependentSourceSessions().mapTo(this) { it.firProvider }
}
private val fileCache: FirCache<FqName, Map<String, List<FirFile>>, Nothing?> = session.firCachesFactory
.createCache { packageFqName, _ ->
firProviders.flatMap { it.getFirFilesByPackage(packageFqName) }.groupBy { it.jvmName() }
}
override fun findPackage(qualifiedName: String): PsiPackage? {
if (firProviders.none { it.symbolProvider.getPackage(FqName(qualifiedName)) != null }) return null
return PsiPackageImpl(psiManager, qualifiedName)
@@ -91,8 +98,7 @@ class FirJavaElementFinder(
val classId = ClassId.topLevel(topLevelClass)
// 1. We could be asked to find class of kind "...MainKt" that was created from file "main.kt"
val firFile = firProviders.firstNotNullOfOrNull { it.getFirFilesByPackage(classId.packageFqName) }
?.singleOrNull { classId.relativeClassName.asString() == it.name.removeSuffix(".kt").capitalizeAsciiOnly() + "Kt" }
val firFile = fileCache.getValue(classId.packageFqName)[classId.relativeClassName.asString()]?.singleOrNull()
if (firFile != null) {
val fileStub = createJavaFileStub(classId.packageFqName, psiManager)
return buildFileAsClassStub(firFile, classId, fileStub).psi
@@ -112,6 +118,13 @@ class FirJavaElementFinder(
return null
}
private fun FirFile.jvmName(): String {
val jvmNameAnnotation = this.findJvmNameAnnotation()
val jvmName = jvmNameAnnotation?.findArgumentByName(StandardNames.NAME)
val jvmNameValue = (jvmName as? FirConstExpression<*>)?.value as? String
return jvmNameValue ?: (this.name.removeSuffix(".kt").capitalizeAsciiOnly() + "Kt")
}
private fun buildFileAsClassStub(firFile: FirFile, classId: ClassId, parent: StubElement<*>): PsiClassStub<*> {
val stub = PsiClassStubImpl<ClsClassImpl>(
JavaStubElementTypes.CLASS, parent, classId.asSingleFqName().asString(), classId.relativeClassName.asString(), null,
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.java
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
@@ -21,7 +22,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.expectedConeType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.RXJAVA3_ANNOTATIONS
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
@@ -142,3 +142,12 @@ fun FirProperty.hasJvmFieldAnnotation(session: FirSession): Boolean =
fun FirAnnotation.isJvmFieldAnnotation(session: FirSession): Boolean =
toAnnotationClassId(session) == JvmStandardClassIds.Annotations.JvmField
fun FirDeclaration.findJvmNameAnnotation(): FirAnnotation? {
return annotations.firstOrNull {
// Access to type must be through `coneTypeOrNull`.
// Even if `JvmName` is in the list of annotations that must be resoled for compilation, we still could try to access some user
// annotations that could be not resolved.
it.annotationTypeRef.coneTypeOrNull?.classId == JvmStandardClassIds.Annotations.JvmName
}
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// WITH_STDLIB
// FILE: Bar.java
package one.two;
public class Bar {
public static final int BAR = OtherKt.FOO + 1;
}
// FILE: Main.kt
@file:JvmName(<!EVALUATED("OtherKt")!>"OtherKt"<!>)
package one.two
const val FOO = <!EVALUATED("1")!>1<!>
const val BAZ = <!EVALUATED("3")!>Bar.BAR + 1<!>
fun box(): String {
return "OK"
}
@@ -27839,6 +27839,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@Test
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
@Test
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
@@ -29261,6 +29261,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@Test
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
@Test
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -29261,6 +29261,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@Test
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
@Test
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
@@ -24708,6 +24708,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConst.kt");
}
@TestMetadata("accessTopLevelConstWithCustomFileName.kt")
public void testAccessTopLevelConstWithCustomFileName() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld/accessTopLevelConstWithCustomFileName.kt");
}
public void testAllFilesPresentInConstEvaluationFromJavaWorld() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/constEvaluationFromJavaWorld"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}