[FIR] Add diagnostic collector component that collects diagnostics from error nodes
This commit is contained in:
+4
-4
@@ -15,22 +15,22 @@ class ConeDiagnostic(
|
||||
val source: FirSourceElement
|
||||
)
|
||||
|
||||
inline fun <reified E : PsiElement> DiagnosticFactory0<E>.on(source: FirSourceElement): ConeDiagnostic? {
|
||||
inline fun <reified E : PsiElement> DiagnosticFactory0<E>.onSource(source: FirSourceElement): ConeDiagnostic? {
|
||||
val psi = source.psi as? E ?: return null
|
||||
return ConeDiagnostic(this.on(psi), source)
|
||||
}
|
||||
|
||||
inline fun <reified E : PsiElement, A> DiagnosticFactory1<E, A>.on(source: FirSourceElement, a: A): ConeDiagnostic? {
|
||||
inline fun <reified E : PsiElement, A> DiagnosticFactory1<E, A>.onSource(source: FirSourceElement, a: A): ConeDiagnostic? {
|
||||
val psi = source.psi as? E ?: return null
|
||||
return ConeDiagnostic(this.on(psi, a), source)
|
||||
}
|
||||
|
||||
inline fun <reified E : PsiElement, A, B> DiagnosticFactory2<E, A, B>.on(source: FirSourceElement, a: A, b: B): ConeDiagnostic? {
|
||||
inline fun <reified E : PsiElement, A, B> DiagnosticFactory2<E, A, B>.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 <reified E : PsiElement, A, B, C> DiagnosticFactory3<E, A, B, C>.on(source: FirSourceElement, a: A, b: B, c: C): ConeDiagnostic? {
|
||||
inline fun <reified E : PsiElement, A, B, C> DiagnosticFactory3<E, A, B, C>.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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class FirUnresolvedNameError(val name: Name) : FirDiagnostic() {
|
||||
}
|
||||
|
||||
class FirInapplicableCandidateError(val applicability: CandidateApplicability, val candidates: Collection<AbstractFirBasedSymbol<*>>) : 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<AbstractFirBasedSymbol<*>>) : FirDiagnostic() {
|
||||
|
||||
@@ -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<KtElement, String?>(ERROR)
|
||||
val INAPPLICABLE_CANDIDATE = DiagnosticFactory1.create<KtElement, Collection<AbstractFirBasedSymbol<*>>>(ERROR)
|
||||
val AMBIGUITY = DiagnosticFactory1.create<KtElement, Collection<AbstractFirBasedSymbol<*>>>(ERROR)
|
||||
val ASSIGN_OPERATOR_AMBIGUITY = DiagnosticFactory1.create<KtElement, Collection<AbstractFirBasedSymbol<*>>>(ERROR)
|
||||
val SYNTAX_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val UNRESOLVED_LABEL = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val ILLEGAL_CONST_EXPRESSION = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val DESERIALIZATION_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val INFERENCE_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val NO_SUPERTYPE = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val TYPE_PARAMETER_AS_SUPERTYPE = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val ENUM_AS_SUPERTYPE = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val RECURSION_IN_SUPERTYPES = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val RECURSION_IN_IMPLICIT_TYPES = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val ERROR_FROM_JAVA_RESOLUTION = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val OTHER_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
|
||||
init {
|
||||
val klass = FirErrors::class
|
||||
for (property in klass.memberProperties) {
|
||||
val factory = property.get(this) as? DiagnosticFactory<*> ?: continue
|
||||
factory.name = property.name
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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<FirMemberDeclaration>() {
|
||||
override fun check(declaration: FirMemberDeclaration, reporter: DiagnosticReporter) {
|
||||
@@ -27,6 +27,6 @@ object FirInfixFunctionDeclarationChecker : FirDeclarationChecker<FirMemberDecla
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let { report(Errors.INAPPLICABLE_INFIX_MODIFIER.on(it, "Inapplicable infix modifier")) }
|
||||
source?.let { report(Errors.INAPPLICABLE_INFIX_MODIFIER.onSource(it, "Inapplicable infix modifier")) }
|
||||
}
|
||||
}
|
||||
+8
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.components.AbstractDiagnosticCollectorComponent
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.components.DeclarationCheckersDiagnosticComponent
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.components.ErrorNodeDiagnosticCollectorComponent
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
|
||||
abstract class AbstractDiagnosticCollector {
|
||||
@@ -52,3 +54,9 @@ abstract class AbstractDiagnosticCollector {
|
||||
}
|
||||
}
|
||||
|
||||
fun AbstractDiagnosticCollector.registerAllComponents() {
|
||||
initializeComponents(
|
||||
DeclarationCheckersDiagnosticComponent(this),
|
||||
ErrorNodeDiagnosticCollectorComponent(this)
|
||||
)
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.fir.resolve.diagnostics.collectors.components
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
|
||||
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitErrorLoop(errorLoop: FirErrorLoop) {
|
||||
val source = errorLoop.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorLoop.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef) {
|
||||
val source = errorTypeRef.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorTypeRef.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference) {
|
||||
val source = errorNamedReference.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorNamedReference.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorExpression(errorExpression: FirErrorExpression) {
|
||||
val source = errorExpression.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorExpression.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorFunction(errorFunction: FirErrorFunction) {
|
||||
val source = errorFunction.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorFunction.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
private fun reportFirDiagnostic(diagnostic: FirDiagnostic, source: FirSourceElement, reporter: DiagnosticReporter) {
|
||||
val coneDiagnostic = when (diagnostic) {
|
||||
is FirUnresolvedReferenceError -> 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<PsiElement> {
|
||||
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<PsiElement>
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@ public class DiagnosticFactory0<E extends PsiElement> extends DiagnosticFactoryW
|
||||
super(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement> DiagnosticFactory0<T> create(Severity severity) {
|
||||
return create(severity, PositioningStrategies.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement> DiagnosticFactory0<T> create(Severity severity, PositioningStrategy<? super T> positioningStrategy) {
|
||||
return new DiagnosticFactory0<>(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@@ -29,10 +29,12 @@ public class DiagnosticFactory1<E extends PsiElement, A> extends DiagnosticFacto
|
||||
super(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement, A> DiagnosticFactory1<T, A> create(Severity severity, PositioningStrategy<? super T> positioningStrategy) {
|
||||
return new DiagnosticFactory1<>(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement, A> DiagnosticFactory1<T, A> create(Severity severity) {
|
||||
return create(severity, PositioningStrategies.DEFAULT);
|
||||
}
|
||||
|
||||
@@ -30,10 +30,12 @@ public class DiagnosticFactory2<E extends PsiElement, A, B> extends DiagnosticFa
|
||||
super(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement, A, B> DiagnosticFactory2<T, A, B> create(Severity severity, PositioningStrategy<? super T> positioningStrategy) {
|
||||
return new DiagnosticFactory2<>(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement, A, B> DiagnosticFactory2<T, A, B> create(Severity severity) {
|
||||
return new DiagnosticFactory2<>(severity, PositioningStrategies.DEFAULT);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@ public class DiagnosticFactory3<E extends PsiElement, A, B, C> extends Diagnosti
|
||||
super(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement, A, B, C> DiagnosticFactory3<T, A, B, C> create(Severity severity) {
|
||||
return create(severity, PositioningStrategies.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement, A, B, C> DiagnosticFactory3<T, A, B, C> create(Severity severity, PositioningStrategy<? super T> positioningStrategy) {
|
||||
return new DiagnosticFactory3<>(severity, positioningStrategy);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user