From 38bb9f78d647aa42651a06fba28bf64797e6378a Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 31 Oct 2019 14:36:01 +0300 Subject: [PATCH] [FIR] Add diagnostic collector component that collects diagnostics from error nodes --- .../fir/resolve/diagnostics/ConeDiagnostic.kt | 8 +- .../fir/resolve/diagnostics/FirDiagnostics.kt | 2 +- .../fir/resolve/diagnostics/FirErrors.kt | 38 +++++++++ .../FirInfixFunctionDeclarationChecker.kt | 4 +- .../collectors/AbstractDiagnosticCollector.kt | 8 ++ .../ErrorNodeDiagnosticCollectorComponent.kt | 82 +++++++++++++++++++ ...stractFirResolveWithDiagnosticsTestCase.kt | 3 +- .../diagnostics/DiagnosticFactory0.java | 2 + .../diagnostics/DiagnosticFactory1.java | 2 + .../diagnostics/DiagnosticFactory2.java | 2 + .../diagnostics/DiagnosticFactory3.java | 2 + 11 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirErrors.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostic.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostic.kt index 25ec0bd88ce..19ac1fc3f20 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostic.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostic.kt @@ -15,22 +15,22 @@ class ConeDiagnostic( val source: FirSourceElement ) -inline fun DiagnosticFactory0.on(source: FirSourceElement): ConeDiagnostic? { +inline fun DiagnosticFactory0.onSource(source: FirSourceElement): ConeDiagnostic? { val psi = source.psi as? E ?: return null return ConeDiagnostic(this.on(psi), source) } -inline fun DiagnosticFactory1.on(source: FirSourceElement, a: A): ConeDiagnostic? { +inline fun DiagnosticFactory1.onSource(source: FirSourceElement, a: A): ConeDiagnostic? { val psi = source.psi as? E ?: return null return ConeDiagnostic(this.on(psi, a), source) } -inline fun DiagnosticFactory2.on(source: FirSourceElement, a: A, b: B): ConeDiagnostic? { +inline fun DiagnosticFactory2.onSource(source: FirSourceElement, a: A, b: B): ConeDiagnostic? { val psi = source.psi as? E ?: return null return ConeDiagnostic(this.on(psi, a, b), source) } -inline fun DiagnosticFactory3.on(source: FirSourceElement, a: A, b: B, c: C): ConeDiagnostic? { +inline fun DiagnosticFactory3.onSource(source: FirSourceElement, a: A, b: B, c: C): ConeDiagnostic? { val psi = source.psi as? E ?: return null return ConeDiagnostic(this.on(psi, a, b, c), source) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt index a9dc7cefd58..510f3bbf04a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt @@ -26,7 +26,7 @@ class FirUnresolvedNameError(val name: Name) : FirDiagnostic() { } class FirInapplicableCandidateError(val applicability: CandidateApplicability, val candidates: Collection>) : FirDiagnostic() { - override val reason: String get() = "Inapplicable($applicability): $candidates" + override val reason: String get() = "Inapplicable($applicability): ${candidates.map { describeSymbol(it) }}" } class FirAmbiguityError(val name: Name, val candidates: Collection>) : FirDiagnostic() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirErrors.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirErrors.kt new file mode 100644 index 00000000000..8e11b7830a3 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirErrors.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2019 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.diagnostics + +import org.jetbrains.kotlin.diagnostics.Severity.* +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.psi.KtElement +import kotlin.reflect.full.memberProperties + +object FirErrors { + val UNRESOLVED_REFERENCE = DiagnosticFactory1.create(ERROR) + val INAPPLICABLE_CANDIDATE = DiagnosticFactory1.create>>(ERROR) + val AMBIGUITY = DiagnosticFactory1.create>>(ERROR) + val ASSIGN_OPERATOR_AMBIGUITY = DiagnosticFactory1.create>>(ERROR) + val SYNTAX_ERROR = DiagnosticFactory0.create(ERROR) + val UNRESOLVED_LABEL = DiagnosticFactory0.create(ERROR) + val ILLEGAL_CONST_EXPRESSION = DiagnosticFactory0.create(ERROR) + val DESERIALIZATION_ERROR = DiagnosticFactory0.create(ERROR) + val INFERENCE_ERROR = DiagnosticFactory0.create(ERROR) + val NO_SUPERTYPE = DiagnosticFactory0.create(ERROR) + val TYPE_PARAMETER_AS_SUPERTYPE = DiagnosticFactory0.create(ERROR) + val ENUM_AS_SUPERTYPE = DiagnosticFactory0.create(ERROR) + val RECURSION_IN_SUPERTYPES = DiagnosticFactory0.create(ERROR) + val RECURSION_IN_IMPLICIT_TYPES = DiagnosticFactory0.create(ERROR) + val ERROR_FROM_JAVA_RESOLUTION = DiagnosticFactory0.create(ERROR) + val OTHER_ERROR = DiagnosticFactory0.create(ERROR) + + init { + val klass = FirErrors::class + for (property in klass.memberProperties) { + val factory = property.get(this) as? DiagnosticFactory<*> ?: continue + factory.name = property.name + } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/checkers/declaration/FirInfixFunctionDeclarationChecker.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/checkers/declaration/FirInfixFunctionDeclarationChecker.kt index dd8b4919d65..24a8f119ff5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/checkers/declaration/FirInfixFunctionDeclarationChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/checkers/declaration/FirInfixFunctionDeclarationChecker.kt @@ -10,8 +10,8 @@ import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.isInfix -import org.jetbrains.kotlin.fir.resolve.diagnostics.on import org.jetbrains.kotlin.fir.resolve.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.resolve.diagnostics.onSource object FirInfixFunctionDeclarationChecker : FirDeclarationChecker() { override fun check(declaration: FirMemberDeclaration, reporter: DiagnosticReporter) { @@ -27,6 +27,6 @@ object FirInfixFunctionDeclarationChecker : FirDeclarationChecker FirErrors.UNRESOLVED_REFERENCE.onSource(source, diagnostic.name?.asString()) + is FirUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.onSource(source, diagnostic.classId.asString()) + is FirUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.onSource(source, diagnostic.name.asString()) + is FirInapplicableCandidateError -> FirErrors.INAPPLICABLE_CANDIDATE.onSource(source, diagnostic.candidates) + is FirAmbiguityError -> FirErrors.AMBIGUITY.onSource(source, diagnostic.candidates) + is FirOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.onSource(source, diagnostic.candidates) + is FirSimpleDiagnostic -> diagnostic.getFactory().onSource(source) + else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}") + } + reporter.report(coneDiagnostic) + } + + private fun FirSimpleDiagnostic.getFactory(): DiagnosticFactory0 { + return when (kind) { + DiagnosticKind.Syntax -> FirErrors.SYNTAX_ERROR + DiagnosticKind.ReturnNotAllowed -> Errors.RETURN_NOT_ALLOWED + DiagnosticKind.UnresolvedLabel -> FirErrors.UNRESOLVED_LABEL + DiagnosticKind.IllegalConstExpression -> FirErrors.ILLEGAL_CONST_EXPRESSION + DiagnosticKind.ConstructorInObject -> Errors.CONSTRUCTOR_IN_OBJECT + DiagnosticKind.DeserializationError -> FirErrors.DESERIALIZATION_ERROR + DiagnosticKind.InferenceError -> FirErrors.INFERENCE_ERROR + DiagnosticKind.NoSupertype -> FirErrors.NO_SUPERTYPE + DiagnosticKind.TypeParameterAsSupertype -> FirErrors.TYPE_PARAMETER_AS_SUPERTYPE + DiagnosticKind.EnumAsSupertype -> FirErrors.ENUM_AS_SUPERTYPE + DiagnosticKind.RecursionInSupertypes -> FirErrors.RECURSION_IN_SUPERTYPES + DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES + DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION + DiagnosticKind.Other -> FirErrors.OTHER_ERROR + } as DiagnosticFactory0 + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithDiagnosticsTestCase.kt b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithDiagnosticsTestCase.kt index 13943b9531d..1d7cfabaac2 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithDiagnosticsTestCase.kt +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithDiagnosticsTestCase.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.AbstractDiagnosticCollector import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.ParallelDiagnosticsCollector import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.components.DeclarationCheckersDiagnosticComponent +import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.registerAllComponents import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.KotlinTestUtils @@ -38,7 +39,7 @@ abstract class AbstractFirResolveWithDiagnosticsTestCase : AbstractFirResolveTes private fun createCollector(): AbstractDiagnosticCollector { // val collector = SimpleDiagnosticsCollector() val collector = ParallelDiagnosticsCollector(4) - collector.initializeComponents(DeclarationCheckersDiagnosticComponent(collector)) + collector.registerAllComponents() return collector } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory0.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory0.java index 5b2771e38d6..0bc56efeec1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory0.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory0.java @@ -25,10 +25,12 @@ public class DiagnosticFactory0 extends DiagnosticFactoryW super(severity, positioningStrategy); } + @NotNull public static DiagnosticFactory0 create(Severity severity) { return create(severity, PositioningStrategies.DEFAULT); } + @NotNull public static DiagnosticFactory0 create(Severity severity, PositioningStrategy positioningStrategy) { return new DiagnosticFactory0<>(severity, positioningStrategy); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory1.java index 59dac2b1b81..3bdd1d8ef8e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory1.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory1.java @@ -29,10 +29,12 @@ public class DiagnosticFactory1 extends DiagnosticFacto super(severity, positioningStrategy); } + @NotNull public static DiagnosticFactory1 create(Severity severity, PositioningStrategy positioningStrategy) { return new DiagnosticFactory1<>(severity, positioningStrategy); } + @NotNull public static DiagnosticFactory1 create(Severity severity) { return create(severity, PositioningStrategies.DEFAULT); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory2.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory2.java index df67b0eeb08..ebad40a0b8a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory2.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory2.java @@ -30,10 +30,12 @@ public class DiagnosticFactory2 extends DiagnosticFa super(severity, positioningStrategy); } + @NotNull public static DiagnosticFactory2 create(Severity severity, PositioningStrategy positioningStrategy) { return new DiagnosticFactory2<>(severity, positioningStrategy); } + @NotNull public static DiagnosticFactory2 create(Severity severity) { return new DiagnosticFactory2<>(severity, PositioningStrategies.DEFAULT); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory3.java index ae87aba7a3d..0d337928add 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory3.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/DiagnosticFactory3.java @@ -25,10 +25,12 @@ public class DiagnosticFactory3 extends Diagnosti super(severity, positioningStrategy); } + @NotNull public static DiagnosticFactory3 create(Severity severity) { return create(severity, PositioningStrategies.DEFAULT); } + @NotNull public static DiagnosticFactory3 create(Severity severity, PositioningStrategy positioningStrategy) { return new DiagnosticFactory3<>(severity, positioningStrategy); }