From c507d1c938efb71ec4fb869e5767bda4952d8a3a Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Wed, 2 Jun 2021 16:03:21 +0300 Subject: [PATCH] [FIR] Implement OPERATOR_RENAMED_ON_IMPORT diagnostic --- .../diagnostics/FirDiagnosticsList.kt | 2 ++ .../fir/analysis/diagnostics/FirErrors.kt | 1 + .../checkers/declaration/FirImportsChecker.kt | 22 +++++++++++++++++++ .../diagnostics/FirDefaultErrorMessages.kt | 2 ++ .../imports/OperatorRenameOnImport.fir.kt | 16 -------------- .../tests/imports/OperatorRenameOnImport.kt | 1 + .../diagnostics/KtFirDataClassConverters.kt | 6 +++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 4 ++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 7 ++++++ 9 files changed, 45 insertions(+), 16 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.fir.kt 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 28157f6cffa..9981bb88264 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 @@ -955,6 +955,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val CONFLICTING_IMPORT by error(PositioningStrategy.IMPORT_LAST_NAME) { parameter("name") } + + val OPERATOR_RENAMED_ON_IMPORT by error(PositioningStrategy.IMPORT_LAST_NAME) } } 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 7a9cb9aac4b..dec17032ce8 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 @@ -524,5 +524,6 @@ object FirErrors { val PACKAGE_CANNOT_BE_IMPORTED by error0(SourceElementPositioningStrategies.IMPORT_LAST_NAME) val CANNOT_BE_IMPORTED by error1(SourceElementPositioningStrategies.IMPORT_LAST_NAME) val CONFLICTING_IMPORT by error1(SourceElementPositioningStrategies.IMPORT_LAST_NAME) + val OPERATOR_RENAMED_ON_IMPORT by error0(SourceElementPositioningStrategies.IMPORT_LAST_NAME) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt index 862348f0518..7e9224a4ed7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImportsChecker.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.types.expressions.OperatorConventions object FirImportsChecker : FirFileChecker() { override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) { @@ -25,6 +26,9 @@ object FirImportsChecker : FirFileChecker() { } if (!import.isAllUnder) { checkCanBeImported(import, context, reporter) + if (import is FirResolvedImport) { + checkOperatorRename(import, context, reporter) + } } } checkConflictingImports(declaration.imports, context, reporter) @@ -88,6 +92,24 @@ object FirImportsChecker : FirFileChecker() { } } + private fun checkOperatorRename(import: FirResolvedImport, context: CheckerContext, reporter: DiagnosticReporter) { + val alias = import.aliasName ?: return + val importedName = import.importedName ?: return + if (!OperatorConventions.isConventionName(alias)) return + val classId = import.resolvedClassId + val illegalRename = if (classId != null) { + val classFir = classId.resolveToClass(context) ?: return + classFir.classKind.isSingleton && classFir.declarations.any { it is FirSimpleFunction && it.isOperator} + } else { + context.session.symbolProvider.getTopLevelFunctionSymbols(import.packageFqName, importedName).any { + it.fir.isOperator + } + } + if (illegalRename) { + reporter.reportOn(import.source, FirErrors.OPERATOR_RENAMED_ON_IMPORT, context) + } + } + private fun FirResolvedImport.resolvesToClass(context: CheckerContext): Boolean { if (resolvedClassId != null) { if (isAllUnder) return true 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 d23b13b3acb..381e1ae85d1 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 @@ -228,6 +228,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_SUPERTYP 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 import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BOUND_ALLOWED +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_ON_IMPORT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER @@ -1180,6 +1181,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { "Conflicting import, imported name ''{0}'' is ambiguous", TO_STRING ) + map.put(OPERATOR_RENAMED_ON_IMPORT, "Operator renamed to a different operator on import") // Extended checkers group map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier") diff --git a/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.fir.kt b/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.fir.kt deleted file mode 100644 index 46466062ea0..00000000000 --- a/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER -// FILE: a.kt -package a - -interface A - -operator fun A.plus(other: A): A = this - -// FILE: b.kt -package b - -import a.A -import a.plus as minus - -fun test(a1: A, a2: A) = - a1 - a2 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt b/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt index 2eb9e432679..b268ab7c4c9 100644 --- a/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt +++ b/compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER // FILE: a.kt package a 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 c772dce5df9..136cff54041 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 @@ -2601,6 +2601,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.OPERATOR_RENAMED_ON_IMPORT) { firDiagnostic -> + OperatorRenamedOnImportImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirJvmErrors.CONFLICTING_JVM_DECLARATIONS) { firDiagnostic -> ConflictingJvmDeclarationsImpl( 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 75536f2f1fa..26e33bf598c 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 @@ -1825,6 +1825,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val name: Name } + abstract class OperatorRenamedOnImport : KtFirDiagnostic() { + override val diagnosticClass get() = OperatorRenamedOnImport::class + } + abstract class ConflictingJvmDeclarations : KtFirDiagnostic() { override val diagnosticClass get() = ConflictingJvmDeclarations::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 cfea3aebb03..c7aab0056e5 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 @@ -2960,6 +2960,13 @@ internal class ConflictingImportImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class OperatorRenamedOnImportImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.OperatorRenamedOnImport(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ConflictingJvmDeclarationsImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken,