[FIR] Implement CANNOT_BE_IMPORTED diagnostic

This commit is contained in:
Andrey Zinovyev
2021-06-02 11:18:02 +03:00
committed by Space
parent bf153ab0f0
commit 14789cb9e5
12 changed files with 95 additions and 12 deletions
@@ -945,6 +945,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error<KtSimpleNameExpression>(PositioningStrategy.IMPORT_LAST_NAME) {
parameter<Name>("objectName")
}
val PACKAGE_CANNOT_BE_IMPORTED by error<KtSimpleNameExpression>(PositioningStrategy.IMPORT_LAST_NAME)
val CANNOT_BE_IMPORTED by error<KtSimpleNameExpression>(PositioningStrategy.IMPORT_LAST_NAME) {
parameter<Name>("name")
}
}
}
@@ -520,5 +520,7 @@ object FirErrors {
// Imports
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtSimpleNameExpression, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
val PACKAGE_CANNOT_BE_IMPORTED by error0<KtSimpleNameExpression>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
val CANNOT_BE_IMPORTED by error1<KtSimpleNameExpression, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
}
@@ -16,9 +16,13 @@ import org.jetbrains.kotlin.name.ClassId
object FirImportsChecker : FirFileChecker() {
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
declaration.imports.forEach { import ->
if (import.isAllUnder && import !is FirResolvedImport && import !is FirErrorImport) {
if (import is FirErrorImport) return@forEach
if (import.isAllUnder && import !is FirResolvedImport) {
checkAllUnderFromEnumEntry(import, context, reporter)
}
if (!import.isAllUnder) {
checkCanBeImported(import, context, reporter)
}
}
}
@@ -32,4 +36,33 @@ object FirImportsChecker : FirFileChecker() {
reporter.reportOn(import.source, FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON, classFir.name, context)
}
}
private fun checkCanBeImported(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) {
val importedFqName = import.importedFqName ?: return
val importedName = importedFqName.shortName()
//empty name come from LT in some erroneous cases
if (importedName.isSpecial || importedName.identifier.isEmpty()) return
val classId = (import as? FirResolvedImport)?.resolvedClassId
if (classId != null) {
val classSymbol = context.session.symbolProvider.getClassLikeSymbolByFqName(classId) ?: return
val classFir = classSymbol.fir as? FirRegularClass ?: return
if (classFir.classKind.isSingleton) return
val illegalImport = classFir.declarations.any {
it is FirSimpleFunction && !it.isStatic && it.name == importedName ||
it is FirProperty && it.name == importedName
}
if (illegalImport) {
reporter.reportOn(import.source, FirErrors.CANNOT_BE_IMPORTED, importedName, context)
}
} else {
val importedClassId = ClassId.topLevel(importedFqName)
if (context.session.symbolProvider.getClassLikeSymbolByFqName(importedClassId) != null) {
return
}
context.session.symbolProvider.getPackage(importedFqName)?.let {
reporter.reportOn(import.source, FirErrors.PACKAGE_CANNOT_BE_IMPORTED, context)
}
}
}
}
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BREAK_OR_CONTINUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_BE_IMPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_INFER_PARAMETER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE
@@ -229,6 +230,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BO
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
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_CANNOT_BE_IMPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_CLASS_MEMBER_FROM_INLINE
@@ -1166,6 +1168,12 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
"Cannot import-on-demand from object ''{0}''",
TO_STRING
)
map.put(PACKAGE_CANNOT_BE_IMPORTED, "Packages cannot be imported")
map.put(
CANNOT_BE_IMPORTED,
"Cannot import ''{0}'', functions and properties can be imported only from packages or objects",
TO_STRING
)
// Extended checkers group
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
@@ -14,8 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildErrorImport
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.lookupTracker
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeImportFromSingleton
@@ -11,7 +11,7 @@ class X
// FILE: c.kt
package c
import a.x
import b.x
import a.<!PACKAGE_CANNOT_BE_IMPORTED!>x<!>
import b.<!PACKAGE_CANNOT_BE_IMPORTED!>x<!>
class Y : <!UNRESOLVED_REFERENCE!>x.X<!>
@@ -57,4 +57,4 @@ import a.<!SYNTAX!>%<!>.b.c.<!SYNTAX!><!>
import a.b.c.D.<!SYNTAX!><!>
import a.b.c.D.E.<!SYNTAX!><!>
import a<!SYNTAX!>?.<!><!SYNTAX!>b<!>
import <!PACKAGE_CANNOT_BE_IMPORTED!>a<!><!SYNTAX!>?.<!><!SYNTAX!>b<!>
@@ -48,17 +48,17 @@ class D {
// FILE:c.kt
import a
import a.b
import <!PACKAGE_CANNOT_BE_IMPORTED!>a<!>
import a.<!PACKAGE_CANNOT_BE_IMPORTED!>b<!>
import a.foo
import a.foo.bar
import a.bar
import a.bar.foo
import a.B.foo
import a.B.<!CANNOT_BE_IMPORTED!>foo<!>
import a.B.foo.bar
import a.B.bar
import a.B.<!CANNOT_BE_IMPORTED!>bar<!>
import a.B.bar.foo
import a.C.foo
+1 -1
View File
@@ -8,7 +8,7 @@ import reflect.Constructor
import b.*
import d
import d.Test
import b.d
import b.<!PACKAGE_CANNOT_BE_IMPORTED!>d<!>
class Some: <!UNRESOLVED_REFERENCE!>Test<!>()
@@ -2580,6 +2580,19 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.PACKAGE_CANNOT_BE_IMPORTED) { firDiagnostic ->
PackageCannotBeImportedImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.CANNOT_BE_IMPORTED) { firDiagnostic ->
CannotBeImportedImpl(
firDiagnostic.a,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirJvmErrors.CONFLICTING_JVM_DECLARATIONS) { firDiagnostic ->
ConflictingJvmDeclarationsImpl(
firDiagnostic as FirPsiDiagnostic<*>,
@@ -1810,6 +1810,15 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val objectName: Name
}
abstract class PackageCannotBeImported : KtFirDiagnostic<KtSimpleNameExpression>() {
override val diagnosticClass get() = PackageCannotBeImported::class
}
abstract class CannotBeImported : KtFirDiagnostic<KtSimpleNameExpression>() {
override val diagnosticClass get() = CannotBeImported::class
abstract val name: Name
}
abstract class ConflictingJvmDeclarations : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ConflictingJvmDeclarations::class
}
@@ -2936,6 +2936,21 @@ internal class CannotAllUnderImportFromSingletonImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class PackageCannotBeImportedImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.PackageCannotBeImported(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class CannotBeImportedImpl(
override val name: Name,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.CannotBeImported(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ConflictingJvmDeclarationsImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,