From ad3ae0ff690e0729c22f9cc1ff816dd35ac1c2bb Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 1 Feb 2023 12:46:57 +0200 Subject: [PATCH] [FIR] Add ability to specify that diagnostic collector should visit nodes with specific fake kind --- .../FirProjectionRelationChecker.kt | 1 + .../AbstractDiagnosticCollectorVisitor.kt | 6 ++--- .../org/jetbrains/kotlin/KtSourceElement.kt | 23 +++++++++++-------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt index d7ba928590a..f244278612c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt @@ -44,6 +44,7 @@ object FirProjectionRelationChecker : FirBasicDeclarationChecker() { context: CheckerContext, reporter: DiagnosticReporter ) { + if (typeRef.source?.kind?.shouldSkipErrorTypeReporting != false) return val type = typeRef.coneTypeSafe() val fullyExpandedType = type?.fullyExpandedType(context.session) ?: return val declaration = fullyExpandedType.toSymbol(context.session) as? FirRegularClassSymbol ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt index ee75c1c8548..b4e46dc5797 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt @@ -182,7 +182,7 @@ abstract class AbstractDiagnosticCollectorVisitor( } override fun visitTypeRef(typeRef: FirTypeRef, data: Nothing?) { - if (typeRef.source != null && typeRef.source?.kind !is KtFakeSourceElementKind) { + if (typeRef.source?.kind?.shouldSkipErrorTypeReporting == false) { withTypeRefAnnotationContainer(typeRef) { checkElement(typeRef) visitNestedElements(typeRef) @@ -200,9 +200,9 @@ abstract class AbstractDiagnosticCollectorVisitor( // collected twice: once through resolvedTypeRef's children and another through resolvedTypeRef.delegatedTypeRef's children. val resolvedTypeRefType = resolvedTypeRef.type if (resolvedTypeRefType is ConeErrorType) { - super.visitResolvedTypeRef(resolvedTypeRef, data) + visitTypeRef(resolvedTypeRef, data) } - if (resolvedTypeRef.source?.kind is KtFakeSourceElementKind) return + if (resolvedTypeRef.source?.kind?.shouldSkipErrorTypeReporting != false) return // Even though we don't visit the children of the resolvedTypeRef we still add it as an annotation container // and take care not to add the corresponding delegatedTypeRef. This is so that diagnostics will have access to diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt index 410c5b024f7..4977a93c6d0 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt @@ -15,15 +15,20 @@ import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.tree.IElementType import com.intellij.util.diff.FlyweightCapableTreeStructure -sealed class KtSourceElementKind +sealed class KtSourceElementKind { + abstract val shouldSkipErrorTypeReporting: Boolean +} -object KtRealSourceElementKind : KtSourceElementKind() +object KtRealSourceElementKind : KtSourceElementKind() { + override val shouldSkipErrorTypeReporting: Boolean + get() = false +} -sealed class KtFakeSourceElementKind : KtSourceElementKind() { +sealed class KtFakeSourceElementKind(final override val shouldSkipErrorTypeReporting: Boolean = false) : KtSourceElementKind() { // for some fir expression implicit return typeRef is generated // some of them are: break, continue, return, throw, string concat, // destruction parameters, function literals, explicitly boolean expressions - object ImplicitTypeRef : KtFakeSourceElementKind() + object ImplicitTypeRef : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true) // for each class special class self type ref is created // and have a fake source referencing it @@ -35,7 +40,7 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // for properties without accessors default getter & setter are generated // they have a fake source which refers to property - object DefaultAccessor : KtFakeSourceElementKind() + object DefaultAccessor : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true) // for delegated properties, getter & setter calls to the delegate // they have a fake source which refers to the call that creates the delegate @@ -107,7 +112,7 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // for primary constructor parameter the corresponding class property is generated // with a fake sources which refers to this the corresponding parameter - object PropertyFromParameter : KtFakeSourceElementKind() + object PropertyFromParameter : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true) // if (true) 1 --> if(true) { 1 } // with a fake sources for the block which refers to the wrapped expression @@ -132,7 +137,7 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // for data classes fir generates componentN() & copy() functions // for componentN() functions the source will refer to the corresponding param and will be marked as a fake one // for copy() functions the source will refer class to the param and will be marked as a fake one - object DataClassGeneratedMembers : KtFakeSourceElementKind() + object DataClassGeneratedMembers : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true) // (vararg x: Int) --> (x: Array) where array type ref has a fake source kind object ArrayTypeFromVarargParameter : KtFakeSourceElementKind() @@ -143,7 +148,7 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // when smart casts applied to the expression, it is wrapped into FirSmartCastExpression // which type reference will have a fake source refer to a original source element of it - object SmartCastedTypeRef : KtFakeSourceElementKind() + object SmartCastedTypeRef : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true) // when smart casts applied to the expression, it is wrapped into FirSmartCastExpression // this kind used for such FirSmartCastExpressions itself @@ -181,7 +186,7 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // Consider `super.foo()`. The source PSI `Supertype` is referenced by both the qualified access expression // `super` and the calleeExpression `super`. To avoid having two FIR elements sharing the same source, this fake // source is assigned to the qualified access expression. - object SuperCallExplicitType : KtFakeSourceElementKind() + object SuperCallExplicitType : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true) // fun foo(vararg args: Int) {} // fun bar(1, 2, 3) --> [resolved] fun bar(VarargArgument(1, 2, 3))