diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index dbc280ad1c5..7a17a82f1b8 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -3586,8 +3586,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert } add(FirErrors.SENSELESS_COMPARISON) { firDiagnostic -> SenselessComparisonImpl( - firDiagnostic.a.source!!.psi as KtExpression, - firDiagnostic.b, + firDiagnostic.a, firDiagnostic as KtPsiDiagnostic, token, ) @@ -3621,18 +3620,20 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert } add(FirErrors.UNSAFE_INFIX_CALL) { firDiagnostic -> UnsafeInfixCallImpl( - firDiagnostic.a.source!!.psi as KtExpression, - firDiagnostic.b, - firDiagnostic.c.source!!.psi as KtExpression, + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firDiagnostic.b.source!!.psi as KtExpression, + firDiagnostic.c, + firDiagnostic.d.source!!.psi as KtExpression, firDiagnostic as KtPsiDiagnostic, token, ) } add(FirErrors.UNSAFE_OPERATOR_CALL) { firDiagnostic -> UnsafeOperatorCallImpl( - firDiagnostic.a.source!!.psi as KtExpression, - firDiagnostic.b, - firDiagnostic.c.source!!.psi as KtExpression, + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + firDiagnostic.b.source!!.psi as KtExpression, + firDiagnostic.c, + firDiagnostic.d.source!!.psi as KtExpression, firDiagnostic as KtPsiDiagnostic, token, ) @@ -4315,8 +4316,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert } add(FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE) { firDiagnostic -> InvalidDefaultFunctionalParameterForInlineImpl( - firDiagnostic.a.source!!.psi as KtExpression, - firSymbolBuilder.buildSymbol(firDiagnostic.b), + firSymbolBuilder.buildSymbol(firDiagnostic.a), firDiagnostic as KtPsiDiagnostic, token, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 282bc753b04..50e86a29a4b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -2506,7 +2506,6 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { interface SenselessComparison : KtFirDiagnostic { override val diagnosticClass get() = SenselessComparison::class - val expression: KtExpression val compareResult: Boolean } @@ -2531,6 +2530,7 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { interface UnsafeInfixCall : KtFirDiagnostic { override val diagnosticClass get() = UnsafeInfixCall::class + val receiverType: KtType val receiverExpression: KtExpression val operator: String val argumentExpression: KtExpression @@ -2538,6 +2538,7 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { interface UnsafeOperatorCall : KtFirDiagnostic { override val diagnosticClass get() = UnsafeOperatorCall::class + val receiverType: KtType val receiverExpression: KtExpression val operator: String val argumentExpression: KtExpression @@ -3011,7 +3012,6 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { interface InvalidDefaultFunctionalParameterForInline : KtFirDiagnostic { override val diagnosticClass get() = InvalidDefaultFunctionalParameterForInline::class - val defaultValue: KtExpression val parameter: KtSymbol } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 6aa4baafc8f..0117bc9a916 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -3018,7 +3018,6 @@ internal class UnreachableCodeImpl( ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.UnreachableCode internal class SenselessComparisonImpl( - override val expression: KtExpression, override val compareResult: Boolean, firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, @@ -3048,6 +3047,7 @@ internal class UnsafeImplicitInvokeCallImpl( ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.UnsafeImplicitInvokeCall internal class UnsafeInfixCallImpl( + override val receiverType: KtType, override val receiverExpression: KtExpression, override val operator: String, override val argumentExpression: KtExpression, @@ -3056,6 +3056,7 @@ internal class UnsafeInfixCallImpl( ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.UnsafeInfixCall internal class UnsafeOperatorCallImpl( + override val receiverType: KtType, override val receiverExpression: KtExpression, override val operator: String, override val argumentExpression: KtExpression, @@ -3629,7 +3630,6 @@ internal class NonInternalPublishedApiImpl( ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.NonInternalPublishedApi internal class InvalidDefaultFunctionalParameterForInlineImpl( - override val defaultValue: KtExpression, override val parameter: KtSymbol, firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 41627f99923..fcfabd05fc0 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -29742,6 +29742,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/senselessComparison"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("complexExpression.kt") + public void testComplexExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt"); + } + @Test @TestMetadata("noExplicitType.kt") public void testNoExplicitType() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 44cbf727859..bf9ebd5db53 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -29742,6 +29742,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/senselessComparison"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("complexExpression.kt") + public void testComplexExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt"); + } + @Test @TestMetadata("noExplicitType.kt") public void testNoExplicitType() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 7ad47c13a4e..1faa6843283 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -29742,6 +29742,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/senselessComparison"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("complexExpression.kt") + public void testComplexExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt"); + } + @Test @TestMetadata("noExplicitType.kt") public void testNoExplicitType() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index fe0c183b532..aba17773bb1 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -29838,6 +29838,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/senselessComparison"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("complexExpression.kt") + public void testComplexExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt"); + } + @Test @TestMetadata("noExplicitType.kt") public void testNoExplicitType() throws Exception { 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 e930d76eb9d..40995fa0bad 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 @@ -1236,7 +1236,6 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter>("unreachable") } val SENSELESS_COMPARISON by warning { - parameter("expression") parameter("compareResult") } val SENSELESS_NULL_IN_WHEN by warning() @@ -1252,11 +1251,13 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("receiverType") } val UNSAFE_INFIX_CALL by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { + parameter("receiverType") parameter("receiverExpression") parameter("operator") parameter("argumentExpression") } val UNSAFE_OPERATOR_CALL by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { + parameter("receiverType") parameter("receiverExpression") parameter("operator") parameter("argumentExpression") @@ -1520,7 +1521,6 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val NON_INTERNAL_PUBLISHED_API by error() val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error() { - parameter("defaultValue") parameter("parameter") } 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 f010f9e0166..b4393562c8e 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 @@ -645,15 +645,15 @@ object FirErrors { val VARIABLE_WITH_NO_TYPE_NO_INITIALIZER by error0(SourceElementPositioningStrategies.DECLARATION_NAME) val INITIALIZATION_BEFORE_DECLARATION by error1>() val UNREACHABLE_CODE by warning2, Set>(SourceElementPositioningStrategies.UNREACHABLE_CODE) - val SENSELESS_COMPARISON by warning2() + val SENSELESS_COMPARISON by warning1() val SENSELESS_NULL_IN_WHEN by warning0() val TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM by error0() // Nullability val UNSAFE_CALL by error2(SourceElementPositioningStrategies.DOT_BY_QUALIFIED) val UNSAFE_IMPLICIT_INVOKE_CALL by error1(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val UNSAFE_INFIX_CALL by error3(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val UNSAFE_OPERATOR_CALL by error3(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) + val UNSAFE_INFIX_CALL by error4(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) + val UNSAFE_OPERATOR_CALL by error4(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val ITERATOR_ON_NULLABLE by error0() val UNNECESSARY_SAFE_CALL by warning1(SourceElementPositioningStrategies.SAFE_ACCESS) val SAFE_CALL_WILL_CHANGE_NULLABILITY by warning0(SourceElementPositioningStrategies.CALL_ELEMENT_WITH_DOT) @@ -770,7 +770,7 @@ object FirErrors { val DECLARATION_CANT_BE_INLINED by error0(SourceElementPositioningStrategies.INLINE_FUN_MODIFIER) val OVERRIDE_BY_INLINE by warning0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val NON_INTERNAL_PUBLISHED_API by error0() - val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2() + val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error1() val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error0(SourceElementPositioningStrategies.REIFIED_MODIFIER) val INLINE_PROPERTY_WITH_BACKING_FIELD by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val ILLEGAL_INLINE_PARAMETER_MODIFIER by error0(SourceElementPositioningStrategies.INLINE_PARAMETER_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt index 48d9cad5b23..699921d5699 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt @@ -420,7 +420,6 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { reporter.reportOn( defaultValue.source, FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, - defaultValue, param.symbol, context ) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt index 8dc0661bdcd..659da20572f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt @@ -273,7 +273,7 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() { if (expression.source?.elementType != KtNodeTypes.BINARY_EXPRESSION && type === lType && !compareResult) { reporter.reportOn(expression.source, FirErrors.SENSELESS_NULL_IN_WHEN, context) } else { - reporter.reportOn(expression.source, FirErrors.SENSELESS_COMPARISON, expression, compareResult, context) + reporter.reportOn(expression.source, FirErrors.SENSELESS_COMPARISON, compareResult, context) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index be866619756..1b11b49b2ee 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -11,10 +11,14 @@ import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers import org.jetbrains.kotlin.diagnostics.WhenMissingCase import org.jetbrains.kotlin.diagnostics.rendering.ContextIndependentParameterRenderer import org.jetbrains.kotlin.diagnostics.rendering.Renderer -import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.declarations.utils.* -import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.calleeReference +import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression +import org.jetbrains.kotlin.fir.references.FirNamedReference +import org.jetbrains.kotlin.fir.references.FirSuperReference +import org.jetbrains.kotlin.fir.references.FirThisReference import org.jetbrains.kotlin.fir.renderer.* import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.SymbolInternals @@ -65,12 +69,17 @@ object FirDiagnosticRenderers { } } - val VARIABLE_NAME = Renderer { symbol: FirVariableSymbol<*> -> - symbol.name.asString() + val CALLEE_NAME = Renderer { element: FirExpression -> + when (val reference = element.unwrapSmartcastExpression().calleeReference) { + is FirNamedReference -> reference.name.asString() + is FirThisReference -> "this" + is FirSuperReference -> "super" + else -> "???" + } } - val FIR = Renderer { element: FirElement -> - element.render() + val VARIABLE_NAME = Renderer { symbol: FirVariableSymbol<*> -> + symbol.name.asString() } val DECLARATION_NAME = Renderer { symbol: FirBasedSymbol<*> -> diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index ee016ce3c3b..ea013c73882 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -20,8 +20,8 @@ import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.commaSeparated import org.jetbrains.kotlin.diagnostics.rendering.LanguageFeatureMessageRenderer import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.AMBIGUOUS_CALLS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.CALLEE_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FIR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FQ_NAMES_IN_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FUNCTIONAL_TYPE_KINDS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS_ON_NEWLINE_WITH_INDENT @@ -1254,7 +1254,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { SMARTCAST_IMPOSSIBLE, "Smart cast to ''{0}'' is impossible, because ''{1}'' is a {2}", RENDER_TYPE, - FIR, + CALLEE_NAME, TO_STRING, NOT_RENDERED ) @@ -1367,8 +1367,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { ) map.put( INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, - "Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported", - FIR, + "Invalid default value for inline function parameter. Only lambdas, anonymous functions, and callable references are supported", DECLARATION_NAME ) map.put( @@ -1898,36 +1897,37 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(LEAKED_IN_PLACE_LAMBDA, "Leaked in-place lambda: {0}", SYMBOL) map.put(FirErrors.WRONG_IMPLIES_CONDITION, "Wrong implies condition") map.put(UNREACHABLE_CODE, "Unreachable code", NOT_RENDERED, NOT_RENDERED) - map.put(SENSELESS_COMPARISON, "Condition ''{0}'' is always ''{1}''", FIR, TO_STRING) + map.put(SENSELESS_COMPARISON, "Condition is always ''{0}''", TO_STRING) map.put(SENSELESS_NULL_IN_WHEN, "Expression under 'when' is never equal to null") // Nullability map.put(USELESS_CALL_ON_NOT_NULL, "Unsafe call on not null") map.put( UNSAFE_CALL, - "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type {0}", + "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type ''{0}''.", RENDER_TYPE, - NOT_RENDERED, + NOT_RENDERED ) map.put( UNSAFE_IMPLICIT_INVOKE_CALL, - "Reference has a nullable type ''{0}'', use explicit \"?.invoke\" to make a function-like call instead.", + "Reference has a nullable type ''{0}'', use explicit ''?.invoke'' to make a function-like call instead.", RENDER_TYPE ) map.put( UNSAFE_INFIX_CALL, - "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})'' which is not allowed on a nullable receiver ''{0}''. " + - "Use ''?.''-qualified call instead", - FIR, - TO_STRING, - FIR, + "Infix call is not allowed on a nullable receiver of type ''{0}''. Use ''?.''-qualified call instead.", + RENDER_TYPE, + NOT_RENDERED, + NOT_RENDERED, + NOT_RENDERED, ) map.put( UNSAFE_OPERATOR_CALL, - "Operator call corresponds to a dot-qualified call ''{0}.{1}({2})'' which is not allowed on a nullable receiver ''{0}''. ", - FIR, - TO_STRING, - FIR, + "Operator call is not allowed on a nullable receiver of type ''{0}''. Use ''?.''-qualified call instead.", + RENDER_TYPE, + NOT_RENDERED, + NOT_RENDERED, + NOT_RENDERED, ) map.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE) map.put(NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION, "Non-null assertion (!!) is called on a lambda 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 740c1fc4edd..e0ce80ff682 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 @@ -200,6 +200,7 @@ private fun mapUnsafeCallError( return if (operationSource?.getChild(KtTokens.IDENTIFIER) != null) { FirErrors.UNSAFE_INFIX_CALL.createOn( source, + rootCause.actualType, receiverExpression, candidateFunctionName!!.asString(), singleArgument, @@ -207,6 +208,7 @@ private fun mapUnsafeCallError( } else { FirErrors.UNSAFE_OPERATOR_CALL.createOn( source, + rootCause.actualType, receiverExpression, candidateFunctionName!!.asString(), singleArgument, diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/references/FirReferenceUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/references/FirReferenceUtils.kt index 85909039621..e4fc5de7638 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/references/FirReferenceUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/references/FirReferenceUtils.kt @@ -70,3 +70,10 @@ fun FirReference.isError(): Boolean { else -> false } } + +fun FirReference.toNameString(): String? = when (this) { + is FirNamedReference -> name.asString() + is FirThisReference -> "this" + is FirSuperReference -> "super" + else -> null +} diff --git a/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.diag.txt b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.diag.txt new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.diag.txt @@ -0,0 +1 @@ + diff --git a/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.fir.diag.txt b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.fir.diag.txt new file mode 100644 index 00000000000..b7cbd33d46c --- /dev/null +++ b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.fir.diag.txt @@ -0,0 +1 @@ +/complexExpression.fir.kt:(75,121): warning: Condition is always 'false' diff --git a/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.fir.kt b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.fir.kt new file mode 100644 index 00000000000..c19564df34d --- /dev/null +++ b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.fir.kt @@ -0,0 +1,7 @@ +// RENDER_DIAGNOSTICS_FULL_TEXT + +fun String?.repro(): Boolean { + return this?.let { + return false + } == true +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt new file mode 100644 index 00000000000..3cc0ae92d2b --- /dev/null +++ b/compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt @@ -0,0 +1,7 @@ +// RENDER_DIAGNOSTICS_FULL_TEXT + +fun String?.repro(): Boolean { + return this?.let { + return false + } == true +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/smartCastOnAlienPropertyFromInvisibleClass.fir.diag.txt b/compiler/testData/diagnostics/tests/smartCasts/smartCastOnAlienPropertyFromInvisibleClass.fir.diag.txt index b565c5a09dc..c80547a840a 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/smartCastOnAlienPropertyFromInvisibleClass.fir.diag.txt +++ b/compiler/testData/diagnostics/tests/smartCasts/smartCastOnAlienPropertyFromInvisibleClass.fir.diag.txt @@ -1,3 +1,3 @@ -/B.kt:(133,134): error: Smart cast to 'kotlin/String' is impossible, because 'this@R|/Derived|.R|/Base.x|' is a public API property declared in different module +/B.kt:(133,134): error: Smart cast to 'kotlin/String' is impossible, because 'x' is a public API property declared in different module -/B.kt:(265,268): error: Smart cast to 'kotlin/String' is impossible, because 'R|/i|.R|/Base.x|' is a public API property declared in different module +/B.kt:(265,268): error: Smart cast to 'kotlin/String' is impossible, because 'x' is a public API property declared in different module diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 7fbcfef9576..b9381811bcd 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -30670,6 +30670,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/senselessComparison"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("complexExpression.kt") + public void testComplexExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/senselessComparison/complexExpression.kt"); + } + @Test @TestMetadata("noExplicitType.kt") public void testNoExplicitType() throws Exception {