From 6134c0069866727eb0250face9c6227fefd144dd Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Wed, 10 Mar 2021 16:03:02 -0800 Subject: [PATCH] FIR: track KtSuperTypeCallEntry in FirDelegatedConstructorCall In PSI world, a call to super type constructor is represented by a KtSuperTypeCallEntry. Currently FIR tracks the callee reference to this constructor call. This is undesirable because 1. We may want to report issues on the call arguments, so FIR must track the entire call rather than just the callee reference 2. Light tree actually reports the KtSuperTypeCallEntry. 3. Both the FirDelegatedConstructorCall and its `calleeReference` are currently referencing the same KtConstructorCalleeExpression PSI element as the source. This change makes FirDelegatedConstructorCall track the entire KtSuperTypeCallEntry as the source, if possible. --- .../LightTreePositioningStrategies.kt | 2 +- .../kotlin/fir/builder/RawFirBuilder.kt | 4 +- .../RawFirBuilderTotalKotlinTestCase.kt | 91 ++++++++++--------- .../diagnostics/PositioningStrategies.kt | 1 + 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index 50ae701a137..a0286a9e52b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -386,7 +386,7 @@ object LightTreePositioningStrategies { when (selector.tokenType) { KtNodeTypes.REFERENCE_EXPRESSION -> return markElement(selector, startOffset, endOffset, tree, node) - KtNodeTypes.CALL_EXPRESSION, KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL -> + KtNodeTypes.CALL_EXPRESSION, KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL, KtNodeTypes.SUPER_TYPE_CALL_ENTRY -> return markElement(tree.referenceExpression(selector) ?: selector, startOffset, endOffset, tree, node) } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index fcbf9768f0b..1560101ec87 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -625,11 +625,11 @@ open class RawFirBuilder( ownerTypeParameters: List, body: FirBlock? = null ): FirConstructor { - val constructorCallee = superTypeCallEntry?.calleeExpression?.toFirSourceElement() + val constructorCall = superTypeCallEntry?.toFirSourceElement() val constructorSource = this?.toFirSourceElement() ?: owner.toFirPsiSourceElement(FirFakeSourceElementKind.ImplicitConstructor) val firDelegatedCall = buildDelegatedConstructorCall { - source = constructorCallee ?: constructorSource.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall) + source = constructorCall ?: constructorSource.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall) constructedTypeRef = delegatedSuperTypeRef.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef) isThis = false if (!stubMode) { diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt index 618031b5cbf..2e55039f36a 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt @@ -237,51 +237,7 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { } }) psiSetDirect -= psiSetViaFir - psiSetDirect.removeIf { - it is KtPackageDirective || it is KtImportList || it is KtClassBody || - it is KtModifierList || - it is KtUserType || it is KtNullableType || it is KtFunctionType || it is KtFunctionTypeReceiver || - it is KtQualifiedExpression || - it is KtPropertyDelegate || - it is KtConstructorCalleeExpression && it.parent is KtAnnotationEntry || - it is KtValueArgumentList || it is KtParameterList || it is KtTypeParameterList || it is KtTypeArgumentList || - it is KtTypeReference && it.parent.parent.parent is KtCallExpression || - it is KtSuperTypeList || it is KtSuperTypeListEntry || - it is KtValueArgument || it is KtLambdaArgument || it is KtValueArgumentName || - it is KtContainerNodeForControlStructureBody || it is KtContainerNode || - it is KtStringTemplateEntry || - it is KtOperationReferenceExpression || - it is KtLabelReferenceExpression || - it is KtConstructorDelegationReferenceExpression || - it is KtParenthesizedExpression || - it is KtLabeledExpression || - it is KtAnnotatedExpression || - it is KtWhenConditionWithExpression || - it is KtFinallySection || - it is KtObjectLiteralExpression || - // TODO: KT-24089 (support of dynamic) - it is KtDynamicType || - // NB: KtAnnotation is processed via its KtAnnotationEntries - it is KtFileAnnotationList || it is KtAnnotationUseSiteTarget || it is KtAnnotation || - it is KtInitializerList || it is KtEnumEntrySuperclassReferenceExpression || - it is KtLambdaExpression || - it is KtTypeConstraintList || - it is KtTypeConstraint || - it is KtStringTemplateExpression && it.entries.size <= 1 || - it is KtDestructuringDeclaration && it.parent is KtParameter || - it is KtArrayAccessExpression && it.parent is KtBinaryExpression || - it is KtCallExpression && it.parent is KtQualifiedExpression || - it is KtNameReferenceExpression && - (it.parent is KtUserType || it.parent is KtInstanceExpressionWithLabel || - it.parent is KtValueArgumentName || it.parent is KtTypeConstraint) || - it.getStrictParentOfType() != null || - it.getStrictParentOfType() != null || - (it is KtPropertyAccessor && !it.hasBody()) || - it is KtDestructuringDeclarationEntry && it.text == "_" || - it is KtConstantExpression && it.parent.let { parent -> - parent is KtPrefixExpression && (parent.operationToken == KtTokens.MINUS || parent.operationToken == KtTokens.PLUS) - } - } + psiSetDirect.removeIf(::isKnownToBeNotTraversedByFirTree) if (psiSetDirect.isNotEmpty()) { println("Total of $counter files processed successfully") println("FILE ${file.toRelativeString(root)} has not traversed PSI elements (total of ${psiSetDirect.size})!") @@ -298,4 +254,49 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { counter++ } } + + private fun isKnownToBeNotTraversedByFirTree(it: KtElement): Boolean { + return it is KtPackageDirective || it is KtImportList || it is KtClassBody || + it is KtModifierList || + it is KtUserType || it is KtNullableType || it is KtFunctionType || it is KtFunctionTypeReceiver || + it is KtQualifiedExpression || + it is KtPropertyDelegate || + it is KtConstructorCalleeExpression && (it.parent is KtAnnotationEntry || it.parent is KtSuperTypeCallEntry) || + it is KtValueArgumentList || it is KtParameterList || it is KtTypeParameterList || it is KtTypeArgumentList || + it is KtTypeReference && it.parent.parent.parent is KtCallExpression || + it is KtSuperTypeList || (it is KtSuperTypeListEntry && it !is KtSuperTypeCallEntry) || + it is KtValueArgument || it is KtLambdaArgument || it is KtValueArgumentName || + it is KtContainerNodeForControlStructureBody || it is KtContainerNode || + it is KtStringTemplateEntry || + it is KtOperationReferenceExpression || + it is KtLabelReferenceExpression || + it is KtConstructorDelegationReferenceExpression || + it is KtParenthesizedExpression || + it is KtLabeledExpression || + it is KtAnnotatedExpression || + it is KtWhenConditionWithExpression || + it is KtFinallySection || + it is KtObjectLiteralExpression ||// TODO: KT-24089 (support of dynamic) + it is KtDynamicType || + // NB: KtAnnotation is processed via its KtAnnotationEntries + it is KtFileAnnotationList || it is KtAnnotationUseSiteTarget || it is KtAnnotation || + it is KtInitializerList || it is KtEnumEntrySuperclassReferenceExpression || + it is KtLambdaExpression || + it is KtTypeConstraintList || + it is KtTypeConstraint || + it is KtStringTemplateExpression && it.entries.size <= 1 || + it is KtDestructuringDeclaration && it.parent is KtParameter || + it is KtArrayAccessExpression && it.parent is KtBinaryExpression || + it is KtCallExpression && it.parent is KtQualifiedExpression || + it is KtNameReferenceExpression && + (it.parent is KtUserType || it.parent is KtInstanceExpressionWithLabel || + it.parent is KtValueArgumentName || it.parent is KtTypeConstraint) || + it.getStrictParentOfType() != null || + it.getStrictParentOfType() != null || + (it is KtPropertyAccessor && !it.hasBody()) || + it is KtDestructuringDeclarationEntry && it.text == "_" || + it is KtConstantExpression && it.parent.let { parent -> + parent is KtPrefixExpression && (parent.operationToken == KtTokens.MINUS || parent.operationToken == KtTokens.PLUS) + } + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index b0595fb0c79..8a3112afedd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -755,6 +755,7 @@ object PositioningStrategies { } is KtCallExpression -> return mark(element.calleeExpression ?: element) is KtConstructorDelegationCall -> return mark(element.calleeExpression ?: element) + is KtSuperTypeCallEntry -> return mark(element.calleeExpression) } return super.mark(element) }