diff --git a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt index a1a92464668..468f9bcaf2a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt +++ b/compiler/fir/analysis-tests/testData/resolve/arrays/arraySetWithOperation.kt @@ -32,5 +32,5 @@ fun test_3(a: A) { } fun test_4(b: B) { - b[0] += B() // unresolved + b[0] += B() // unresolved } 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 c1a05326a4a..c216f004c28 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 @@ -49,6 +49,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { PRIVATE_MODIFIER, COMPANION_OBJECT, CONST_MODIFIER, + ARRAY_ACCESS ; 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 3f1efa1539d..304502b2261 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 @@ -515,6 +515,11 @@ object DIAGNOSTICS_LIST : DiagnosticList() { } } + val CONVENTIONS by object : DiagnosticGroup("Conventions") { + val NO_GET_METHOD by error(PositioningStrategy.ARRAY_ACCESS) + val NO_SET_METHOD by error(PositioningStrategy.ARRAY_ACCESS) + } + val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") { val REDUNDANT_VISIBILITY_MODIFIER by warning(PositioningStrategy.VISIBILITY_MODIFIER) val REDUNDANT_MODALITY_MODIFIER by warning(PositioningStrategy.MODALITY_MODIFIER) 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 d9fd8e5f420..51104193e1a 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 @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration @@ -307,6 +308,10 @@ object FirErrors { // Function contracts val ERROR_IN_CONTRACT_DESCRIPTION by error1(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) + // Conventions + val NO_GET_METHOD by error0(SourceElementPositioningStrategies.ARRAY_ACCESS) + val NO_SET_METHOD by error0(SourceElementPositioningStrategies.ARRAY_ACCESS) + // Extended checkers val REDUNDANT_VISIBILITY_MODIFIER by warning0(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val REDUNDANT_MODALITY_MODIFIER by warning0(SourceElementPositioningStrategies.MODALITY_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConventionFunctionCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConventionFunctionCallChecker.kt new file mode 100644 index 00000000000..a1c61322773 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConventionFunctionCallChecker.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError +import org.jetbrains.kotlin.util.OperatorNameConventions + +object FirConventionFunctionCallChecker : FirFunctionCallChecker() { + override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { + val calleeReference = expression.calleeReference as? FirErrorNamedReference ?: return + val diagnostic = calleeReference.diagnostic as? ConeUnresolvedNameError ?: return + + if (expression.calleeReference.source?.kind == FirFakeSourceElementKind.ArrayAccessNameReference) { + when (diagnostic.name) { + OperatorNameConventions.GET -> reporter.reportOn(calleeReference.source, FirErrors.NO_GET_METHOD, context) + OperatorNameConventions.SET -> reporter.reportOn(calleeReference.source, FirErrors.NO_SET_METHOD, context) + } + } + } +} 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 d787ae649a1..24305e7e4f1 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 @@ -39,6 +39,10 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect ?: errorNamedReference.source ?: return // 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 && + errorNamedReference.diagnostic is ConeUnresolvedNameError + ) return reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter, data) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 798d6d6bd93..dd12550c257 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -139,6 +139,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_GET_METHOD +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SET_METHOD import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER @@ -679,6 +681,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { // Function contracts map.put(ERROR_IN_CONTRACT_DESCRIPTION, "Error in contract description", TO_STRING) + // Conventions + map.put(NO_GET_METHOD, "No get method providing array access") + map.put(NO_SET_METHOD, "No set method providing array access") + // Extended checkers group map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier") map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier") 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 f5255345982..50ae701a137 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 @@ -415,6 +415,17 @@ object LightTreePositioningStrategies { return markElement(tree.ifKeyword(node) ?: node, startOffset, endOffset, tree, node) } } + + val ARRAY_ACCESS = object : LightTreePositioningStrategy() { + override fun mark( + node: LighterASTNode, + startOffset: Int, + endOffset: Int, + tree: FlyweightCapableTreeStructure + ): List { + return markElement(tree.findChildByType(node, KtNodeTypes.INDICES)!!, startOffset, endOffset, tree, node) + } + } } fun FirSourceElement.hasValOrVar(): Boolean = 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 69b214cb13e..41e8cfe9de7 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 @@ -143,4 +143,8 @@ object SourceElementPositioningStrategies { PositioningStrategies.IF_EXPRESSION ) + val ARRAY_ACCESS = SourceElementPositioningStrategy( + LightTreePositioningStrategies.ARRAY_ACCESS, + PositioningStrategies.ARRAY_ACCESS + ) } diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt index 4f958d3d0fc..143921bf468 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt @@ -26,7 +26,9 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirSealedClassConstructorCallChecker, ) - override val functionCallCheckers: Set = setOf() + override val functionCallCheckers: Set = setOf( + FirConventionFunctionCallChecker, + ) override val tryExpressionCheckers: Set = setOf( FirCatchParameterChecker diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index a50d29e6045..39e6afd4b9c 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -825,10 +825,11 @@ class ExpressionsConverter( } val getArgument = context.arraySetArgument.remove(arrayAccess) return buildFunctionCall { - source = arrayAccess.toFirSourceElement() + val isGet = getArgument == null + source = (if (isGet) arrayAccess else arrayAccess.getParent()!!).toFirSourceElement() calleeReference = buildSimpleNamedReference { - source = this@buildFunctionCall.source - name = if (getArgument == null) OperatorNameConventions.GET else OperatorNameConventions.SET + source = arrayAccess.toFirSourceElement().fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) + name = if (isGet) OperatorNameConventions.GET else OperatorNameConventions.SET } explicitReceiver = firExpression argumentList = buildArgumentList { diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index b2ad391072e..fcbf9768f0b 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -28,8 +28,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.scopes.FirScopeProvider -import org.jetbrains.kotlin.name.CallableId -import org.jetbrains.kotlin.name.LocalCallableIdConstructor import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.* @@ -38,7 +36,9 @@ import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection import org.jetbrains.kotlin.lexer.KtTokens.* +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.LocalCallableIdConstructor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* @@ -1931,23 +1931,14 @@ open class RawFirBuilder( override fun visitArrayAccessExpression(expression: KtArrayAccessExpression, data: Unit): FirElement { val arrayExpression = expression.arrayExpression + val getArgument = context.arraySetArgument.remove(expression) return buildFunctionCall { - val source: FirPsiSourceElement<*> - val getArgument = context.arraySetArgument.remove(expression) - if (getArgument != null) { - calleeReference = buildSimpleNamedReference { - source = expression.parent.toFirSourceElement() - this.source = source.fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) - name = OperatorNameConventions.SET - } - } else { - source = expression.toFirSourceElement() - calleeReference = buildSimpleNamedReference { - this.source = source.fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) - name = OperatorNameConventions.GET - } + val isGet = getArgument == null + source = (if (isGet) expression else expression.parent).toFirSourceElement() + calleeReference = buildSimpleNamedReference { + source = expression.toFirSourceElement().fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) + name = if (isGet) OperatorNameConventions.GET else OperatorNameConventions.SET } - this.source = source explicitReceiver = arrayExpression.toFirExpression("No array expression") argumentList = buildArgumentList { for (indexExpression in expression.indexExpressions) { diff --git a/compiler/testData/diagnostics/tests/LValueAssignment.fir.kt b/compiler/testData/diagnostics/tests/LValueAssignment.fir.kt index ef18c4e661c..313f2cb9980 100644 --- a/compiler/testData/diagnostics/tests/LValueAssignment.fir.kt +++ b/compiler/testData/diagnostics/tests/LValueAssignment.fir.kt @@ -128,7 +128,7 @@ class Test() { (f@ a)[3] = 4 - this[54] = 34 + this[54] = 34 } } diff --git a/compiler/testData/diagnostics/tests/annotations/rendering/memberProjectedOut.fir.kt b/compiler/testData/diagnostics/tests/annotations/rendering/memberProjectedOut.fir.kt index 4c0852edda9..42f6c83229a 100644 --- a/compiler/testData/diagnostics/tests/annotations/rendering/memberProjectedOut.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/rendering/memberProjectedOut.fir.kt @@ -12,5 +12,5 @@ class C { } fun test(a: C) { - a[1] = 25 + a[1] = 25 } diff --git a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt index cc17a127e45..bb6927c297d 100644 --- a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt +++ b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSet.fir.kt @@ -31,5 +31,5 @@ fun test() { D[0] = "" D[0] = 2.72 - Z[0] = "" + Z[0] = "" } diff --git a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSetTooManyArgs.fir.kt b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSetTooManyArgs.fir.kt index a3725af26f9..05cb5f29c98 100644 --- a/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSetTooManyArgs.fir.kt +++ b/compiler/testData/diagnostics/tests/checkArguments/arrayAccessSetTooManyArgs.fir.kt @@ -6,6 +6,6 @@ class A { operator fun set(x: String, value: Int) {} fun d(x: Int) { - this["", 1] = 1 + this["", 1] = 1 } } diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/noCollectionLiterals.fir.kt b/compiler/testData/diagnostics/tests/collectionLiterals/noCollectionLiterals.fir.kt index 8d9d3afaa65..6525f070c28 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/noCollectionLiterals.fir.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/noCollectionLiterals.fir.kt @@ -1,7 +1,7 @@ // !WITH_NEW_INFERENCE fun test(): Array { [1, 2] - [1, 2][0] + [1, 2][0] [1, 2].get(0) foo([""]) diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutConventions.fir.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutConventions.fir.kt index 2ce7570c7cb..3dd7ce34287 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutConventions.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/projectedOutConventions.fir.kt @@ -9,6 +9,6 @@ class A { fun test(a: A) { a + "" - a[1] = "" + a[1] = "" a[""] } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/typeMismatchConventions.fir.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/typeMismatchConventions.fir.kt index 2de22c03be5..bf1c53064b6 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/typeMismatchConventions.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/typeMismatchConventions.fir.kt @@ -11,7 +11,7 @@ class Out fun test(a: A, y: Out) { a + y - a[1] = y + a[1] = y a[y] a + Out() diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/arrayExpression.fir.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/arrayExpression.fir.kt index 72d6ba7470d..a62c7f0d096 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/arrayExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/arrayExpression.fir.kt @@ -4,5 +4,5 @@ package bar fun main() { class Some - Some[] names = ["ads"] + Some[] names = ["ads"] } diff --git a/compiler/testData/diagnostics/tests/incompleteCode/kt4866UnresolvedArrayAccess.fir.kt b/compiler/testData/diagnostics/tests/incompleteCode/kt4866UnresolvedArrayAccess.fir.kt index 63e21a0e0a6..75a8fcd6427 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/kt4866UnresolvedArrayAccess.fir.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/kt4866UnresolvedArrayAccess.fir.kt @@ -1,5 +1,5 @@ //KT-4866 Resolve does not work inside brackets with unresolved reference before fun test(i: Int, j: Int) { - foo[i, j] -} \ No newline at end of file + foo[i, j] +} diff --git a/compiler/testData/diagnostics/tests/inference/kt28598.fir.kt b/compiler/testData/diagnostics/tests/inference/kt28598.fir.kt index 79603513ffe..f58ab2ccf1d 100644 --- a/compiler/testData/diagnostics/tests/inference/kt28598.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/kt28598.fir.kt @@ -15,7 +15,7 @@ fun case_1(a: MutableListg[0] + val h = g[0] if (h != null) { h.inc() } @@ -43,7 +43,7 @@ fun case_2(a: MutableListg[0] // no SMARTCAST diagnostic + val h = g[0] // no SMARTCAST diagnostic if (h != null) { h.inc() } diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.fir.kt deleted file mode 100644 index c05704fda35..00000000000 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.fir.kt +++ /dev/null @@ -1,31 +0,0 @@ -// FILE: J.java - -import org.jetbrains.annotations.*; - -public class J { - @NotNull - public static Integer[] staticNN; - @Nullable - public static Integer[] staticN; - public static Integer[] staticJ; -} - -// FILE: k.kt - -fun test() { - // @NotNull platform type - val platformNN = J.staticNN - // @Nullable platform type - val platformN = J.staticN - // platform type with no annotation - val platformJ = J.staticJ - - platformNN[0] - platformN[0] - platformJ[0] - - platformNN[0] = 1 - platformN[0] = 1 - platformJ[0] = 1 -} - diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt index acf93ae0567..c8c27446120 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: J.java import org.jetbrains.annotations.*; diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.fir.kt deleted file mode 100644 index ae8754ed694..00000000000 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.fir.kt +++ /dev/null @@ -1,31 +0,0 @@ -// FILE: J.java - -import org.jetbrains.annotations.*; - -public class J { - @NotNull - public static int[] staticNN; - @Nullable - public static int[] staticN; - public static int[] staticJ; -} - -// FILE: k.kt - -fun test() { - // @NotNull platform type - val platformNN = J.staticNN - // @Nullable platform type - val platformN = J.staticN - // platform type with no annotation - val platformJ = J.staticJ - - platformNN[0] - platformN[0] - platformJ[0] - - platformNN[0] = 1 - platformN[0] = 1 - platformJ[0] = 1 -} - diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.kt index 63d41a2ccb6..a48ea4711c6 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/primitiveArray.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: J.java import org.jetbrains.annotations.*; diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt2865.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/kt2865.fir.kt index fe257d907eb..b45e99f82f0 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt2865.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt2865.fir.kt @@ -7,6 +7,6 @@ fun foo(a: MutableMap, x: String?) { } fun foo1(a: MutableMap, x: String?) { - a[x] = x!! + a[x] = x!! a[x!!] = x } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/15.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/15.fir.kt index 6e15f53f9f1..895bd4ef64d 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/15.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/15.fir.kt @@ -96,7 +96,7 @@ fun case_7() { fun case_8(y: MutableList) { var x: Boolean? = true if (x != null) { - y[if (true) {x = null;0} else 0] = x + y[if (true) {x = null;0} else 0] = x } } @@ -130,6 +130,6 @@ fun case_10() { fun case_11(y: MutableList>) { var x: Int? = 10 if (x != null) { - y[if (true) {x = null;0} else 0][x] = 10 + y[if (true) {x = null;0} else 0][x] = 10 } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/28.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/28.fir.kt index 6b73e404062..18806d60f39 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/28.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/28.fir.kt @@ -6,6 +6,6 @@ fun > Inv.case_1() { if (this is MutableList<*>) { & kotlin.collections.MutableList<*> & Inv")!>this - & kotlin.collections.MutableList<*> & Inv")!>this[0] = & kotlin.collections.MutableList<*> & Inv")!>this[1] + & kotlin.collections.MutableList<*> & Inv")!>this[0] = & kotlin.collections.MutableList<*> & Inv")!>this[1] } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index e10fef36bcd..3e803848417 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration @@ -1402,6 +1403,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.NO_GET_METHOD) { firDiagnostic -> + NoGetMethodImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.NO_SET_METHOD) { firDiagnostic -> + NoSetMethodImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.REDUNDANT_VISIBILITY_MODIFIER) { firDiagnostic -> RedundantVisibilityModifierImpl( firDiagnostic as FirPsiDiagnostic<*>, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 830c4a3463e..4b026b1a13d 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration @@ -987,6 +988,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val reason: String } + abstract class NoGetMethod : KtFirDiagnostic() { + override val diagnosticClass get() = NoGetMethod::class + } + + abstract class NoSetMethod : KtFirDiagnostic() { + override val diagnosticClass get() = NoSetMethod::class + } + abstract class RedundantVisibilityModifier : KtFirDiagnostic() { override val diagnosticClass get() = RedundantVisibilityModifier::class } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index e6d720e6cf4..a626ce7067c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration @@ -1597,6 +1598,20 @@ internal class ErrorInContractDescriptionImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class NoGetMethodImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.NoGetMethod(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class NoSetMethodImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.NoSetMethod(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class RedundantVisibilityModifierImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken,