[LL FIR] FileStructure: process annotations from constructors correctly

^KT-56543
This commit is contained in:
Dmitrii Gridin
2023-04-05 18:52:18 +02:00
committed by Space Team
parent 71f48ede53
commit 8387ea8a39
27 changed files with 309 additions and 30 deletions
@@ -81,8 +81,9 @@ internal class FirElementBuilder(
val firFile = element.containingKtFile
val fileStructure = moduleComponents.fileStructureCache.getFileStructure(firFile)
val mappings = fileStructure.getStructureElementFor(element).mappings
val structureElement = fileStructure.getStructureElementFor(element)
val psi = getPsiAsFirElementSource(element) ?: return null
val mappings = structureElement.mappings
return mappings.getFirOfClosestParent(psi, firResolveSession)
?: firResolveSession.getOrBuildFirFile(firFile)
}
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import java.util.concurrent.ConcurrentHashMap
import org.jetbrains.kotlin.fir.correspondingProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
internal class FileStructure private constructor(
private val ktFile: KtFile,
@@ -69,10 +71,6 @@ internal class FileStructure private constructor(
container is KtClassOrObject && container.isInsideSuperClassCall(element) -> {
container.primaryConstructor?.let { return it }
}
container is KtPrimaryConstructor && container.isInsideAnnotationOnParameter(element) -> {
container.containingClassOrObject?.let { return it }
}
}
return container
@@ -86,30 +84,6 @@ internal class FileStructure private constructor(
return false
}
private fun KtPrimaryConstructor.isInsideAnnotationOnParameter(element: KtElement): Boolean {
for (parameter in valueParameters) {
for (annotation in parameter.annotationEntries) {
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue
when (target) {
AnnotationUseSiteTarget.FIELD,
AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.PROPERTY_GETTER,
AnnotationUseSiteTarget.PROPERTY_SETTER,
AnnotationUseSiteTarget.SETTER_PARAMETER -> {
if (annotation.isAncestor(element)) return true
}
AnnotationUseSiteTarget.FILE,
AnnotationUseSiteTarget.RECEIVER,
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER,
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> {
}
}
}
}
return false
}
private fun getStructureElementForDeclaration(declaration: KtElement): FileStructureElement {
@Suppress("CANNOT_CHECK_FOR_ERASED")
val structureElement = structureElements.compute(declaration) { _, structureElement ->
@@ -178,6 +152,12 @@ internal class FileStructure private constructor(
)
firDeclaration.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
if (firDeclaration is FirPrimaryConstructor) {
firDeclaration.valueParameters.forEach { parameter ->
parameter.correspondingProperty?.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
}
}
return FileElementFactory.createFileStructureElement(
firDeclaration = firDeclaration,
ktDeclaration = declaration,
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.psi.*
import java.util.concurrent.ConcurrentHashMap
import org.jetbrains.kotlin.fir.correspondingProperty
internal sealed class FileStructureElement(val firFile: FirFile, protected val moduleComponents: LLFirModuleResolveComponents) {
abstract val psi: KtAnnotated
@@ -276,7 +277,19 @@ internal class NonReanalyzableNonClassDeclarationStructureElement(
moduleComponents,
)
internal object Recorder : FirElementsRecorder()
internal object Recorder : FirElementsRecorder() {
override fun visitConstructor(constructor: FirConstructor, data: MutableMap<KtElement, FirElement>) {
if (constructor is FirPrimaryConstructor) {
constructor.valueParameters.forEach { parameter ->
parameter.correspondingProperty?.let { property ->
visitProperty(property, data)
}
}
}
super.visitConstructor(constructor, data)
}
}
}
internal class DanglingTopLevelModifierListStructureElement(
@@ -0,0 +1,5 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
class Abc(<expr>@Anno</expr> var i: Int) {
}
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@<ERROR TYPE REF: Symbol not found for Anno>[Types]()
@@ -0,0 +1,3 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
fun <reified T : Number> String.collectOfType(i: Int): Sequence<<expr>@kotlin.internal.NoInfer</expr> T> = 4
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@<ERROR TYPE REF: Symbol not found for kotlin.internal.NoInfer>[Types]()
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@<ERROR TYPE REF: HIDDEN: kotlin/internal/NoInfer is invisible>[Unresolved]()
@@ -0,0 +1,11 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
// WITH_STDLIB
class MyClass(
<expr>@JvmField</expr>
var addCommaWarning: Boolean = false
) : A() {
}
open class A
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@<ERROR TYPE REF: Symbol not found for JvmField>[Types]()
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|kotlin/jvm/JvmField|[Types]()
@@ -0,0 +1,12 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
class ResolveMe(
addCommaWarning: <expr>@Anno</expr> Boolean = false
) : A() {
}
open class A
@Target(AnnotationTarget.TYPE)
annotation class Anno
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|Anno|[Types]()
@@ -0,0 +1,12 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
class ResolveMe(
var addCommaWarning: <expr>@Anno</expr> Boolean = false,
) : A() {
}
open class A
@Target(AnnotationTarget.TYPE)
annotation class Anno
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|Anno|[Types]()
@@ -0,0 +1,13 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
class ResolveMe(
var addCommaWarning: <expr>@Anno</expr> Boolean = false,
second: @Anno Boolean = false,
) : A() {
}
open class A
@Target(AnnotationTarget.TYPE)
annotation class Anno
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|Anno|[Types]()
@@ -0,0 +1,12 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
class ResolveMe(
var addCommaWarning: <expr>@Anno("abc")</expr> Boolean = false,
) : A() {
}
open class A
@Target(AnnotationTarget.TYPE)
annotation class Anno(val value: String)
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|Anno|[Types](value = String(abc))
@@ -0,0 +1,10 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
fun t(addCommaWarning: <expr>@Anno</expr> Boolean) {
}
open class A
@Target(AnnotationTarget.TYPE)
annotation class Anno
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|Anno|[Types]()
@@ -0,0 +1,10 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
fun t(addCommaWarning: <expr>@Anno("abcd")</expr> Boolean) {
}
open class A
@Target(AnnotationTarget.TYPE)
annotation class Anno(val value: String)
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|Anno|[Types](value = String(abcd))
@@ -0,0 +1,5 @@
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtParameter
class Abc(<expr>val i: Int = 4</expr>) {
}
@@ -0,0 +1,6 @@
KT element: KtParameter
FIR element: FirValueParameterImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
[ResolvedTo(BODY_RESOLVE)] i: R|kotlin/Int| = Int(4)
@@ -69,6 +69,18 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationApplicationWithArgumentsOnCallSite.kt");
}
@Test
@TestMetadata("annotationOnConstructorProperty.kt")
public void testAnnotationOnConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationOnConstructorProperty.kt");
}
@Test
@TestMetadata("annotationOnReturnType.kt")
public void testAnnotationOnReturnType() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationOnReturnType.kt");
}
@Test
@TestMetadata("danglingAnnotation.kt")
public void testDanglingAnnotation() throws Exception {
@@ -87,6 +99,12 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/fileAnnotation.kt");
}
@Test
@TestMetadata("jvmFieldAnnotationOnConstructorProperty.kt")
public void testJvmFieldAnnotationOnConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/jvmFieldAnnotationOnConstructorProperty.kt");
}
@Test
@TestMetadata("retentionValue.kt")
public void testRetentionValue() throws Exception {
@@ -105,6 +123,42 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/superCallAnnotation2.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorParameter.kt")
public void testTypeOnAnnotationOnConstructorParameter() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorParameter.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorProperty.kt")
public void testTypeOnAnnotationOnConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorProperty.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorPropertyAndParameter.kt")
public void testTypeOnAnnotationOnConstructorPropertyAndParameter() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorPropertyAndParameter.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorPropertyWithArguments.kt")
public void testTypeOnAnnotationOnConstructorPropertyWithArguments() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorPropertyWithArguments.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnFunctionParameter.kt")
public void testTypeOnAnnotationOnFunctionParameter() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnFunctionParameter.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnFunctionParameterWithArguments.kt")
public void testTypeOnAnnotationOnFunctionParameterWithArguments() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnFunctionParameterWithArguments.kt");
}
@Nested
@TestMetadata("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/useSite")
@TestDataPath("$PROJECT_ROOT")
@@ -375,6 +429,12 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("constructorProperty.kt")
public void testConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/constructorProperty.kt");
}
@Test
@TestMetadata("destructuring.kt")
public void testDestructuring() throws Exception {
@@ -69,6 +69,18 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationApplicationWithArgumentsOnCallSite.kt");
}
@Test
@TestMetadata("annotationOnConstructorProperty.kt")
public void testAnnotationOnConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationOnConstructorProperty.kt");
}
@Test
@TestMetadata("annotationOnReturnType.kt")
public void testAnnotationOnReturnType() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationOnReturnType.kt");
}
@Test
@TestMetadata("danglingAnnotation.kt")
public void testDanglingAnnotation() throws Exception {
@@ -87,6 +99,12 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/fileAnnotation.kt");
}
@Test
@TestMetadata("jvmFieldAnnotationOnConstructorProperty.kt")
public void testJvmFieldAnnotationOnConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/jvmFieldAnnotationOnConstructorProperty.kt");
}
@Test
@TestMetadata("retentionValue.kt")
public void testRetentionValue() throws Exception {
@@ -105,6 +123,42 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/superCallAnnotation2.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorParameter.kt")
public void testTypeOnAnnotationOnConstructorParameter() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorParameter.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorProperty.kt")
public void testTypeOnAnnotationOnConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorProperty.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorPropertyAndParameter.kt")
public void testTypeOnAnnotationOnConstructorPropertyAndParameter() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorPropertyAndParameter.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnConstructorPropertyWithArguments.kt")
public void testTypeOnAnnotationOnConstructorPropertyWithArguments() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnConstructorPropertyWithArguments.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnFunctionParameter.kt")
public void testTypeOnAnnotationOnFunctionParameter() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnFunctionParameter.kt");
}
@Test
@TestMetadata("typeOnAnnotationOnFunctionParameterWithArguments.kt")
public void testTypeOnAnnotationOnFunctionParameterWithArguments() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/typeOnAnnotationOnFunctionParameterWithArguments.kt");
}
@Nested
@TestMetadata("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/useSite")
@TestDataPath("$PROJECT_ROOT")
@@ -375,6 +429,12 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("constructorProperty.kt")
public void testConstructorProperty() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/constructorProperty.kt");
}
@Test
@TestMetadata("destructuring.kt")
public void testDestructuring() throws Exception {