From d6907222cd83db19a98ac41ecf7efa6cd8cdd8d8 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Sun, 7 Mar 2021 16:10:29 -0800 Subject: [PATCH] FIR: pass the qualified access source when reporting ErrorNamedReference Currently if there is an error in a function call, FIR would report the entire expression if this call is qualified, but *only* the name if it's not qualified. For example, assume the following two calls are all contains some errors. ``` a.foo(1,2,3) ^^^^^^^^^^^^ bar(1,2,3) ^^^ ``` The entire call of `foo` is reported since it's qualified. But only the reference `bar` is reported since it's not qualified. This limits the usage of position strategies because the IDE does not allow position strategies to go outside of the initially reported PSI element (org.jetbrains.kotlin.idea.fir.highlighter.KotlinHighLevelDiagnosticHighlightingPass#addDiagnostic). This change passes both the original error named reference and the surrounding qualified access expression and defer the decision of which to use to the reporting logic. For unresolved reference and checks on `super` keyword, the position strategy should not highlight the surrounding parentheses. Hence a new position strategy `REFERENCED_NAME_BY_QUALIFIED` is added. In addition, this change also has the following side effect * some diagnostics are no longer reported when there is a syntax error since the higher level structure does not exist when there is a syntax error --- .../resolve/arrays/arraySetWithOperation.kt | 4 +- .../testData/resolve/expresssions/access.kt | 2 +- .../expresssions/operators/plusAssign.kt | 2 +- .../visibility/visibilityWithOverrides.kt | 2 +- .../generator/diagnostics/DiagnosticData.kt | 1 + .../diagnostics/FirDiagnosticsList.kt | 12 ++-- .../fir/analysis/diagnostics/FirErrors.kt | 12 ++-- .../ErrorNodeDiagnosticCollectorComponent.kt | 20 +++--- .../LightTreePositioningStrategies.kt | 67 ++++++++++++++++--- .../SourceElementPositioningStrategies.kt | 5 ++ .../coneDiagnosticToFirDiagnostic.kt | 47 ++++++++----- .../kotlin/fir/builder/PsiConversionUtils.kt | 2 +- .../diagnostics/PositioningStrategies.kt | 45 ++++++++++--- .../tests/BinaryCallsOnNullableValues.fir.kt | 2 +- .../tests/FunctionCalleeExpressions.fir.kt | 24 +++---- ...ityResolveWithVarargAndOperatorCall.fir.kt | 4 +- .../namedFunAsLastExpressionInBlock.fir.kt | 2 +- ...onstructorWithDefaultParametersOnly.fir.kt | 2 +- .../throwOutCandidatesByReceiver.fir.kt | 2 +- .../functionLiterals/DeprecatedSyntax.fir.kt | 4 +- .../noTypeParamsInReturnType.fir.kt | 1 - .../tests/incompleteCode/inExpr.fir.kt | 2 +- .../tests/incompleteCode/inExpr.kt | 2 +- .../inner/classesInClassObjectHeader.fir.kt | 2 +- .../diagnostics/tests/inner/modality.fir.kt | 2 +- .../testData/diagnostics/tests/kt435.fir.kt | 4 +- ...recatedModAssignOperatorConventions.fir.kt | 4 +- .../forbiddenModOperatorConvention.fir.kt | 4 +- ...esolveToModWhenNoOperatorRemFeature.fir.kt | 4 +- .../InconsistentGetSet.fir.kt | 7 +- ...assignmentOperationsCheckReturnType.fir.kt | 8 +-- .../plusAssignOnArray.fir.kt | 4 +- .../delegatedProperties.fir.kt | 4 +- .../calleeExpressionAsCallExpression.fir.kt | 2 +- .../receiverPresenceErrorForInvoke.fir.kt | 4 +- .../wrongReceiverForInvokeOnExpression.fir.kt | 10 +-- .../resolve/invoke/invokeAndSmartCast.fir.kt | 4 +- ...OnVariableWithExtensionFunctionType.fir.kt | 10 +-- .../tests/smartCasts/alwaysNull.fir.kt | 2 +- .../traitSupertypeList.fir.kt | 2 +- .../inference/plusAssignWithLambda.fir.kt | 2 +- .../p-1/pos/2.1.fir.kt | 2 +- .../p-1/pos/2.1.fir.kt | 2 +- .../operator-call/p-1/neg/2.4.fir.kt | 8 +-- .../operator-call/p-1/neg/2.5.fir.kt | 4 +- .../operator-call/p-1/neg/2.6.fir.kt | 4 +- .../operator-call/p-1/neg/2.7.fir.kt | 4 +- .../operator-call/p-1/neg/2.8.fir.kt | 8 +-- .../p-17/neg/2.1.fir.kt | 2 +- .../p-17/neg/2.2.fir.kt | 2 +- .../diagnostics/notLinked/dfa/neg/12.fir.kt | 2 +- .../KtFirAnalysisSessionComponent.kt | 4 +- .../api/fir/components/KtFirCallResolver.kt | 15 +++-- 53 files changed, 247 insertions(+), 155 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt index 468f9bcaf2a..2413f4bde3a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt +++ b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt @@ -28,9 +28,9 @@ fun test_2(a: A) { } fun test_3(a: A) { - a[0] += D() // ambiguity + a[0] += D() // ambiguity } fun test_4(b: B) { - b[0] += B() // unresolved + b[0] += B() // unresolved } diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/access.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/access.kt index ead6b21eda9..43487deca83 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/access.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/access.kt @@ -21,7 +21,7 @@ class Bar { } // NB! abc() here is resolved to member Foo.abc(), and not to extension member of Bar - fun Foo.check() = abc() + bar() + fun Foo.check() = abc() + bar() // NB! + here is resolved to member String.plus (not to extension member above) fun Foo.check2() = "" + bar() diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAssign.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAssign.kt index 235e861ef18..0c734abf427 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAssign.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/operators/plusAssign.kt @@ -7,7 +7,7 @@ class Foo { fun test_1() { val f = Foo() - f + f + f + f } fun test_2() { diff --git a/compiler/fir/analysis-tests/testData/resolve/visibility/visibilityWithOverrides.kt b/compiler/fir/analysis-tests/testData/resolve/visibility/visibilityWithOverrides.kt index 768d1052b24..9e5875af43c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/visibility/visibilityWithOverrides.kt +++ b/compiler/fir/analysis-tests/testData/resolve/visibility/visibilityWithOverrides.kt @@ -19,5 +19,5 @@ abstract class A { // FILE: main.kt fun test(b: B): String { - return b foo "hello" // should be an error + return b foo "hello" // should be an error } diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt index c216f004c28..104e5d8cda9 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt @@ -46,6 +46,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { INNER_MODIFIER, SELECTOR_BY_QUALIFIED, REFERENCE_BY_QUALIFIED, + REFERENCED_NAME_BY_QUALIFIED, PRIVATE_MODIFIER, COMPANION_OBJECT, CONST_MODIFIER, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index ba946656f57..effe6b3aba8 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -67,7 +67,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val HIDDEN by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { parameter>("hidden") } - val UNRESOLVED_REFERENCE by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { + val UNRESOLVED_REFERENCE by error(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) { parameter("reference") } val UNRESOLVED_LABEL by error() @@ -79,9 +79,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() { } val SUPER by object : DiagnosticGroup("Super") { - val SUPER_IS_NOT_AN_EXPRESSION by error() - val SUPER_NOT_AVAILABLE by error() - val ABSTRACT_SUPER_CALL by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) + val SUPER_IS_NOT_AN_EXPRESSION by error(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) + val SUPER_NOT_AVAILABLE by error(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) + val ABSTRACT_SUPER_CALL by error(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error { parameter("target") } @@ -497,12 +497,12 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val UNSAFE_IMPLICIT_INVOKE_CALL by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { parameter("receiverType") } - val UNSAFE_INFIX_CALL by error { + val UNSAFE_INFIX_CALL by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { parameter("lhs") parameter("operator") parameter("rhs") } - val UNSAFE_OPERATOR_CALL by error { + val UNSAFE_OPERATOR_CALL by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { parameter("lhs") parameter("operator") parameter("rhs") diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 5a00e77e094..98bb25ede92 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -77,7 +77,7 @@ object FirErrors { // Unresolved val HIDDEN by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val UNRESOLVED_REFERENCE by error1(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) + val UNRESOLVED_REFERENCE by error1(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val UNRESOLVED_LABEL by error0() val DESERIALIZATION_ERROR by error0() val ERROR_FROM_JAVA_RESOLUTION by error0() @@ -86,9 +86,9 @@ object FirErrors { val NO_THIS by error0() // Super - val SUPER_IS_NOT_AN_EXPRESSION by error0() - val SUPER_NOT_AVAILABLE by error0() - val ABSTRACT_SUPER_CALL by error0(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) + val SUPER_IS_NOT_AN_EXPRESSION by error0(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) + val SUPER_NOT_AVAILABLE by error0(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) + val ABSTRACT_SUPER_CALL by error0(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error1() // Supertypes @@ -303,8 +303,8 @@ object FirErrors { // Nullability val UNSAFE_CALL by error1(SourceElementPositioningStrategies.DOT_BY_QUALIFIED) val UNSAFE_IMPLICIT_INVOKE_CALL by error1(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val UNSAFE_INFIX_CALL by error3() - val UNSAFE_OPERATOR_CALL by error3() + val UNSAFE_INFIX_CALL by error3(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) + val UNSAFE_OPERATOR_CALL by error3(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) // When expressions val NO_ELSE_IN_WHEN by error1>(SourceElementPositioningStrategies.WHEN_EXPRESSION) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index 24305e7e4f1..42eaf831712 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -14,9 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic -import org.jetbrains.kotlin.fir.expressions.FirErrorExpression -import org.jetbrains.kotlin.fir.expressions.FirErrorLoop -import org.jetbrains.kotlin.fir.expressions.FirErrorResolvedQualifier +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError @@ -35,15 +33,18 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect } override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) { - val source = data.qualifiedAccesses.lastOrNull()?.source?.takeIf { it.elementType == KtNodeTypes.DOT_QUALIFIED_EXPRESSION } - ?: errorNamedReference.source ?: return + val source = errorNamedReference.source ?: return + val qualifiedAccessSource = data.qualifiedAccesses.lastOrNull()?.takeIf { + // Use the source of the enclosing FirQualifiedAccessExpression if it is exactly the call to the erroneous callee. + it is FirQualifiedAccessExpression && it.calleeReference == errorNamedReference + }?.source // Don't report duplicated unresolved reference on annotation entry (already reported on its type) if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && errorNamedReference.diagnostic is ConeUnresolvedNameError) return // Already reported in FirConventionFunctionCallChecker - if (errorNamedReference.source?.kind == FirFakeSourceElementKind.ArrayAccessNameReference && + if (source.kind == FirFakeSourceElementKind.ArrayAccessNameReference && errorNamedReference.diagnostic is ConeUnresolvedNameError ) return - reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter, data) + reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter, data, qualifiedAccessSource) } override fun visitErrorExpression(errorExpression: FirErrorExpression, data: CheckerContext) { @@ -65,7 +66,8 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect diagnostic: ConeDiagnostic, source: FirSourceElement, reporter: DiagnosticReporter, - context: CheckerContext + context: CheckerContext, + qualifiedAccessSource: FirSourceElement? = null ) { // Will be handled by [FirDestructuringDeclarationChecker] if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY) { @@ -81,7 +83,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect if (source.kind == FirFakeSourceElementKind.ImplicitConstructor) { return } - for (coneDiagnostic in diagnostic.toFirDiagnostics(source)) { + for (coneDiagnostic in diagnostic.toFirDiagnostics(source, qualifiedAccessSource)) { reporter.report(coneDiagnostic, context) } } 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 9c2bb1bcd9e..05021fbd55e 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 @@ -343,10 +343,11 @@ object LightTreePositioningStrategies { endOffset: Int, tree: FlyweightCapableTreeStructure ): List { - if (node.tokenType != KtNodeTypes.DOT_QUALIFIED_EXPRESSION) { - return super.mark(node, startOffset, endOffset, tree) + if (node.tokenType == KtNodeTypes.DOT_QUALIFIED_EXPRESSION) { + return markElement(tree.dotOperator(node) ?: node, startOffset, endOffset, tree, node) } - return markElement(tree.dotOperator(node) ?: node, startOffset, endOffset, tree, node) + // Fallback to mark the callee reference. + return REFERENCE_BY_QUALIFIED.mark(node, startOffset, endOffset, tree) } } @@ -368,7 +369,13 @@ object LightTreePositioningStrategies { } } - val REFERENCE_BY_QUALIFIED: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { + val REFERENCE_BY_QUALIFIED: LightTreePositioningStrategy = FindReferencePositioningStrategy(false) + val REFERENCED_NAME_BY_QUALIFIED: LightTreePositioningStrategy = FindReferencePositioningStrategy(true) + + /** + * @param locateReferencedName see doc on [referenceExpression] + */ + class FindReferencePositioningStrategy(val locateReferencedName: Boolean) : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, startOffset: Int, @@ -376,7 +383,10 @@ object LightTreePositioningStrategies { tree: FlyweightCapableTreeStructure ): List { if (node.tokenType == KtNodeTypes.CALL_EXPRESSION || node.tokenType == KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL) { - return markElement(tree.referenceExpression(node) ?: node, startOffset, endOffset, tree, node) + return markElement(tree.referenceExpression(node, locateReferencedName) ?: node, startOffset, endOffset, tree, node) + } + if (node.tokenType in nodeTypesWithOperation) { + return markElement(tree.operationReference(node) ?: node, startOffset, endOffset, tree, node) } if (node.tokenType != KtNodeTypes.DOT_QUALIFIED_EXPRESSION && node.tokenType != KtNodeTypes.SAFE_ACCESS_EXPRESSION && @@ -389,14 +399,30 @@ object LightTreePositioningStrategies { when (selector.tokenType) { KtNodeTypes.REFERENCE_EXPRESSION -> return markElement(selector, startOffset, endOffset, tree, node) - KtNodeTypes.CALL_EXPRESSION, KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL, KtNodeTypes.SUPER_TYPE_CALL_ENTRY -> - return markElement(tree.referenceExpression(selector) ?: selector, startOffset, endOffset, tree, node) + KtNodeTypes.CALL_EXPRESSION, KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL,KtNodeTypes.SUPER_TYPE_CALL_ENTRY -> + return markElement( + tree.referenceExpression(selector, locateReferencedName) ?: selector, + startOffset, + endOffset, + tree, + node + ) } } return super.mark(node, startOffset, endOffset, tree) } } + private val nodeTypesWithOperation = setOf( + KtNodeTypes.IS_EXPRESSION, + KtNodeTypes.BINARY_WITH_TYPE, + KtNodeTypes.BINARY_EXPRESSION, + KtNodeTypes.POSTFIX_EXPRESSION, + KtNodeTypes.PREFIX_EXPRESSION, + KtNodeTypes.BINARY_EXPRESSION, + KtNodeTypes.WHEN_CONDITION_IN_RANGE + ) + val WHEN_EXPRESSION = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, @@ -464,12 +490,33 @@ private fun FlyweightCapableTreeStructure.nameIdentifier(node: L private fun FlyweightCapableTreeStructure.operationReference(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtNodeTypes.OPERATION_REFERENCE) -private fun FlyweightCapableTreeStructure.referenceExpression(node: LighterASTNode): LighterASTNode? { +/** + * @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for diagnostics + * on super and unresolved references. For example, with the following, only the part inside the parentheses should be highlighted. + * + * ``` + * fun foo() { + * (super)() + * ^^^^^ + * (random123)() + * ^^^^^^^^^ + * } + * ``` + */ +private fun FlyweightCapableTreeStructure.referenceExpression( + node: LighterASTNode, + locateReferencedName: Boolean +): LighterASTNode? { val childrenRef = Ref>() getChildren(node, childrenRef) - return childrenRef.get()?.firstOrNull { - it?.tokenType == KtNodeTypes.REFERENCE_EXPRESSION || it?.tokenType == KtNodeTypes.CONSTRUCTOR_DELEGATION_REFERENCE + var result = childrenRef.get()?.firstOrNull { + it?.tokenType == KtNodeTypes.REFERENCE_EXPRESSION || it?.tokenType == KtNodeTypes.CONSTRUCTOR_DELEGATION_REFERENCE || + it?.tokenType == KtNodeTypes.SUPER_EXPRESSION || it?.tokenType == KtNodeTypes.PARENTHESIZED } + while (locateReferencedName && result != null && result.tokenType == KtNodeTypes.PARENTHESIZED) { + result = referenceExpression(result, locateReferencedName = true) + } + return result } private fun FlyweightCapableTreeStructure.rightParenthesis(node: LighterASTNode): LighterASTNode? = diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 41e8cfe9de7..1232989c737 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -133,6 +133,11 @@ object SourceElementPositioningStrategies { PositioningStrategies.REFERENCE_BY_QUALIFIED ) + val REFERENCED_NAME_BY_QUALIFIED = SourceElementPositioningStrategy( + LightTreePositioningStrategies.REFERENCED_NAME_BY_QUALIFIED, + PositioningStrategies.REFERENCED_NAME_BY_QUALIFIED + ) + val WHEN_EXPRESSION = SourceElementPositioningStrategy( LightTreePositioningStrategies.WHEN_EXPRESSION, PositioningStrategies.WHEN_EXPRESSION 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 1396d217bd5..2db4cb0a8a3 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 @@ -23,7 +23,10 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.utils.addToStdlib.safeAs -private fun ConeDiagnostic.toFirDiagnostic(source: FirSourceElement): FirDiagnostic? = when (this) { +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()) @@ -36,14 +39,14 @@ private fun ConeDiagnostic.toFirDiagnostic(source: FirSourceElement): FirDiagnos } is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.on(source, this.candidates) is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.on(source) - is ConeTypeMismatchError -> FirErrors.TYPE_MISMATCH.on(source, this.expectedType, this.actualType) + is ConeTypeMismatchError -> FirErrors.TYPE_MISMATCH.on(qualifiedAccessSource ?: source, this.expectedType, this.actualType) 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 ConeWrongNumberOfTypeArgumentsError -> - FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(source, this.desiredCount, this.type) + FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) is ConeSimpleDiagnostic -> when { source.kind is FirFakeSourceElementKind -> null - else -> this.getFactory().on(source) + else -> this.getFactory().on(qualifiedAccessSource ?: source) } is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target) is ConeStubDiagnostic -> null @@ -54,11 +57,14 @@ private fun ConeDiagnostic.toFirDiagnostic(source: FirSourceElement): FirDiagnos else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}") } -fun ConeDiagnostic.toFirDiagnostics(source: FirSourceElement): List> { +fun ConeDiagnostic.toFirDiagnostics( + source: FirSourceElement, + qualifiedAccessSource: FirSourceElement? +): List> { if (this is ConeInapplicableCandidateError) { - return mapInapplicableCandidateError(this, source) + return mapInapplicableCandidateError(this, source, qualifiedAccessSource) } - return listOfNotNull(toFirDiagnostic(source)) + return listOfNotNull(toFirDiagnostic(source, qualifiedAccessSource)) } private fun ConeKotlinType.isEffectivelyNotNull(): Boolean { @@ -75,13 +81,14 @@ private fun mapUnsafeCallError( diagnostic: ConeInapplicableCandidateError, source: FirSourceElement, rootCause: ResolutionDiagnostic?, + qualifiedAccessSource: FirSourceElement?, ): FirDiagnostic<*>? { - if (rootCause is InapplicableWrongReceiver && - rootCause.actualType?.isNullable == true && - (rootCause.expectedType == null || rootCause.expectedType!!.isEffectivelyNotNull()) - ) { + if (rootCause !is InapplicableWrongReceiver) return null + val actualType = rootCause.actualType ?: return null + val expectedType = rootCause.expectedType + if (actualType.isNullable && (expectedType == null || expectedType.isEffectivelyNotNull())) { if (diagnostic.candidate.callInfo.isImplicitInvoke) { - return FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL.on(source, rootCause.actualType!!) + return FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL.on(source, actualType) } val candidateFunction = diagnostic.candidate.symbol.fir as? FirSimpleFunction @@ -100,8 +107,11 @@ private fun mapUnsafeCallError( return FirErrors.UNSAFE_OPERATOR_CALL.on(source, left, candidateFunctionName!!.asString(), right) } } - - return FirErrors.UNSAFE_CALL.on(source, rootCause.actualType!!) + return if (source.kind == FirFakeSourceElementKind.ArrayAccessNameReference) { + FirErrors.UNSAFE_CALL.on(source, actualType) + } else { + FirErrors.UNSAFE_CALL.on(qualifiedAccessSource ?: source, actualType) + } } return null } @@ -109,15 +119,18 @@ private fun mapUnsafeCallError( private fun mapInapplicableCandidateError( diagnostic: ConeInapplicableCandidateError, source: FirSourceElement, + qualifiedAccessSource: FirSourceElement?, ): List> { // TODO: Need to distinguish SMARTCAST_IMPOSSIBLE return diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause -> - mapUnsafeCallError(diagnostic, source, rootCause)?.let { return@mapNotNull it } + mapUnsafeCallError(diagnostic, source, rootCause, qualifiedAccessSource)?.let { return@mapNotNull it } when (rootCause) { - is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on(rootCause.argument.source ?: source) + is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on( + rootCause.argument.source ?: qualifiedAccessSource + ) is NamedArgumentNotAllowed -> FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED.on( - rootCause.argument.source ?: source, + rootCause.argument.source ?: qualifiedAccessSource, rootCause.forbiddenNamedArgumentsTarget ) else -> null diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt index 289c9af8859..c10e211ea07 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt @@ -45,7 +45,7 @@ internal fun KtWhenCondition.toFirWhenCondition( firRange.generateContainsOperation( firSubjectExpression, isNegated, - rangeExpression?.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition), + this@toFirWhenCondition.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition), operationReference.toFirPsiSourceElement() ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 6fecd098e27..e8e6f55f69d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -729,7 +729,8 @@ object PositioningStrategies { return mark(element.operationTokenNode.psi) } } - return super.mark(element) + // Fallback to mark the callee reference. + return REFERENCE_BY_QUALIFIED.mark(element) } } @@ -744,21 +745,45 @@ object PositioningStrategies { } } - val REFERENCE_BY_QUALIFIED: PositioningStrategy = object : PositioningStrategy() { + val REFERENCE_BY_QUALIFIED: PositioningStrategy = FindReferencePositioningStrategy(false) + val REFERENCED_NAME_BY_QUALIFIED: PositioningStrategy = FindReferencePositioningStrategy(true) + + /** + * @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for + * diagnostics on super and unresolved references. For example, with the following, only the part inside the parentheses should be + * highlighted. + * + * ``` + * fun foo() { + * (super)() + * ^^^^^ + * (random123)() + * ^^^^^^^^^ + * } + * ``` + */ + class FindReferencePositioningStrategy(val locateReferencedName: Boolean) : PositioningStrategy() { override fun mark(element: PsiElement): List { - when (element) { + var result: PsiElement = when (element) { is KtQualifiedExpression -> { when (val selectorExpression = element.selectorExpression) { - is KtCallExpression -> return mark(selectorExpression.calleeExpression ?: selectorExpression) - is KtReferenceExpression -> return mark(selectorExpression) + is KtCallExpression -> selectorExpression.calleeExpression ?: selectorExpression + is KtReferenceExpression -> selectorExpression + else -> element } } - is KtCallableReferenceExpression -> return mark(element.callableReference) - is KtCallExpression -> return mark(element.calleeExpression ?: element) - is KtConstructorDelegationCall -> return mark(element.calleeExpression ?: element) - is KtSuperTypeCallEntry -> return mark(element.calleeExpression) + is KtCallableReferenceExpression -> element.callableReference + is KtCallExpression -> element.calleeExpression ?: element + is KtConstructorDelegationCall -> element.calleeExpression ?: element + is KtSuperTypeCallEntry -> element.calleeExpression + is KtOperationExpression -> element.operationReference + is KtWhenConditionInRange -> element.operationReference + else -> element } - return super.mark(element) + while (locateReferencedName && result is KtParenthesizedExpression) { + result = result.expression ?: break + } + return super.mark(result) } } } diff --git a/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt b/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt index 520fffe2f90..34f681b3add 100644 --- a/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt +++ b/compiler/testData/diagnostics/tests/BinaryCallsOnNullableValues.fir.kt @@ -9,7 +9,7 @@ fun f(): Unit { x + 1 x plus 1 x < 1 - x += 1 + x += 1 x == 1 x != 1 diff --git a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt index 278ab1000ca..38f66e13e72 100644 --- a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt @@ -28,20 +28,20 @@ fun fooT2() : (t : T) -> T { fun main(args : Array) { args.foo()() - args.foo1()() - a.foo1()() + args.foo1()() + a.foo1()() a.foo1()(a) args.foo1()(1) - args.foo1()("1") - a.foo1()("1") + args.foo1()("1") + a.foo1()("1") a.foo1()(a) foo2()({}) foo2(){} (foo2()){} (foo2()){x -> } - foo2()({x -> }) + foo2()({x -> }) val a = fooT1(1)() checkSubtype(a) @@ -58,13 +58,13 @@ fun main(args : Array) { fun f() : Int.() -> Unit = {} fun main1() { - 1.(fun Int.() = 1)(); + 1.(fun Int.() = 1)(); {1}(); (fun (x : Int) = x)(1) - 1.(fun Int.(x : Int) = x)(1); + 1.(fun Int.(x : Int) = x)(1); l@{1}() - 1.((fun Int.() = 1))() - 1.(f())() + 1.((fun Int.() = 1))() + 1.(f())() 1.if(true){f()}else{f()}() 1.if(true)(fun Int.() {})else{f()}() @@ -78,10 +78,10 @@ fun main1() { fun test() { {x : Int -> 1}(); (fun Int.() = 1)() - "sd".(fun Int.() = 1)() + "sd".(fun Int.() = 1)() val i : Int? = null - i.(fun Int.() = 1)(); + i.(fun Int.() = 1)(); {}() - 1?.(fun Int.() = 1)() + 1?.(fun Int.() = 1)() 1.{}() } diff --git a/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.fir.kt b/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.fir.kt index f9b72970cea..8f47952580e 100644 --- a/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/compatibilityResolveWithVarargAndOperatorCall.fir.kt @@ -14,5 +14,5 @@ operator fun A.set(i: IFoo, newValue: Int) {} fun withVararg(vararg xs: Int) = 42 fun test1() { - A[::withVararg] += 1 -} \ No newline at end of file + A[::withVararg] += 1 +} diff --git a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt index 7ad3ec07b8b..501a6e79e7c 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt @@ -45,7 +45,7 @@ fun test() { x4 checkType { _>() } { y: Int -> fun named14(): Int {return 1} } - val b = (fun named15(): Boolean { return true })() + val b = (fun named15(): Boolean { return true })() baz(fun named16(){}) } diff --git a/compiler/testData/diagnostics/tests/enum/constructorWithDefaultParametersOnly.fir.kt b/compiler/testData/diagnostics/tests/enum/constructorWithDefaultParametersOnly.fir.kt index 0923425dd69..863bd73eb40 100644 --- a/compiler/testData/diagnostics/tests/enum/constructorWithDefaultParametersOnly.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/constructorWithDefaultParametersOnly.fir.kt @@ -18,4 +18,4 @@ enum class TestMultipleConstructors(val x: String = "", val y: Int = 0) { enum class TestVarargs(val x: Int) { TEST; constructor(vararg xs: Any) : this(xs.size) -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/extensions/throwOutCandidatesByReceiver.fir.kt b/compiler/testData/diagnostics/tests/extensions/throwOutCandidatesByReceiver.fir.kt index 5e36f04c40f..cf9e93659a0 100644 --- a/compiler/testData/diagnostics/tests/extensions/throwOutCandidatesByReceiver.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/throwOutCandidatesByReceiver.fir.kt @@ -35,7 +35,7 @@ fun test4() { // should be an error on receiver, shouldn't be thrown away fun test5() { - 1.(fun String.()=1)() + 1.(fun String.()=1)() } fun R?.sure() : R = this!! diff --git a/compiler/testData/diagnostics/tests/functionLiterals/DeprecatedSyntax.fir.kt b/compiler/testData/diagnostics/tests/functionLiterals/DeprecatedSyntax.fir.kt index 85ce9597a68..8111b18415b 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/DeprecatedSyntax.fir.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/DeprecatedSyntax.fir.kt @@ -1,9 +1,9 @@ // !WITH_NEW_INFERENCE val receiver = { Int.() -> } -val receiverWithParameter = { Int.(a) -> } +val receiverWithParameter = { Int.(a) -> } val receiverAndReturnType = { Int.(): Int -> 5 } -val receiverAndReturnTypeWithParameter = { Int.(a: Int): Int -> 5 } +val receiverAndReturnTypeWithParameter = { Int.(a: Int): Int -> 5 } val returnType = { (): Int -> 5 } val returnTypeWithParameter = { (b: Int): Int -> 5 } diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/noTypeParamsInReturnType.fir.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/noTypeParamsInReturnType.fir.kt index 859e1d1b28f..7dcf7de4b6f 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/noTypeParamsInReturnType.fir.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/noTypeParamsInReturnType.fir.kt @@ -8,4 +8,3 @@ fun getMap() : Map = throw Exception() fun bar123() { foo(getMap( } - diff --git a/compiler/testData/diagnostics/tests/incompleteCode/inExpr.fir.kt b/compiler/testData/diagnostics/tests/incompleteCode/inExpr.fir.kt index e53e01564df..0e31891284e 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/inExpr.fir.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/inExpr.fir.kt @@ -2,4 +2,4 @@ package l fun test(a: Int) { if (a in ) {} //a is not unresolved -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/incompleteCode/inExpr.kt b/compiler/testData/diagnostics/tests/incompleteCode/inExpr.kt index c40646cbb25..2645d815631 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/inExpr.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/inExpr.kt @@ -2,4 +2,4 @@ package l fun test(a: Int) { if (a in ) {} //a is not unresolved -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inner/classesInClassObjectHeader.fir.kt b/compiler/testData/diagnostics/tests/inner/classesInClassObjectHeader.fir.kt index 1076a1809f3..2e168387680 100644 --- a/compiler/testData/diagnostics/tests/inner/classesInClassObjectHeader.fir.kt +++ b/compiler/testData/diagnostics/tests/inner/classesInClassObjectHeader.fir.kt @@ -8,4 +8,4 @@ class Test { open class StaticClass open inner class InnerClass -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inner/modality.fir.kt b/compiler/testData/diagnostics/tests/inner/modality.fir.kt index 720c5f95c83..e5f9277c709 100644 --- a/compiler/testData/diagnostics/tests/inner/modality.fir.kt +++ b/compiler/testData/diagnostics/tests/inner/modality.fir.kt @@ -14,4 +14,4 @@ class Outer { inner class Inner2 : FinalNested() inner class Inner3 : OpenInner() inner class Inner4 : FinalInner() -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/kt435.fir.kt b/compiler/testData/diagnostics/tests/kt435.fir.kt index c24f1f89f78..5ec15398cd4 100644 --- a/compiler/testData/diagnostics/tests/kt435.fir.kt +++ b/compiler/testData/diagnostics/tests/kt435.fir.kt @@ -3,5 +3,5 @@ fun Any.foo1() : (i : Int) -> Unit { } fun test(a : Any) { - a.foo1()() -} \ No newline at end of file + a.foo1()() +} diff --git a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt index 8dbd3ff4ab0..f64bd1bdf0d 100644 --- a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt @@ -30,7 +30,7 @@ fun test() { oldAndNew %= 1 val onlyOld = OnlyOld() - onlyOld %= 1 + onlyOld %= 1 val onlyNew = OnlyNew() onlyNew %= 1 @@ -40,4 +40,4 @@ fun test() { var modAndRemAssign = ModAndRemAssign() modAndRemAssign %= 1 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt index 1b7ad2ad8af..842be5c2e1c 100644 --- a/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt @@ -27,6 +27,6 @@ fun foo() { r.remAssign(1) val m = JustMod - m %= 1 + m %= 1 m.modAssign(1) -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/operatorRem/resolveToModWhenNoOperatorRemFeature.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/resolveToModWhenNoOperatorRemFeature.fir.kt index 1877165b621..1d608206b05 100644 --- a/compiler/testData/diagnostics/tests/operatorRem/resolveToModWhenNoOperatorRemFeature.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorRem/resolveToModWhenNoOperatorRemFeature.fir.kt @@ -25,7 +25,7 @@ fun test() { takeInt(ModAndRem % 1) val c = ModAssignAndRemAssign - c %= "" + c %= "" var c1 = RemAndModAssign c1 %= 1 @@ -36,4 +36,4 @@ fun test() { c2 %= 1 } -fun takeInt(x: Int) {} \ No newline at end of file +fun takeInt(x: Int) {} diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt index dcd7b5368ec..5933e9a4041 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/InconsistentGetSet.fir.kt @@ -20,7 +20,7 @@ object MismatchingTypes { fun testMismatchingTypes() { ++MismatchingTypes[0] MismatchingTypes[0]++ - MismatchingTypes[0] += 1 + MismatchingTypes[0] += 1 } object MismatchingArities1 { @@ -36,10 +36,9 @@ object MismatchingArities2 { fun testMismatchingArities() { ++MismatchingArities1[0] MismatchingArities1[0]++ - MismatchingArities1[0] += 1 + MismatchingArities1[0] += 1 ++MismatchingArities2[0] MismatchingArities2[0]++ - MismatchingArities2[0] += 1 + MismatchingArities2[0] += 1 } - diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/assignmentOperationsCheckReturnType.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/assignmentOperationsCheckReturnType.fir.kt index 9884f34c1a1..6f622c7bf2c 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/assignmentOperationsCheckReturnType.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/assignmentOperationsCheckReturnType.fir.kt @@ -1,12 +1,12 @@ fun intBinEq() { var x = 0 - x += 'a' + x += 'a' x += 1.toByte() x += 1.toShort() x += 1L x += 1f x += 1.0 - x *= 'a' + x *= 'a' x *= 1.toByte() x *= 1.toShort() x *= 1L @@ -16,14 +16,14 @@ fun intBinEq() { fun shortBinEq() { var x = 0.toShort() - x += 'a' + x += 'a' x += 1.toByte() x += 1.toShort() x += 1L x += 1f x += 1.0 - x *= 'a' + x *= 'a' x *= 1.toByte() x *= 1.toShort() x *= 1L diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt index bf4edbd5427..288139fe2c2 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnArray.fir.kt @@ -16,5 +16,5 @@ fun test() { val c = C() c[0] += "" var c1 = C1() - c1[0] += "" -} \ No newline at end of file + c1[0] += "" +} diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.fir.kt index c7009ad980b..14ab7e5b685 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.fir.kt @@ -19,5 +19,5 @@ public class J { // FILE: k.kt var A by J.staticNN -var B by J.staticN -var C by J.staticJ \ No newline at end of file +var B by J.staticN +var C by J.staticJ diff --git a/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt b/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt index 5bc68c265e7..77afc514e0c 100644 --- a/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/qualifiedExpression/calleeExpressionAsCallExpression.fir.kt @@ -1,2 +1,2 @@ // !WITH_NEW_INFERENCE -val unwrapped = some<sdf()()::unwrap +val unwrapped = some<sdf()()::unwrap diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt index e02acf7781b..68c4faece55 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt @@ -7,5 +7,5 @@ fun test1(f: String.() -> Unit) { fun test2(f: (Int) -> Int) { 1.f(2) - 2.(f)(2) -} \ No newline at end of file + 2.(f)(2) +} diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt index 5a3559b9135..b92866a8c13 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt @@ -1,17 +1,17 @@ // !WITH_NEW_INFERENCE fun test1() { - 1. (fun String.(i: Int) = i )(1) - 1.(label@ fun String.(i: Int) = i )(1) + 1. (fun String.(i: Int) = i )(1) + 1.(label@ fun String.(i: Int) = i )(1) } fun test2(f: String.(Int) -> Unit) { - 11.(f)(1) - 11.(f)() + 11.(f)(1) + 11.(f)() } fun test3() { fun foo(): String.(Int) -> Unit = {} - 1.(foo())(1) + 1.(foo())(1) } diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt index 8af8d45ccec..a95ec3b4fd2 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt @@ -2,11 +2,11 @@ class A(val x: (String.() -> Unit)?) fun test(a: A) { if (a.x != null) { - "".(a.x)() + "".(a.x)() a.x("") // todo (a.x)("") } - "".(a.x)() + "".(a.x)() a.x("") (a.x)("") diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt index 2ee6ca48bc2..cd0235c4b5e 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt @@ -8,7 +8,7 @@ class B val A.foo: B.() -> Unit get() = {} fun test(a: A, b: B) { - b.(a.foo)() + b.(a.foo)() (a.foo)(b) a.foo(b) @@ -25,7 +25,7 @@ fun test(a: A, b: B) { with(b) { a.foo() - a.(foo)() + a.(foo)() (a.foo)() @@ -50,7 +50,7 @@ class A { class B fun test(a: A, b: B) { - b.(a.foo)() + b.(a.foo)() (a.foo)(b) a.foo(b) @@ -59,7 +59,7 @@ fun test(a: A, b: B) { b.(foo)() - (b.foo)() + (b.foo)() foo(b) (foo)(b) @@ -67,7 +67,7 @@ fun test(a: A, b: B) { with(b) { a.foo() - a.(foo)() + a.(foo)() (a.foo)() diff --git a/compiler/testData/diagnostics/tests/smartCasts/alwaysNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/alwaysNull.fir.kt index 7addcc32b87..d900c519e42 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/alwaysNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/alwaysNull.fir.kt @@ -8,7 +8,7 @@ fun foo(): String { var t: String? = "y" if (t == null) t = "x" var x: Int? = null - if (x == null) x += null + if (x == null) x += null return t + s } diff --git a/compiler/testData/diagnostics/tests/traitWithRequired/traitSupertypeList.fir.kt b/compiler/testData/diagnostics/tests/traitWithRequired/traitSupertypeList.fir.kt index abca9fd22b6..c38b13da824 100644 --- a/compiler/testData/diagnostics/tests/traitWithRequired/traitSupertypeList.fir.kt +++ b/compiler/testData/diagnostics/tests/traitWithRequired/traitSupertypeList.fir.kt @@ -7,4 +7,4 @@ interface Foo2 : bar, Foo { } open class Foo1() : bar(), bar, Foo, Foo() {} -open class Foo12 : bar(), bar {} \ No newline at end of file +open class Foo12 : bar(), bar {} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda.fir.kt index 89e50eaa83a..6a393ec0908 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/plusAssignWithLambda.fir.kt @@ -26,7 +26,7 @@ fun id(x: T) = x fun foo2() = { var x = A() - x += { "" } + x += { "" } var y = A() y += 1 } diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-named-parameters/p-1/pos/2.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-named-parameters/p-1/pos/2.1.fir.kt index 476e7e2e0c2..9638d5570bf 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-named-parameters/p-1/pos/2.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-named-parameters/p-1/pos/2.1.fir.kt @@ -63,7 +63,7 @@ fun case3() { */ fun case4(marker : Marker?) { marker?.foo(y=1) - marker?.foo(x=1)> + marker?.foo(x=1)> } diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-trailing-lambda-expressions/p-1/pos/2.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-trailing-lambda-expressions/p-1/pos/2.1.fir.kt index 5f9b80e065f..ccf3ed12d65 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-trailing-lambda-expressions/p-1/pos/2.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-with-trailing-lambda-expressions/p-1/pos/2.1.fir.kt @@ -63,7 +63,7 @@ fun case3() { */ fun case4(marker: Marker?) { marker?.foo(y = { 1 }) - marker?.foo(x = { 1 })> + marker?.foo(x = { 1 })> } diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.4.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.4.fir.kt index b23bb9fedf4..f2a664e306e 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.4.fir.kt @@ -26,9 +26,9 @@ import LibPackCase1.b.* fun case1 (){ var b: B? = B() - b += { C() } + b += { C() } - b += {1} + b += {1} } class B { @@ -63,9 +63,9 @@ import LibPackCase2.b.* fun case2 (){ var b: B = B() - b += { C() } + b += { C() } - b += {1} + b += {1} } class B { diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.5.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.5.fir.kt index 5dcc3461f9d..7dd153b55a1 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.5.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.5.fir.kt @@ -10,9 +10,9 @@ import LibPackCase1.a.* import LibPackCase1.b.* fun case1 (){ var b: B? = null - b += { C() } + b += { C() } - b += {1} + b += {1} } class B { diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.6.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.6.fir.kt index 4434928a706..d2ba79f7ee0 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.6.fir.kt @@ -15,9 +15,9 @@ import LibPackCase1.b.* fun case1 (){ var b: B? = B() - b += { C() } + b += { C() } - b += {1} + b += {1} } class B { diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.7.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.7.fir.kt index 650626deefb..84b91dc6529 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.7.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.7.fir.kt @@ -15,9 +15,9 @@ import LibPackCase1.b.plusAssign fun case1 (){ var b: B? = B() - b += { C() } + b += { C() } - b += {1} + b += {1} } class B { diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.8.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.8.fir.kt index b57c07ce3ad..5df10ae0ab8 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.8.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/operator-call/p-1/neg/2.8.fir.kt @@ -15,8 +15,8 @@ import LibPackCase1.b.plusAssign fun case1 (){ var b: B = B() - b +={ C() } - b +={ 1 } + b +={ C() } + b +={ 1 } } class B @@ -48,8 +48,8 @@ import LibPackCase2.b.plusAssign fun case2 (){ var b: B = B() - b +={ C() } - b +={ 1 } + b +={ C() } + b +={ 1 } b.plusAssign{ C() } } diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.1.fir.kt index 7df09612c75..66968f0590a 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.1.fir.kt @@ -17,7 +17,7 @@ operator fun I2.invoke(): String = TODO() fun case1(a: A) { a.invoke() a() - A()() + A()() } // FILE: TestCase2.kt diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.2.fir.kt index 9b65fd3866a..1e3365503c0 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/choosing-the-most-specific-candidate-from-the-overload-candidate-set/algorithm-of-msc-selection/p-17/neg/2.2.fir.kt @@ -17,7 +17,7 @@ operator fun I2.invoke(): String = TODO() fun case1(a: A) { a.invoke() a() - A()() + A()() } // FILE: TestCase2.kt diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/12.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/12.fir.kt index 6855de1205a..69eed526113 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/12.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/12.fir.kt @@ -6,7 +6,7 @@ fun case_1() { var x: Int? = 11 x!! - try {x = null;} finally { x += 10; } + try {x = null;} finally { x += 10; } } // TESTCASE NUMBER: 2 diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt index c484ad3538f..95d4bc6933c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt @@ -30,8 +30,8 @@ internal interface KtFirAnalysisSessionComponent { fun FirPsiDiagnostic<*>.asKtDiagnostic(): KtDiagnosticWithPsi<*> = KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, this as FirDiagnostic<*>) - fun ConeDiagnostic.asKtDiagnostic(source: FirSourceElement): KtDiagnosticWithPsi<*>? { - val firDiagnostic = toFirDiagnostics(source).firstOrNull() ?: return null + fun ConeDiagnostic.asKtDiagnostic(source: FirSourceElement, qualifiedAccessSource: FirSourceElement?): KtDiagnosticWithPsi<*>? { + val firDiagnostic = toFirDiagnostics(source, qualifiedAccessSource).firstOrNull() ?: return null check(firDiagnostic is FirPsiDiagnostic<*>) return firDiagnostic.asKtDiagnostic() } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt index 8a8f1a2d2df..506b75df3b0 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression @@ -85,7 +86,7 @@ internal class KtFirCallResolver( } is FirErrorNamedReference -> KtVariableWithInvokeFunctionCall( variableLikeSymbol, - callReference.createErrorCallTarget() + callReference.createErrorCallTarget(source) ) else -> error("Unexpected call reference ${callReference::class.simpleName}") } @@ -93,8 +94,8 @@ internal class KtFirCallResolver( private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? { val target = when (val calleeReference = calleeReference) { is FirResolvedNamedReference -> calleeReference.getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) } - is FirErrorNamedReference -> calleeReference.createErrorCallTarget() - is FirErrorReferenceWithCandidate -> calleeReference.createErrorCallTarget() + is FirErrorNamedReference -> calleeReference.createErrorCallTarget(source) + is FirErrorReferenceWithCandidate -> calleeReference.createErrorCallTarget(source) is FirSimpleNamedReference -> error( """ @@ -109,16 +110,16 @@ internal class KtFirCallResolver( return KtFunctionCall(target) } - private fun FirErrorNamedReference.createErrorCallTarget(): KtErrorCallTarget = + private fun FirErrorNamedReference.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget = KtErrorCallTarget( getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, - source?.let { diagnostic.asKtDiagnostic(it) } ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) + source?.let { diagnostic.asKtDiagnostic(it, qualifiedAccessSource) } ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) ) - private fun FirErrorReferenceWithCandidate.createErrorCallTarget(): KtErrorCallTarget = + private fun FirErrorReferenceWithCandidate.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget = KtErrorCallTarget( getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, - source?.let { diagnostic.asKtDiagnostic(it) } ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) + source?.let { diagnostic.asKtDiagnostic(it,qualifiedAccessSource) } ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) ) private fun FirResolvedNamedReference.getKtFunctionOrConstructorSymbol(): KtFunctionLikeSymbol? =