[FIR] Implement CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON diagnostic
This commit is contained in:
+6
@@ -940,6 +940,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<Symbol>("symbol")
|
||||
}
|
||||
}
|
||||
|
||||
val IMPORTS by object : DiagnosticGroup("Imports") {
|
||||
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error<KtSimpleNameExpression>(PositioningStrategy.IMPORT_LAST_NAME) {
|
||||
parameter<Name>("objectName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val exposedVisibilityDiagnosticInit: DiagnosticBuilder.() -> Unit = {
|
||||
|
||||
+1
@@ -73,6 +73,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
QUESTION_MARK_BY_TYPE,
|
||||
ANNOTATION_USE_SITE,
|
||||
ASSIGNMENT_LHS,
|
||||
IMPORT_LAST_NAME,
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -518,4 +518,7 @@ object FirErrors {
|
||||
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error2<KtElement, AbstractFirBasedSymbol<*>, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val SUPER_CALL_FROM_PUBLIC_INLINE by warning1<KtElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
// Imports
|
||||
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtSimpleNameExpression, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -100,6 +100,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirKClassWithIncorrectTypeArgumentChecker,
|
||||
FirTopLevelFunctionsChecker,
|
||||
FirTopLevelPropertiesChecker,
|
||||
FirImportsChecker,
|
||||
)
|
||||
|
||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.declaration
|
||||
|
||||
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.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
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) {
|
||||
checkAllUnderFromEnumEntry(import, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAllUnderFromEnumEntry(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val fqName = import.importedFqName ?: return
|
||||
if (fqName.isRoot || fqName.parent().isRoot) return
|
||||
val classId = ClassId.topLevel(fqName.parent())
|
||||
val classSymbol = context.session.symbolProvider.getClassLikeSymbolByFqName(classId) ?: return
|
||||
val classFir = classSymbol.fir as? FirRegularClass ?: return
|
||||
if (classFir.isEnumClass && classFir.collectEnumEntries().any { it.name == fqName.shortName() }) {
|
||||
reporter.reportOn(import.source, FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON, classFir.name, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.*
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
|
||||
+6
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
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.declarations.FirErrorImport
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
@@ -94,6 +95,11 @@ class ErrorNodeDiagnosticCollectorComponent(
|
||||
reportFirDiagnostic(errorResolvedQualifier.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
override fun visitErrorImport(errorImport: FirErrorImport, data: CheckerContext) {
|
||||
val source = errorImport.source ?: return
|
||||
reportFirDiagnostic(errorImport.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
private fun reportFirDiagnostic(
|
||||
diagnostic: ConeDiagnostic,
|
||||
source: FirSourceElement,
|
||||
|
||||
+8
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BOUND_ON_TYPE_ALI
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP
|
||||
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_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
|
||||
@@ -1159,6 +1160,13 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
)
|
||||
map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL)
|
||||
|
||||
//imports
|
||||
map.put(
|
||||
CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON,
|
||||
"Cannot import-on-demand from object ''{0}''",
|
||||
TO_STRING
|
||||
)
|
||||
|
||||
// Extended checkers group
|
||||
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
|
||||
map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier")
|
||||
|
||||
+12
@@ -758,6 +758,18 @@ object LightTreePositioningStrategies {
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
|
||||
val IMPORT_LAST_NAME: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
val nodeToMark = tree.collectDescendantsOfType(node, KtNodeTypes.REFERENCE_EXPRESSION).lastOrNull() ?: node
|
||||
return markElement(nodeToMark, startOffset, endOffset, tree, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirSourceElement.hasValOrVar(): Boolean =
|
||||
|
||||
+5
@@ -252,4 +252,9 @@ object SourceElementPositioningStrategies {
|
||||
LightTreePositioningStrategies.ASSIGNMENT_LHS,
|
||||
PositioningStrategies.ASSIGNMENT_LHS
|
||||
)
|
||||
|
||||
val IMPORT_LAST_NAME = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.IMPORT_LAST_NAME,
|
||||
PositioningStrategies.IMPORT_LAST_NAME
|
||||
)
|
||||
}
|
||||
|
||||
+1
@@ -73,6 +73,7 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
||||
is ConeTypeParameterSupertype -> FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE.on(source, this.reason)
|
||||
is ConeTypeParameterInQualifiedAccess -> null // reported in various checkers instead
|
||||
is ConeNotAnnotationContainer -> null
|
||||
is ConeImportFromSingleton -> FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.on(source, this.name)
|
||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -122,6 +122,10 @@ class ConeCyclicTypeBound(val symbol: FirTypeParameterSymbol, val bounds: Immuta
|
||||
override val reason: String get() = "Type parameter ${symbol.fir.name} has cyclic bounds"
|
||||
}
|
||||
|
||||
class ConeImportFromSingleton(val name: Name) : ConeDiagnostic() {
|
||||
override val reason: String get() = "Import from singleton $name is not allowed"
|
||||
}
|
||||
|
||||
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
|
||||
return when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
||||
|
||||
+14
-1
@@ -5,14 +5,20 @@
|
||||
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
@@ -71,7 +77,14 @@ open class FirImportResolveTransformer protected constructor(
|
||||
get() = true
|
||||
|
||||
private fun transformImportForFqName(fqName: FqName, delegate: FirImport): FirImport {
|
||||
val (packageFqName, relativeClassFqName) = resolveToPackageOrClass(symbolProvider, fqName) ?: return delegate
|
||||
val (packageFqName, relativeClassFqName, classSymbol) = resolveToPackageOrClass(symbolProvider, fqName) ?: return delegate
|
||||
val firClass = classSymbol?.fir as? FirRegularClass
|
||||
if (delegate.isAllUnder && firClass?.classKind?.isSingleton == true) {
|
||||
return buildErrorImport {
|
||||
this.delegate = delegate
|
||||
this.diagnostic = ConeImportFromSingleton(firClass.name)
|
||||
}
|
||||
}
|
||||
return buildResolvedImport {
|
||||
this.delegate = delegate
|
||||
this.packageFqName = packageFqName
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.declarations
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirErrorImport : FirPureAbstractElement(), FirImport, FirDiagnosticHolder {
|
||||
abstract override val source: FirSourceElement?
|
||||
abstract override val importedFqName: FqName?
|
||||
abstract override val isAllUnder: Boolean
|
||||
abstract override val aliasName: Name?
|
||||
abstract override val diagnostic: ConeDiagnostic
|
||||
abstract val delegate: FirImport
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitErrorImport(this, data)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <E: FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
|
||||
transformer.transformErrorImport(this, data) as E
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -17,11 +16,11 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirImport : FirPureAbstractElement(), FirElement {
|
||||
abstract override val source: FirSourceElement?
|
||||
abstract val importedFqName: FqName?
|
||||
abstract val isAllUnder: Boolean
|
||||
abstract val aliasName: Name?
|
||||
interface FirImport : FirElement {
|
||||
override val source: FirSourceElement?
|
||||
val importedFqName: FqName?
|
||||
val isAllUnder: Boolean
|
||||
val aliasName: Name?
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitImport(this, data)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -17,7 +18,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirResolvedImport : FirImport() {
|
||||
abstract class FirResolvedImport : FirPureAbstractElement(), FirImport {
|
||||
abstract override val source: FirSourceElement?
|
||||
abstract override val importedFqName: FqName?
|
||||
abstract override val isAllUnder: Boolean
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.declarations.builder
|
||||
|
||||
import kotlin.contracts.*
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorImportImpl
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
@FirBuilderDsl
|
||||
class FirErrorImportBuilder {
|
||||
lateinit var diagnostic: ConeDiagnostic
|
||||
lateinit var delegate: FirImport
|
||||
|
||||
fun build(): FirErrorImport {
|
||||
return FirErrorImportImpl(
|
||||
diagnostic,
|
||||
delegate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun buildErrorImport(init: FirErrorImportBuilder.() -> Unit): FirErrorImport {
|
||||
contract {
|
||||
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return FirErrorImportBuilder().apply(init).build()
|
||||
}
|
||||
+1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.declarations.builder
|
||||
|
||||
import kotlin.contracts.*
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.declarations.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
internal class FirErrorImportImpl(
|
||||
override val diagnostic: ConeDiagnostic,
|
||||
override var delegate: FirImport,
|
||||
) : FirErrorImport() {
|
||||
override val source: FirSourceElement? get() = delegate.source
|
||||
override val importedFqName: FqName? get() = delegate.importedFqName
|
||||
override val isAllUnder: Boolean get() = delegate.isAllUnder
|
||||
override val aliasName: Name? get() = delegate.aliasName
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
delegate.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirErrorImportImpl {
|
||||
delegate = delegate.transform(transformer, data)
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -21,7 +22,7 @@ internal class FirImportImpl(
|
||||
override val importedFqName: FqName?,
|
||||
override val isAllUnder: Boolean,
|
||||
override val aliasName: Name?,
|
||||
) : FirImport() {
|
||||
) : FirPureAbstractElement(), FirImport {
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirImportImpl {
|
||||
|
||||
@@ -10,8 +10,6 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.FirTargetElement
|
||||
@@ -49,6 +47,9 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLoop
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop
|
||||
@@ -157,14 +158,6 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformElement(label, data)
|
||||
}
|
||||
|
||||
open fun transformImport(import: FirImport, data: D): FirImport {
|
||||
return transformElement(import, data)
|
||||
}
|
||||
|
||||
open fun transformResolvedImport(resolvedImport: FirResolvedImport, data: D): FirImport {
|
||||
return transformElement(resolvedImport, data)
|
||||
}
|
||||
|
||||
open fun <E> transformSymbolOwner(symbolOwner: FirSymbolOwner<E>, data: D): FirSymbolOwner<E> where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||
return transformElement(symbolOwner, data)
|
||||
}
|
||||
@@ -313,6 +306,18 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformElement(diagnosticHolder, data)
|
||||
}
|
||||
|
||||
open fun transformImport(import: FirImport, data: D): FirImport {
|
||||
return transformElement(import, data)
|
||||
}
|
||||
|
||||
open fun transformResolvedImport(resolvedImport: FirResolvedImport, data: D): FirImport {
|
||||
return transformElement(resolvedImport, data)
|
||||
}
|
||||
|
||||
open fun transformErrorImport(errorImport: FirErrorImport, data: D): FirImport {
|
||||
return transformElement(errorImport, data)
|
||||
}
|
||||
|
||||
open fun transformLoop(loop: FirLoop, data: D): FirStatement {
|
||||
return transformElement(loop, data)
|
||||
}
|
||||
@@ -661,14 +666,6 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformLabel(label, data)
|
||||
}
|
||||
|
||||
final override fun visitImport(import: FirImport, data: D): FirImport {
|
||||
return transformImport(import, data)
|
||||
}
|
||||
|
||||
final override fun visitResolvedImport(resolvedImport: FirResolvedImport, data: D): FirImport {
|
||||
return transformResolvedImport(resolvedImport, data)
|
||||
}
|
||||
|
||||
final override fun <E> visitSymbolOwner(symbolOwner: FirSymbolOwner<E>, data: D): FirSymbolOwner<E> where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||
return transformSymbolOwner(symbolOwner, data)
|
||||
}
|
||||
@@ -817,6 +814,18 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformDiagnosticHolder(diagnosticHolder, data)
|
||||
}
|
||||
|
||||
final override fun visitImport(import: FirImport, data: D): FirImport {
|
||||
return transformImport(import, data)
|
||||
}
|
||||
|
||||
final override fun visitResolvedImport(resolvedImport: FirResolvedImport, data: D): FirImport {
|
||||
return transformResolvedImport(resolvedImport, data)
|
||||
}
|
||||
|
||||
final override fun visitErrorImport(errorImport: FirErrorImport, data: D): FirImport {
|
||||
return transformErrorImport(errorImport, data)
|
||||
}
|
||||
|
||||
final override fun visitLoop(loop: FirLoop, data: D): FirStatement {
|
||||
return transformLoop(loop, data)
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.FirTargetElement
|
||||
@@ -49,6 +47,9 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLoop
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop
|
||||
@@ -148,10 +149,6 @@ abstract class FirVisitor<out R, in D> {
|
||||
|
||||
open fun visitLabel(label: FirLabel, data: D): R = visitElement(label, data)
|
||||
|
||||
open fun visitImport(import: FirImport, data: D): R = visitElement(import, data)
|
||||
|
||||
open fun visitResolvedImport(resolvedImport: FirResolvedImport, data: D): R = visitElement(resolvedImport, data)
|
||||
|
||||
open fun <E> visitSymbolOwner(symbolOwner: FirSymbolOwner<E>, data: D): R where E : FirSymbolOwner<E>, E : FirDeclaration = visitElement(symbolOwner, data)
|
||||
|
||||
open fun visitResolvable(resolvable: FirResolvable, data: D): R = visitElement(resolvable, data)
|
||||
@@ -226,6 +223,12 @@ abstract class FirVisitor<out R, in D> {
|
||||
|
||||
open fun visitDiagnosticHolder(diagnosticHolder: FirDiagnosticHolder, data: D): R = visitElement(diagnosticHolder, data)
|
||||
|
||||
open fun visitImport(import: FirImport, data: D): R = visitElement(import, data)
|
||||
|
||||
open fun visitResolvedImport(resolvedImport: FirResolvedImport, data: D): R = visitElement(resolvedImport, data)
|
||||
|
||||
open fun visitErrorImport(errorImport: FirErrorImport, data: D): R = visitElement(errorImport, data)
|
||||
|
||||
open fun visitLoop(loop: FirLoop, data: D): R = visitElement(loop, data)
|
||||
|
||||
open fun visitErrorLoop(errorLoop: FirErrorLoop, data: D): R = visitElement(errorLoop, data)
|
||||
|
||||
@@ -10,8 +10,6 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.FirTargetElement
|
||||
@@ -49,6 +47,9 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLoop
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop
|
||||
@@ -156,14 +157,6 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitElement(label)
|
||||
}
|
||||
|
||||
open fun visitImport(import: FirImport) {
|
||||
visitElement(import)
|
||||
}
|
||||
|
||||
open fun visitResolvedImport(resolvedImport: FirResolvedImport) {
|
||||
visitElement(resolvedImport)
|
||||
}
|
||||
|
||||
open fun <E> visitSymbolOwner(symbolOwner: FirSymbolOwner<E>) where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||
visitElement(symbolOwner)
|
||||
}
|
||||
@@ -312,6 +305,18 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitElement(diagnosticHolder)
|
||||
}
|
||||
|
||||
open fun visitImport(import: FirImport) {
|
||||
visitElement(import)
|
||||
}
|
||||
|
||||
open fun visitResolvedImport(resolvedImport: FirResolvedImport) {
|
||||
visitElement(resolvedImport)
|
||||
}
|
||||
|
||||
open fun visitErrorImport(errorImport: FirErrorImport) {
|
||||
visitElement(errorImport)
|
||||
}
|
||||
|
||||
open fun visitLoop(loop: FirLoop) {
|
||||
visitElement(loop)
|
||||
}
|
||||
@@ -660,14 +665,6 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitLabel(label)
|
||||
}
|
||||
|
||||
final override fun visitImport(import: FirImport, data: Nothing?) {
|
||||
visitImport(import)
|
||||
}
|
||||
|
||||
final override fun visitResolvedImport(resolvedImport: FirResolvedImport, data: Nothing?) {
|
||||
visitResolvedImport(resolvedImport)
|
||||
}
|
||||
|
||||
final override fun <E> visitSymbolOwner(symbolOwner: FirSymbolOwner<E>, data: Nothing?) where E : FirSymbolOwner<E>, E : FirDeclaration {
|
||||
visitSymbolOwner(symbolOwner)
|
||||
}
|
||||
@@ -816,6 +813,18 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitDiagnosticHolder(diagnosticHolder)
|
||||
}
|
||||
|
||||
final override fun visitImport(import: FirImport, data: Nothing?) {
|
||||
visitImport(import)
|
||||
}
|
||||
|
||||
final override fun visitResolvedImport(resolvedImport: FirResolvedImport, data: Nothing?) {
|
||||
visitResolvedImport(resolvedImport)
|
||||
}
|
||||
|
||||
final override fun visitErrorImport(errorImport: FirErrorImport, data: Nothing?) {
|
||||
visitErrorImport(errorImport)
|
||||
}
|
||||
|
||||
final override fun visitLoop(loop: FirLoop, data: Nothing?) {
|
||||
visitLoop(loop)
|
||||
}
|
||||
|
||||
+5
-2
@@ -14,8 +14,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
val typeRef = sealedElement("TypeRef", TypeRef, annotationContainer)
|
||||
val reference = element("Reference", Reference)
|
||||
val label = element("Label", Other)
|
||||
val import = element("Import", Declaration)
|
||||
val resolvedImport = element("ResolvedImport", Declaration, import)
|
||||
|
||||
val symbolOwner = element("SymbolOwner", Other)
|
||||
val resolvable = sealedElement("Resolvable", Expression)
|
||||
|
||||
@@ -64,6 +63,10 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
|
||||
val diagnosticHolder = element("DiagnosticHolder", Diagnostics)
|
||||
|
||||
val import = element("Import", Declaration)
|
||||
val resolvedImport = element("ResolvedImport", Declaration, import)
|
||||
val errorImport = element("ErrorImport", Declaration, import, diagnosticHolder)
|
||||
|
||||
val loop = sealedElement("Loop", Expression, statement, targetElement)
|
||||
val errorLoop = element("ErrorLoop", Expression, loop, diagnosticHolder)
|
||||
val doWhileLoop = element("DoWhileLoop", Expression, loop)
|
||||
|
||||
+4
@@ -65,6 +65,10 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
}
|
||||
|
||||
impl(errorImport) {
|
||||
delegateFields(listOf("aliasName", "importedFqName", "isAllUnder", "source"), "delegate")
|
||||
}
|
||||
|
||||
impl(annotationCall) {
|
||||
default("typeRef") {
|
||||
value = "annotationTypeRef"
|
||||
|
||||
+4
@@ -432,6 +432,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
)
|
||||
}
|
||||
|
||||
errorImport.configure {
|
||||
+field("delegate", import)
|
||||
}
|
||||
|
||||
annotationCall.configure {
|
||||
+field("useSiteTarget", annotationUseSiteTargetType, nullable = true)
|
||||
+field("annotationTypeRef", typeRef).withTransform()
|
||||
|
||||
@@ -890,6 +890,19 @@ object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
val IMPORT_LAST_NAME: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||
override fun mark(element: PsiElement): List<TextRange> {
|
||||
if (element is KtImportDirective) {
|
||||
val importedReference = element.importedReference
|
||||
if (importedReference is KtDotQualifiedExpression) {
|
||||
importedReference.selectorExpression?.let { return super.mark(it) }
|
||||
}
|
||||
return super.mark(element.importedReference ?: element)
|
||||
}
|
||||
return super.mark(element)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
+4
-4
@@ -60,12 +60,12 @@ class C3 {
|
||||
// FILE: b.kt
|
||||
package b
|
||||
|
||||
import a.C1.O.*
|
||||
import a.C1.<!CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON!>O<!>.*
|
||||
|
||||
fun testErroneusAllUnderImportFromObject() {
|
||||
A()
|
||||
B
|
||||
bar()
|
||||
<!UNRESOLVED_REFERENCE!>A<!>()
|
||||
<!UNRESOLVED_REFERENCE!>B<!>
|
||||
<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
}
|
||||
|
||||
// FILE: c.kt
|
||||
|
||||
@@ -54,12 +54,12 @@ object K: Base(), BaseI<Int> {
|
||||
// FILE: b.kt
|
||||
package b
|
||||
|
||||
import a.O.*
|
||||
import a.<!CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON!>O<!>.*
|
||||
|
||||
fun testErroneusAllUnderImportFromObject() {
|
||||
A()
|
||||
B
|
||||
bar()
|
||||
<!UNRESOLVED_REFERENCE!>A<!>()
|
||||
<!UNRESOLVED_REFERENCE!>B<!>
|
||||
<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
}
|
||||
|
||||
// FILE: c.kt
|
||||
|
||||
@@ -72,7 +72,7 @@ fun bar() {}
|
||||
//FILE:c.kt
|
||||
package c
|
||||
|
||||
import c.C.*
|
||||
import c.<!CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON!>C<!>.*
|
||||
|
||||
object C {
|
||||
fun f() {
|
||||
@@ -81,7 +81,7 @@ object C {
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
if (i == 3) f()
|
||||
if (<!UNRESOLVED_REFERENCE!>i<!> == 3) <!UNRESOLVED_REFERENCE!>f<!>()
|
||||
}
|
||||
|
||||
//FILE:d.kt
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package a
|
||||
|
||||
import a.A.*
|
||||
import a.A.C
|
||||
import a.A.C.*
|
||||
import a.A.D.*
|
||||
import a.A.C.*
|
||||
import a.A.C.G
|
||||
import a.A.E.J.*
|
||||
import a.A.CO.*
|
||||
import a.A.CO
|
||||
|
||||
import a.B.C.*
|
||||
import a.B.C.A.*
|
||||
import a.B.C.D.*
|
||||
|
||||
import a.E.*
|
||||
import a.E.E1
|
||||
import a.E.E2.*
|
||||
|
||||
class A {
|
||||
object C {
|
||||
object G
|
||||
}
|
||||
object D {
|
||||
|
||||
}
|
||||
|
||||
class E {
|
||||
object J
|
||||
}
|
||||
|
||||
companion object CO {
|
||||
object H
|
||||
}
|
||||
}
|
||||
|
||||
enum class E {
|
||||
E1, E2
|
||||
}
|
||||
|
||||
object B {
|
||||
class C {
|
||||
object A
|
||||
object D
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
package a
|
||||
|
||||
import a.A.*
|
||||
|
||||
@@ -75,7 +75,7 @@ fun bar() {}
|
||||
//FILE:c.kt
|
||||
package c
|
||||
|
||||
import c.C.*
|
||||
import c.<!CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON!>C<!>.*
|
||||
|
||||
object C {
|
||||
fun f() {
|
||||
@@ -84,7 +84,7 @@ object C {
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
if (i == 3) f()
|
||||
if (<!UNRESOLVED_REFERENCE!>i<!> == 3) <!UNRESOLVED_REFERENCE!>f<!>()
|
||||
}
|
||||
|
||||
//FILE:d.kt
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// import all members from companion object
|
||||
package c
|
||||
|
||||
import c.A.Companion.B
|
||||
import c.M.*
|
||||
|
||||
fun foo() {
|
||||
val b: B = B()
|
||||
var r: R = R()
|
||||
}
|
||||
|
||||
class A() {
|
||||
companion object {
|
||||
class B() {
|
||||
companion object {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object M {
|
||||
fun foo() {}
|
||||
class R() {}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// import all members from companion object
|
||||
package c
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package d
|
||||
|
||||
//import from objects before properties resolve
|
||||
|
||||
import d.A.*
|
||||
import d.<!CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON!>A<!>.*
|
||||
import d.M.R
|
||||
import d.M.R.bar
|
||||
import d.M.T
|
||||
@@ -14,7 +14,7 @@ val y: T = Y
|
||||
fun f() {
|
||||
bar()
|
||||
R.bar()
|
||||
B.foo()
|
||||
<!UNRESOLVED_REFERENCE!>B<!>.foo()
|
||||
}
|
||||
|
||||
object M {
|
||||
|
||||
+7
@@ -2573,6 +2573,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON) { firDiagnostic ->
|
||||
CannotAllUnderImportFromSingletonImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJvmErrors.CONFLICTING_JVM_DECLARATIONS) { firDiagnostic ->
|
||||
ConflictingJvmDeclarationsImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
|
||||
+5
@@ -1805,6 +1805,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val symbol: KtSymbol
|
||||
}
|
||||
|
||||
abstract class CannotAllUnderImportFromSingleton : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||
override val diagnosticClass get() = CannotAllUnderImportFromSingleton::class
|
||||
abstract val objectName: Name
|
||||
}
|
||||
|
||||
abstract class ConflictingJvmDeclarations : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ConflictingJvmDeclarations::class
|
||||
}
|
||||
|
||||
+8
@@ -2928,6 +2928,14 @@ internal class SuperCallFromPublicInlineImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class CannotAllUnderImportFromSingletonImpl(
|
||||
override val objectName: Name,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.CannotAllUnderImportFromSingleton(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ConflictingJvmDeclarationsImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user