[FIR] Implement CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON diagnostic

This commit is contained in:
Andrey Zinovyev
2021-06-01 16:33:07 +03:00
committed by Space
parent fdd9287836
commit bf153ab0f0
39 changed files with 347 additions and 139 deletions
@@ -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 = {
@@ -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)
}
@@ -100,6 +100,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirKClassWithIncorrectTypeArgumentChecker,
FirTopLevelFunctionsChecker,
FirTopLevelPropertiesChecker,
FirImportsChecker,
)
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
@@ -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)
}
}
}
@@ -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
@@ -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,
@@ -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")
@@ -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 =
@@ -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
)
}
@@ -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}")
}
@@ -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()
@@ -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
@@ -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()
}
@@ -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
@@ -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)
}
@@ -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)
@@ -65,6 +65,10 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
}
impl(errorImport) {
delegateFields(listOf("aliasName", "importedFqName", "isAllUnder", "source"), "delegate")
}
impl(annotationCall) {
default("typeRef") {
value = "annotationTypeRef"
@@ -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
@@ -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
+2 -2
View File
@@ -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
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// import all members from companion object
package c
+2 -2
View File
@@ -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 {
@@ -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<*>,
@@ -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
}
@@ -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,