diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt index b9ae5e81991..9c11c5b0ec3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt @@ -20,9 +20,10 @@ abstract class DiagnosticReporter { fun

DiagnosticReporter.reportOn( source: FirSourceElement?, factory: FirDiagnosticFactory0

, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { - source?.let { report(factory.on(it), context) } + source?.let { report(factory.on(it, positioningStrategy), context) } } @OptIn(InternalDiagnosticFactoryMethod::class) @@ -30,9 +31,10 @@ fun

DiagnosticReporter.reportOn( source: FirSourceElement?, factory: FirDiagnosticFactory1, a: A, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { - source?.let { report(factory.on(it, a), context) } + source?.let { report(factory.on(it, a, positioningStrategy), context) } } @OptIn(InternalDiagnosticFactoryMethod::class) @@ -41,9 +43,10 @@ fun

DiagnosticReporter.reportOn( factory: FirDiagnosticFactory2, a: A, b: B, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { - source?.let { report(factory.on(it, a, b), context) } + source?.let { report(factory.on(it, a, b, positioningStrategy), context) } } @OptIn(InternalDiagnosticFactoryMethod::class) @@ -53,9 +56,10 @@ fun

DiagnosticReporter.reportOn( a: A, b: B, c: C, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { - source?.let { report(factory.on(it, a, b, c), context) } + source?.let { report(factory.on(it, a, b, c, positioningStrategy), context) } } @OptIn(InternalDiagnosticFactoryMethod::class) @@ -66,9 +70,10 @@ fun

DiagnosticReporter.repo b: B, c: C, d: D, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { - source?.let { report(factory.on(it, a, b, c, d), context) } + source?.let { report(factory.on(it, a, b, c, d, positioningStrategy), context) } } inline fun withSuppressedDiagnostics( @@ -94,10 +99,11 @@ inline fun withSuppressedDiagnostics( fun

DiagnosticReporter.reportOnWithSuppression( element: FirElement, factory: FirDiagnosticFactory0

, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { withSuppressedDiagnostics(element, context) { - reportOn(element.source, factory, it) + reportOn(element.source, factory, it, positioningStrategy) } } @@ -105,10 +111,11 @@ fun

DiagnosticReporter.reportOnWithSuppression( element: FirElement, factory: FirDiagnosticFactory1, a: A, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { withSuppressedDiagnostics(element, context) { - reportOn(element.source, factory, a, it) + reportOn(element.source, factory, a, it, positioningStrategy) } } @@ -117,10 +124,11 @@ fun

DiagnosticReporter.reportOnWithSuppressio factory: FirDiagnosticFactory2, a: A, b: B, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { withSuppressedDiagnostics(element, context) { - reportOn(element.source, factory, a, b, it) + reportOn(element.source, factory, a, b, it, positioningStrategy) } } @@ -130,10 +138,11 @@ fun

DiagnosticReporter.reportOnWithS a: A, b: B, c: C, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { withSuppressedDiagnostics(element, context) { - reportOn(element.source, factory, a, b, c, it) + reportOn(element.source, factory, a, b, c, it, positioningStrategy) } } @@ -144,10 +153,11 @@ fun

DiagnosticReporter.repo b: B, c: C, d: D, - context: CheckerContext + context: CheckerContext, + positioningStrategy: SourceElementPositioningStrategy

? = null ) { withSuppressedDiagnostics(element, context) { - reportOn(element.source, factory, a, b, c, d, it) + reportOn(element.source, factory, a, b, c, d, it, positioningStrategy) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt index 728335ae7ec..e0efef3834b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt @@ -21,12 +21,13 @@ sealed class FirDiagnostic : UnboundDiagnostic { abstract val element: E abstract override val severity: Severity abstract override val factory: AbstractFirDiagnosticFactory<*, *> + abstract val positioningStrategy: SourceElementPositioningStrategy<*> override val textRanges: List - get() = factory.getTextRanges(this) + get() = positioningStrategy.markDiagnostic(this) override val isValid: Boolean - get() = factory.isValid(this) + get() = positioningStrategy.isValid(element) } sealed class FirSimpleDiagnostic : FirDiagnostic() { @@ -74,14 +75,16 @@ interface FirPsiDiagnostic

: Diagnostic { data class FirPsiSimpleDiagnostic

( override val element: FirPsiSourceElement

, override val severity: Severity, - override val factory: FirDiagnosticFactory0

+ override val factory: FirDiagnosticFactory0

, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirSimpleDiagnostic>(), FirPsiDiagnostic

data class FirPsiDiagnosticWithParameters1

( override val element: FirPsiSourceElement

, override val a: A, override val severity: Severity, - override val factory: FirDiagnosticFactory1 + override val factory: FirDiagnosticFactory1, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters1, A>(), FirPsiDiagnostic

data class FirPsiDiagnosticWithParameters2

( @@ -89,7 +92,8 @@ data class FirPsiDiagnosticWithParameters2

( override val a: A, override val b: B, override val severity: Severity, - override val factory: FirDiagnosticFactory2 + override val factory: FirDiagnosticFactory2, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters2, A, B>(), FirPsiDiagnostic

data class FirPsiDiagnosticWithParameters3

( @@ -98,7 +102,8 @@ data class FirPsiDiagnosticWithParameters3

( override val b: B, override val c: C, override val severity: Severity, - override val factory: FirDiagnosticFactory3 + override val factory: FirDiagnosticFactory3, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters3, A, B, C>(), FirPsiDiagnostic

data class FirPsiDiagnosticWithParameters4

( @@ -108,7 +113,8 @@ data class FirPsiDiagnosticWithParameters4

( override val c: C, override val d: D, override val severity: Severity, - override val factory: FirDiagnosticFactory4 + override val factory: FirDiagnosticFactory4, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters4, A, B, C, D>(), FirPsiDiagnostic

// ------------------------------ light tree diagnostics ------------------------------ @@ -120,14 +126,16 @@ interface FirLightDiagnostic : UnboundDiagnostic { data class FirLightSimpleDiagnostic( override val element: FirLightSourceElement, override val severity: Severity, - override val factory: FirDiagnosticFactory0<*> + override val factory: FirDiagnosticFactory0<*>, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirSimpleDiagnostic(), FirLightDiagnostic data class FirLightDiagnosticWithParameters1( override val element: FirLightSourceElement, override val a: A, override val severity: Severity, - override val factory: FirDiagnosticFactory1<*, A> + override val factory: FirDiagnosticFactory1<*, A>, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters1(), FirLightDiagnostic data class FirLightDiagnosticWithParameters2( @@ -135,7 +143,8 @@ data class FirLightDiagnosticWithParameters2( override val a: A, override val b: B, override val severity: Severity, - override val factory: FirDiagnosticFactory2<*, A, B> + override val factory: FirDiagnosticFactory2<*, A, B>, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters2(), FirLightDiagnostic data class FirLightDiagnosticWithParameters3( @@ -144,7 +153,8 @@ data class FirLightDiagnosticWithParameters3( override val b: B, override val c: C, override val severity: Severity, - override val factory: FirDiagnosticFactory3<*, A, B, C> + override val factory: FirDiagnosticFactory3<*, A, B, C>, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters3(), FirLightDiagnostic data class FirLightDiagnosticWithParameters4( @@ -154,5 +164,6 @@ data class FirLightDiagnosticWithParameters4( override val c: C, override val d: D, override val severity: Severity, - override val factory: FirDiagnosticFactory4<*, A, B, C, D> + override val factory: FirDiagnosticFactory4<*, A, B, C, D>, + override val positioningStrategy: SourceElementPositioningStrategy<*> ) : FirDiagnosticWithParameters4(), FirLightDiagnostic diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt index 693522b3dab..0ebdd8edb9c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics -import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Severity @@ -22,7 +21,7 @@ annotation class InternalDiagnosticFactoryMethod sealed class AbstractFirDiagnosticFactory, P : PsiElement>( override val name: String, override val severity: Severity, - val positioningStrategy: SourceElementPositioningStrategy

, + val defaultPositioningStrategy: SourceElementPositioningStrategy

, ) : DiagnosticFactory(name, severity) { abstract val firRenderer: FirDiagnosticRenderer @@ -30,30 +29,25 @@ sealed class AbstractFirDiagnosticFactory, P : PsiElement>( get() = firRenderer set(_) { } - - fun getTextRanges(diagnostic: FirDiagnostic<*>): List = - positioningStrategy.markDiagnostic(diagnostic) - - fun isValid(diagnostic: FirDiagnostic<*>): Boolean { - val element = diagnostic.element - return positioningStrategy.isValid(element) - } } class FirDiagnosticFactory0

( name: String, severity: Severity, - positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, -) : AbstractFirDiagnosticFactory, P>(name, severity, positioningStrategy) { + defaultPositioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, +) : AbstractFirDiagnosticFactory, P>(name, severity, defaultPositioningStrategy) { override val firRenderer: FirDiagnosticRenderer> = SimpleFirDiagnosticRenderer("") @InternalDiagnosticFactoryMethod - fun on(element: FirSourceElement): FirSimpleDiagnostic<*> { + fun on( + element: FirSourceElement, + positioningStrategy: SourceElementPositioningStrategy

? + ): FirSimpleDiagnostic<*> { return when (element) { is FirPsiSourceElement<*> -> FirPsiSimpleDiagnostic( - element as FirPsiSourceElement

, severity, this + element as FirPsiSourceElement

, severity, this, positioningStrategy ?: defaultPositioningStrategy ) - is FirLightSourceElement -> FirLightSimpleDiagnostic(element, severity, this) + is FirLightSourceElement -> FirLightSimpleDiagnostic(element, severity, this, positioningStrategy ?: defaultPositioningStrategy) else -> incorrectElement(element) } } @@ -62,20 +56,30 @@ class FirDiagnosticFactory0

( class FirDiagnosticFactory1

( name: String, severity: Severity, - positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, -) : AbstractFirDiagnosticFactory, P>(name, severity, positioningStrategy) { + defaultPositioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, +) : AbstractFirDiagnosticFactory, P>(name, severity, defaultPositioningStrategy) { override val firRenderer: FirDiagnosticRenderer> = FirDiagnosticWithParameters1Renderer( "{0}", FirDiagnosticRenderers.TO_STRING ) @InternalDiagnosticFactoryMethod - fun on(element: FirSourceElement, a: A): FirDiagnosticWithParameters1<*, A> { + fun on( + element: FirSourceElement, + a: A, + positioningStrategy: SourceElementPositioningStrategy

? + ): FirDiagnosticWithParameters1<*, A> { return when (element) { is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters1( - element as FirPsiSourceElement

, a, severity, this + element as FirPsiSourceElement

, a, severity, this, positioningStrategy ?: defaultPositioningStrategy + ) + is FirLightSourceElement -> FirLightDiagnosticWithParameters1( + element, + a, + severity, + this, + positioningStrategy ?: defaultPositioningStrategy ) - is FirLightSourceElement -> FirLightDiagnosticWithParameters1(element, a, severity, this) else -> incorrectElement(element) } } @@ -84,8 +88,8 @@ class FirDiagnosticFactory1

( class FirDiagnosticFactory2

( name: String, severity: Severity, - positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, -) : AbstractFirDiagnosticFactory, P>(name, severity, positioningStrategy) { + defaultPositioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, +) : AbstractFirDiagnosticFactory, P>(name, severity, defaultPositioningStrategy) { override val firRenderer: FirDiagnosticRenderer> = FirDiagnosticWithParameters2Renderer( "{0}, {1}", FirDiagnosticRenderers.TO_STRING, @@ -93,12 +97,24 @@ class FirDiagnosticFactory2

( ) @InternalDiagnosticFactoryMethod - fun on(element: FirSourceElement, a: A, b: B): FirDiagnosticWithParameters2<*, A, B> { + fun on( + element: FirSourceElement, + a: A, + b: B, + positioningStrategy: SourceElementPositioningStrategy

? + ): FirDiagnosticWithParameters2<*, A, B> { return when (element) { is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters2( - element as FirPsiSourceElement

, a, b, severity, this + element as FirPsiSourceElement

, a, b, severity, this, positioningStrategy ?: defaultPositioningStrategy + ) + is FirLightSourceElement -> FirLightDiagnosticWithParameters2( + element, + a, + b, + severity, + this, + positioningStrategy ?: defaultPositioningStrategy ) - is FirLightSourceElement -> FirLightDiagnosticWithParameters2(element, a, b, severity, this) else -> incorrectElement(element) } } @@ -107,8 +123,8 @@ class FirDiagnosticFactory2

( class FirDiagnosticFactory3

( name: String, severity: Severity, - positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, -) : AbstractFirDiagnosticFactory, P>(name, severity, positioningStrategy) { + defaultPositioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, +) : AbstractFirDiagnosticFactory, P>(name, severity, defaultPositioningStrategy) { override val firRenderer: FirDiagnosticRenderer> = FirDiagnosticWithParameters3Renderer( "{0}, {1}, {2}", FirDiagnosticRenderers.TO_STRING, @@ -117,12 +133,26 @@ class FirDiagnosticFactory3

( ) @InternalDiagnosticFactoryMethod - fun on(element: FirSourceElement, a: A, b: B, c: C): FirDiagnosticWithParameters3<*, A, B, C> { + fun on( + element: FirSourceElement, + a: A, + b: B, + c: C, + positioningStrategy: SourceElementPositioningStrategy

? + ): FirDiagnosticWithParameters3<*, A, B, C> { return when (element) { is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters3( - element as FirPsiSourceElement

, a, b, c, severity, this + element as FirPsiSourceElement

, a, b, c, severity, this, positioningStrategy ?: defaultPositioningStrategy + ) + is FirLightSourceElement -> FirLightDiagnosticWithParameters3( + element, + a, + b, + c, + severity, + this, + positioningStrategy ?: defaultPositioningStrategy ) - is FirLightSourceElement -> FirLightDiagnosticWithParameters3(element, a, b, c, severity, this) else -> incorrectElement(element) } } @@ -131,8 +161,8 @@ class FirDiagnosticFactory3

( class FirDiagnosticFactory4

( name: String, severity: Severity, - positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, -) : AbstractFirDiagnosticFactory, P>(name, severity, positioningStrategy) { + defaultPositioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, +) : AbstractFirDiagnosticFactory, P>(name, severity, defaultPositioningStrategy) { override val firRenderer: FirDiagnosticRenderer> = FirDiagnosticWithParameters4Renderer( "{0}, {1}, {2}, {3}", FirDiagnosticRenderers.TO_STRING, @@ -142,12 +172,28 @@ class FirDiagnosticFactory4

( ) @InternalDiagnosticFactoryMethod - fun on(element: FirSourceElement, a: A, b: B, c: C, d: D): FirDiagnosticWithParameters4<*, A, B, C, D> { + fun on( + element: FirSourceElement, + a: A, + b: B, + c: C, + d: D, + positioningStrategy: SourceElementPositioningStrategy

? + ): FirDiagnosticWithParameters4<*, A, B, C, D> { return when (element) { is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters4( - element as FirPsiSourceElement

, a, b, c, d, severity, this + element as FirPsiSourceElement

, a, b, c, d, severity, this, positioningStrategy ?: defaultPositioningStrategy + ) + is FirLightSourceElement -> FirLightDiagnosticWithParameters4( + element, + a, + b, + c, + d, + severity, + this, + positioningStrategy ?: defaultPositioningStrategy ) - is FirLightSourceElement -> FirLightDiagnosticWithParameters4(element, a, b, c, d, severity, this) else -> incorrectElement(element) } } @@ -156,45 +202,3 @@ class FirDiagnosticFactory4

( private fun incorrectElement(element: FirSourceElement): Nothing { throw IllegalArgumentException("Unknown element type: ${element::class}") } - -@InternalDiagnosticFactoryMethod -fun

FirDiagnosticFactory0

.on(element: FirSourceElement?): FirSimpleDiagnostic<*>? { - return element?.let { on(it) } -} - -@InternalDiagnosticFactoryMethod -fun

FirDiagnosticFactory1.on( - element: FirSourceElement?, a: A -): FirDiagnosticWithParameters1<*, A>? { - return element?.let { on(it, a) } -} - -@InternalDiagnosticFactoryMethod -fun

FirDiagnosticFactory2.on( - element: FirSourceElement?, - a: A, - b: B -): FirDiagnosticWithParameters2<*, A, B>? { - return element?.let { on(it, a, b) } -} - -@InternalDiagnosticFactoryMethod -fun

FirDiagnosticFactory3.on( - element: FirSourceElement?, - a: A, - b: B, - c: C -): FirDiagnosticWithParameters3<*, A, B, C>? { - return element?.let { on(it, a, b, c) } -} - -@InternalDiagnosticFactoryMethod -fun

FirDiagnosticFactory4.on( - element: FirSourceElement?, - a: A, - b: B, - c: C, - d: D -): FirDiagnosticWithParameters4<*, A, B, C, D>? { - return element?.let { on(it, a, b, c, d) } -} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index b2fff2217db..3662734482c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirSourceElement @@ -32,58 +33,58 @@ import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.jetbrains.kotlin.utils.addToStdlib.safeAs -@OptIn(InternalDiagnosticFactoryMethod::class) private fun ConeDiagnostic.toFirDiagnostic( source: FirSourceElement, qualifiedAccessSource: FirSourceElement? ): FirDiagnostic? = when (this) { - is ConeUnresolvedReferenceError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.name?.asString() ?: "") - is ConeUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.classId.asString()) - is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.name.asString()) - is ConeUnresolvedQualifierError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.qualifier) - is ConeHiddenCandidateError -> FirErrors.INVISIBLE_REFERENCE.on(source, this.candidateSymbol) - is ConeAmbiguityError -> if (this.applicability.isSuccess) { - FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.on(source, this.candidates.map { it.symbol }) - } else if (this.applicability == CandidateApplicability.UNSAFE_CALL) { - val candidate = candidates.first { it.currentApplicability == CandidateApplicability.UNSAFE_CALL } - val unsafeCall = candidate.diagnostics.firstIsInstance() - mapUnsafeCallError(candidate, unsafeCall, source, qualifiedAccessSource) - } else if (this.applicability == CandidateApplicability.UNSTABLE_SMARTCAST) { - val unstableSmartcast = - this.candidates.first { it.currentApplicability == CandidateApplicability.UNSTABLE_SMARTCAST }.diagnostics.firstIsInstance() - FirErrors.SMARTCAST_IMPOSSIBLE.on( - unstableSmartcast.argument.source, - unstableSmartcast.targetType, - unstableSmartcast.argument, - unstableSmartcast.argument.smartcastStability.description - ) - } else { - FirErrors.NONE_APPLICABLE.on(source, this.candidates.map { it.symbol }) + is ConeUnresolvedReferenceError -> FirErrors.UNRESOLVED_REFERENCE.createOn(source, this.name?.asString() ?: "") + is ConeUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.createOn(source, this.classId.asString()) + is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.createOn(source, this.name.asString()) + is ConeUnresolvedQualifierError -> FirErrors.UNRESOLVED_REFERENCE.createOn(source, this.qualifier) + is ConeHiddenCandidateError -> FirErrors.INVISIBLE_REFERENCE.createOn(source, this.candidateSymbol) + is ConeAmbiguityError -> when { + applicability.isSuccess -> FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.createOn(source, this.candidates.map { it.symbol }) + applicability == CandidateApplicability.UNSAFE_CALL -> { + val candidate = candidates.first { it.currentApplicability == CandidateApplicability.UNSAFE_CALL } + val unsafeCall = candidate.diagnostics.firstIsInstance() + mapUnsafeCallError(candidate, unsafeCall, source, qualifiedAccessSource) + } + applicability == CandidateApplicability.UNSTABLE_SMARTCAST -> { + val unstableSmartcast = + this.candidates.first { it.currentApplicability == CandidateApplicability.UNSTABLE_SMARTCAST }.diagnostics.firstIsInstance() + FirErrors.SMARTCAST_IMPOSSIBLE.createOn( + unstableSmartcast.argument.source, + unstableSmartcast.targetType, + unstableSmartcast.argument, + unstableSmartcast.argument.smartcastStability.description + ) + } + else -> FirErrors.NONE_APPLICABLE.createOn(source, this.candidates.map { it.symbol }) } - is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.on(source, this.candidates) - is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.on(source) + is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidates) + is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.createOn(source) is ConeValReassignmentError -> when (val symbol = this.variable) { - is FirBackingFieldSymbol -> FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR.on(source, symbol.fir.symbol) - else -> FirErrors.VAL_REASSIGNMENT.on(source, symbol) + is FirBackingFieldSymbol -> FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR.createOn(source, symbol.fir.symbol) + else -> FirErrors.VAL_REASSIGNMENT.createOn(source, symbol) } - is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.on(this.source.safeAs() ?: source) - is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.on(source, this.name.asString()) + is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source.safeAs() ?: source) + is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString()) is ConeWrongNumberOfTypeArgumentsError -> - FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) + FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.type) is ConeNoTypeArgumentsOnRhsError -> - FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) + FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.type) is ConeSimpleDiagnostic -> when (source.kind) { is FirFakeSourceElementKind -> null - else -> this.getFactory(source).on(qualifiedAccessSource ?: source) + else -> this.getFactory(source).createOn(qualifiedAccessSource ?: source) } - is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target) + is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.createOn(source, this.target) is ConeStubDiagnostic -> null is ConeIntermediateDiagnostic -> null - is ConeContractDescriptionError -> FirErrors.ERROR_IN_CONTRACT_DESCRIPTION.on(source, this.reason) - is ConeTypeParameterSupertype -> FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE.on(source, this.reason) + is ConeContractDescriptionError -> FirErrors.ERROR_IN_CONTRACT_DESCRIPTION.createOn(source, this.reason) + is ConeTypeParameterSupertype -> FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE.createOn(source, this.reason) is ConeTypeParameterInQualifiedAccess -> null // reported in various checkers instead is ConeNotAnnotationContainer -> null - is ConeImportFromSingleton -> FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.on(source, this.name) + is ConeImportFromSingleton -> FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.createOn(source, this.name) else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}") } @@ -98,15 +99,14 @@ fun ConeDiagnostic.toFirDiagnostics( } } -@OptIn(InternalDiagnosticFactoryMethod::class) private fun mapUnsafeCallError( candidate: Candidate, rootCause: UnsafeCall, source: FirSourceElement, qualifiedAccessSource: FirSourceElement?, -): FirDiagnostic<*> { +): FirDiagnostic<*>? { if (candidate.callInfo.isImplicitInvoke) { - return FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL.on(source, rootCause.actualType) + return FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL.createOn(source, rootCause.actualType) } val candidateFunction = candidate.symbol.fir as? FirSimpleFunction @@ -126,14 +126,14 @@ private fun mapUnsafeCallError( source } return if (operationSource?.getChild(KtTokens.IDENTIFIER) != null) { - FirErrors.UNSAFE_INFIX_CALL.on( + FirErrors.UNSAFE_INFIX_CALL.createOn( source, receiverExpression, candidateFunctionName!!.asString(), singleArgument, ) } else { - FirErrors.UNSAFE_OPERATOR_CALL.on( + FirErrors.UNSAFE_OPERATOR_CALL.createOn( source, receiverExpression, candidateFunctionName!!.asString(), @@ -142,51 +142,50 @@ private fun mapUnsafeCallError( } } return if (source.kind == FirFakeSourceElementKind.ArrayAccessNameReference) { - FirErrors.UNSAFE_CALL.on(source, rootCause.actualType, receiverExpression) + FirErrors.UNSAFE_CALL.createOn(source, rootCause.actualType, receiverExpression) } else { - FirErrors.UNSAFE_CALL.on(qualifiedAccessSource ?: source, rootCause.actualType, receiverExpression) + FirErrors.UNSAFE_CALL.createOn(qualifiedAccessSource ?: source, rootCause.actualType, receiverExpression) } } -@OptIn(InternalDiagnosticFactoryMethod::class) private fun mapInapplicableCandidateError( diagnostic: ConeInapplicableCandidateError, source: FirSourceElement, qualifiedAccessSource: FirSourceElement?, ): List> { - val genericDiagnostic = FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol) + val genericDiagnostic = FirErrors.INAPPLICABLE_CANDIDATE.createOn(source, diagnostic.candidate.symbol) val diagnostics = diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause -> when (rootCause) { - is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on( + is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.createOn( rootCause.argument.source ?: qualifiedAccessSource ) - is NamedArgumentNotAllowed -> FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED.on( + is NamedArgumentNotAllowed -> FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED.createOn( rootCause.argument.source, rootCause.forbiddenNamedArgumentsTarget ) - is ArgumentTypeMismatch -> FirErrors.ARGUMENT_TYPE_MISMATCH.on( + is ArgumentTypeMismatch -> FirErrors.ARGUMENT_TYPE_MISMATCH.createOn( rootCause.argument.source ?: source, rootCause.expectedType, rootCause.actualType, rootCause.isMismatchDueToNullability ) - is NullForNotNullType -> FirErrors.NULL_FOR_NONNULL_TYPE.on( + is NullForNotNullType -> FirErrors.NULL_FOR_NONNULL_TYPE.createOn( rootCause.argument.source ?: source ) - is NonVarargSpread -> FirErrors.NON_VARARG_SPREAD.on(rootCause.argument.source?.getChild(KtTokens.MUL, depth = 1)!!) - is ArgumentPassedTwice -> FirErrors.ARGUMENT_PASSED_TWICE.on(rootCause.argument.source) - is TooManyArguments -> FirErrors.TOO_MANY_ARGUMENTS.on(rootCause.argument.source ?: source, rootCause.function) - is NoValueForParameter -> FirErrors.NO_VALUE_FOR_PARAMETER.on(qualifiedAccessSource ?: source, rootCause.valueParameter) - is NameNotFound -> FirErrors.NAMED_PARAMETER_NOT_FOUND.on( + is NonVarargSpread -> FirErrors.NON_VARARG_SPREAD.createOn(rootCause.argument.source?.getChild(KtTokens.MUL, depth = 1)!!) + is ArgumentPassedTwice -> FirErrors.ARGUMENT_PASSED_TWICE.createOn(rootCause.argument.source) + is TooManyArguments -> FirErrors.TOO_MANY_ARGUMENTS.createOn(rootCause.argument.source ?: source, rootCause.function) + is NoValueForParameter -> FirErrors.NO_VALUE_FOR_PARAMETER.createOn(qualifiedAccessSource ?: source, rootCause.valueParameter) + is NameNotFound -> FirErrors.NAMED_PARAMETER_NOT_FOUND.createOn( rootCause.argument.source ?: source, rootCause.argument.name.asString() ) is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource) - is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(rootCause.argument.source ?: source) - is InfixCallOfNonInfixFunction -> FirErrors.INFIX_MODIFIER_REQUIRED.on(source, rootCause.function) + is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.createOn(rootCause.argument.source ?: source) + is InfixCallOfNonInfixFunction -> FirErrors.INFIX_MODIFIER_REQUIRED.createOn(source, rootCause.function) is OperatorCallOfNonOperatorFunction -> - FirErrors.OPERATOR_MODIFIER_REQUIRED.on(source, rootCause.function, rootCause.function.fir.name.asString()) - is UnstableSmartCast -> FirErrors.SMARTCAST_IMPOSSIBLE.on( + FirErrors.OPERATOR_MODIFIER_REQUIRED.createOn(source, rootCause.function, rootCause.function.fir.name.asString()) + is UnstableSmartCast -> FirErrors.SMARTCAST_IMPOSSIBLE.createOn( rootCause.argument.source, rootCause.targetType, rootCause.argument, @@ -203,7 +202,7 @@ private fun mapInapplicableCandidateError( } } -@OptIn(ExperimentalStdlibApi::class, InternalDiagnosticFactoryMethod::class) +@OptIn(ExperimentalStdlibApi::class) private fun mapSystemHasContradictionError( diagnostic: ConeConstraintSystemHasContradiction, source: FirSourceElement, @@ -241,13 +240,12 @@ private fun mapSystemHasContradictionError( if (morePreciseDiagnosticExists) return@firstNotNullOfOrNull null } - FirErrors.NEW_INFERENCE_ERROR.on(qualifiedAccessSource ?: source, message) + FirErrors.NEW_INFERENCE_ERROR.createOn(qualifiedAccessSource ?: source, message) } ) } } -@OptIn(InternalDiagnosticFactoryMethod::class) private fun ConstraintSystemError.toDiagnostic( source: FirSourceElement, qualifiedAccessSource: FirSourceElement?, @@ -267,7 +265,7 @@ private fun ConstraintSystemError.toDiagnostic( } argument?.let { - return FirErrors.ARGUMENT_TYPE_MISMATCH.on( + return FirErrors.ARGUMENT_TYPE_MISMATCH.createOn( it.source ?: source, lowerConeType, upperConeType, @@ -287,13 +285,13 @@ private fun ConstraintSystemError.toDiagnostic( else upperConeType.withNullability(ConeNullability.NULLABLE, typeContext) - FirErrors.TYPE_MISMATCH.on(qualifiedAccessSource ?: source, upperConeType, inferredType) + FirErrors.TYPE_MISMATCH.createOn(qualifiedAccessSource ?: source, upperConeType, inferredType) } is ExplicitTypeParameterConstraintPosition<*> -> { val conePosition = position as ConeExplicitTypeParameterConstraintPosition val typeArgument = conePosition.typeArgument - FirErrors.UPPER_BOUND_VIOLATED.on( + FirErrors.UPPER_BOUND_VIOLATED.createOn( typeArgument.source ?: qualifiedAccessSource ?: source, upperConeType, ) @@ -319,7 +317,7 @@ private fun ConstraintSystemError.toDiagnostic( else -> error("Unsupported type variable: $typeVariable") } - FirErrors.NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on( + FirErrors.NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.createOn( source, typeVariableName, ) @@ -375,3 +373,37 @@ private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagno else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass") } } + +@OptIn(InternalDiagnosticFactoryMethod::class) +private fun

FirDiagnosticFactory0

.createOn( + element: FirSourceElement? +): FirSimpleDiagnostic<*>? { + return element?.let { on(it, positioningStrategy = null) } +} + +@OptIn(InternalDiagnosticFactoryMethod::class) +private fun

FirDiagnosticFactory1.createOn( + element: FirSourceElement?, + a: A +): FirDiagnosticWithParameters1<*, A>? { + return element?.let { on(it, a, positioningStrategy = null) } +} + +@OptIn(InternalDiagnosticFactoryMethod::class) +private fun

FirDiagnosticFactory2.createOn( + element: FirSourceElement?, + a: A, + b: B +): FirDiagnosticWithParameters2<*, A, B>? { + return element?.let { on(it, a, b, positioningStrategy = null) } +} + +@OptIn(InternalDiagnosticFactoryMethod::class) +private fun

FirDiagnosticFactory3.createOn( + element: FirSourceElement?, + a: A, + b: B, + c: C +): FirDiagnosticWithParameters3<*, A, B, C>? { + return element?.let { on(it, a, b, c, positioningStrategy = null) } +} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticCodeMetaInfo.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticCodeMetaInfo.kt index edc03a75d02..f5d9680ea6e 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticCodeMetaInfo.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticCodeMetaInfo.kt @@ -23,7 +23,7 @@ class FirDiagnosticCodeMetaInfo( renderConfiguration: FirDiagnosticCodeMetaRenderConfiguration ) : CodeMetaInfo { private val textRangeFromClassicDiagnostic: TextRange = run { - diagnostic.factory.positioningStrategy.markDiagnostic(diagnostic).first() + diagnostic.factory.defaultPositioningStrategy.markDiagnostic(diagnostic).first() } override var renderConfiguration: FirDiagnosticCodeMetaRenderConfiguration = renderConfiguration diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index 46bf950fe93..c8583cdef39 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -120,11 +120,13 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes ) { val metaInfos = if (firFile.psi != null) { AnalyzingUtils.getSyntaxErrorRanges(firFile.psi!!).map { - FirErrors.SYNTAX.on(FirRealPsiSourceElement(it)).toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled) + FirErrors.SYNTAX.on(FirRealPsiSourceElement(it), positioningStrategy = null) + .toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled) } } else { collectLightTreeSyntaxErrors(firFile).map { sourceElement -> - FirErrors.SYNTAX.on(sourceElement).toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled) + FirErrors.SYNTAX.on(sourceElement, positioningStrategy = null) + .toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled) } } @@ -245,8 +247,20 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes val argumentText = argument() val factory = FirDiagnosticFactory1(name, severity) return when (positionedElement) { - is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters1(positionedElement, argumentText, severity, factory) - is FirLightSourceElement -> FirLightDiagnosticWithParameters1(positionedElement, argumentText, severity, factory) + is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters1( + positionedElement, + argumentText, + severity, + factory, + factory.defaultPositioningStrategy + ) + is FirLightSourceElement -> FirLightDiagnosticWithParameters1( + positionedElement, + argumentText, + severity, + factory, + factory.defaultPositioningStrategy + ) } } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index e580b335600..678588a99d4 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -215,13 +215,15 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { sourceElement, argumentText, severity, - FirDiagnosticFactory1(name, severity) + FirDiagnosticFactory1(name, severity), + SourceElementPositioningStrategy.DEFAULT ) is FirLightSourceElement -> FirLightDiagnosticWithParameters1( sourceElement, argumentText, severity, - FirDiagnosticFactory1(name, severity) + FirDiagnosticFactory1(name, severity), + SourceElementPositioningStrategy.DEFAULT ) } } @@ -276,7 +278,10 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { } private fun createCollector(session: FirSession): AbstractDiagnosticCollector { - return FirDiagnosticsCollector.create(session, ScopeSession()) // seems this class is obsolete, so do not care about correctness of the scope session here + return FirDiagnosticsCollector.create( + session, + ScopeSession() + ) // seems this class is obsolete, so do not care about correctness of the scope session here } private fun checkCfgDump(testDataFile: File, firFiles: List) { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt index 41b62bf311d..c65cf75f0a6 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt @@ -34,36 +34,41 @@ private fun FirLightDiagnostic.toPsiDiagnostic(): FirPsiDiagnostic<*> { is FirLightSimpleDiagnostic -> FirPsiSimpleDiagnostic( psiSourceElement, severity, - factory as FirDiagnosticFactory0 + factory as FirDiagnosticFactory0, + positioningStrategy ) is FirLightDiagnosticWithParameters1<*> -> FirPsiDiagnosticWithParameters1( psiSourceElement, a, severity, - factory as FirDiagnosticFactory1 + factory as FirDiagnosticFactory1, + positioningStrategy ) is FirLightDiagnosticWithParameters2<*, *> -> FirPsiDiagnosticWithParameters2( psiSourceElement, a, b, severity, - factory as FirDiagnosticFactory2 + factory as FirDiagnosticFactory2, + positioningStrategy ) is FirLightDiagnosticWithParameters3<*, *, *> -> FirPsiDiagnosticWithParameters3( psiSourceElement, a, b, c, severity, - factory as FirDiagnosticFactory3 + factory as FirDiagnosticFactory3, + positioningStrategy ) is FirLightDiagnosticWithParameters4<*, *, *, *> -> FirPsiDiagnosticWithParameters4( psiSourceElement, a, b, c, d, severity, - factory as FirDiagnosticFactory4 + factory as FirDiagnosticFactory4, + positioningStrategy ) else -> error("Unknown diagnostic type ${this::class.simpleName}") } -} \ No newline at end of file +}