FIR checker: report unresolved reference in imports

Compared to FE1.0, instead of using UNRESOLVED_REFERENCE, a new
UNRESOLVED_IMPORT diagnostic is introduced. This is so that we can use a
different positioning strategy to highlight the last part of the import
if the entire import is passed.

Also, this change fixed some incorrectly rejected imports in FIR. Such
cases are covered the newly added test file staticFunAndPropertyImport.kt
This commit is contained in:
Tianyu Geng
2021-10-25 17:37:38 -07:00
committed by teamcityserver
parent f51b108821
commit 18f7a760bb
33 changed files with 470 additions and 95 deletions
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.api.components.ShortenOption
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.utils.addImportToFile import org.jetbrains.kotlin.analysis.api.fir.utils.addImportToFile
import org.jetbrains.kotlin.analysis.api.fir.utils.computeImportableName import org.jetbrains.kotlin.analysis.api.fir.utils.computeImportableName
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.PackageResolutionResult
import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.getFunctions import org.jetbrains.kotlin.fir.scopes.getFunctions
@@ -49,8 +51,10 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
@@ -229,7 +233,8 @@ private class FirShorteningContext(val firResolveState: FirModuleResolveState) {
} }
private fun createFakeResolvedImport(fqNameToImport: FqName): FirResolvedImport? { private fun createFakeResolvedImport(fqNameToImport: FqName): FirResolvedImport? {
val packageOrClass = resolveToPackageOrClass(firSession.symbolProvider, fqNameToImport) ?: return null val packageOrClass =
(resolveToPackageOrClass(firSession.symbolProvider, fqNameToImport) as? PackageResolutionResult.PackageOrClass) ?: return null
val delegateImport = buildImport { val delegateImport = buildImport {
importedFqName = fqNameToImport importedFqName = fqNameToImport
@@ -326,6 +326,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, token,
) )
} }
add(FirErrors.UNRESOLVED_IMPORT) { firDiagnostic ->
UnresolvedImportImpl(
firDiagnostic.a,
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS) { firDiagnostic -> add(FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS) { firDiagnostic ->
CreatingAnInstanceOfAbstractClassImpl( CreatingAnInstanceOfAbstractClassImpl(
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
@@ -261,6 +261,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val candidates: List<KtSymbol> abstract val candidates: List<KtSymbol>
} }
abstract class UnresolvedImport : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = UnresolvedImport::class
abstract val reference: String
}
abstract class CreatingAnInstanceOfAbstractClass : KtFirDiagnostic<KtExpression>() { abstract class CreatingAnInstanceOfAbstractClass : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = CreatingAnInstanceOfAbstractClass::class override val diagnosticClass get() = CreatingAnInstanceOfAbstractClass::class
} }
@@ -300,6 +300,12 @@ internal class UnresolvedReferenceWrongReceiverImpl(
override val token: ValidityToken, override val token: ValidityToken,
) : KtFirDiagnostic.UnresolvedReferenceWrongReceiver(), KtAbstractFirDiagnostic<PsiElement> ) : KtFirDiagnostic.UnresolvedReferenceWrongReceiver(), KtAbstractFirDiagnostic<PsiElement>
internal class UnresolvedImportImpl(
override val reference: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.UnresolvedImport(), KtAbstractFirDiagnostic<PsiElement>
internal class CreatingAnInstanceOfAbstractClassImpl( internal class CreatingAnInstanceOfAbstractClassImpl(
override val firDiagnostic: KtPsiDiagnostic, override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken, override val token: ValidityToken,
@@ -26011,6 +26011,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt"); runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt");
} }
@Test
@TestMetadata("staticFunAndPropertyImport.kt")
public void testStaticFunAndPropertyImport() throws Exception {
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/staticFunAndPropertyImport.kt");
}
@Test @Test
@TestMetadata("staticFunVsImport.kt") @TestMetadata("staticFunVsImport.kt")
public void testStaticFunVsImport() throws Exception { public void testStaticFunVsImport() throws Exception {
@@ -26011,6 +26011,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt"); runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt");
} }
@Test
@TestMetadata("staticFunAndPropertyImport.kt")
public void testStaticFunAndPropertyImport() throws Exception {
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/staticFunAndPropertyImport.kt");
}
@Test @Test
@TestMetadata("staticFunVsImport.kt") @TestMetadata("staticFunVsImport.kt")
public void testStaticFunVsImport() throws Exception { public void testStaticFunVsImport() throws Exception {
@@ -26011,6 +26011,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt"); runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt");
} }
@Test
@TestMetadata("staticFunAndPropertyImport.kt")
public void testStaticFunAndPropertyImport() throws Exception {
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/staticFunAndPropertyImport.kt");
}
@Test @Test
@TestMetadata("staticFunVsImport.kt") @TestMetadata("staticFunVsImport.kt")
public void testStaticFunVsImport() throws Exception { public void testStaticFunVsImport() throws Exception {
@@ -123,6 +123,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val UNRESOLVED_REFERENCE_WRONG_RECEIVER by error<PsiElement> { val UNRESOLVED_REFERENCE_WRONG_RECEIVER by error<PsiElement> {
parameter<Collection<Symbol>>("candidates") parameter<Collection<Symbol>>("candidates")
} }
val UNRESOLVED_IMPORT by error<PsiElement>(PositioningStrategy.IMPORT_LAST_NAME) {
parameter<String>("reference")
}
} }
val CALL_RESOLUTION by object : DiagnosticGroup("Call resolution") { val CALL_RESOLUTION by object : DiagnosticGroup("Call resolution") {
@@ -149,6 +149,7 @@ object FirErrors {
val DEPRECATION_ERROR by error2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val DEPRECATION_ERROR by error2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val DEPRECATION by warning2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val DEPRECATION by warning2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val UNRESOLVED_REFERENCE_WRONG_RECEIVER by error1<PsiElement, Collection<FirBasedSymbol<*>>>() val UNRESOLVED_REFERENCE_WRONG_RECEIVER by error1<PsiElement, Collection<FirBasedSymbol<*>>>()
val UNRESOLVED_IMPORT by error1<PsiElement, String>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
// Call resolution // Call resolution
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error0<KtExpression>() val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error0<KtExpression>()
@@ -10,33 +10,33 @@ import com.intellij.psi.tree.IElementType
import com.intellij.psi.tree.TokenSet import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.* import org.jetbrains.kotlin.*
fun KtSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1): KtSourceElement? { fun KtSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1, reverse: Boolean = false): KtSourceElement? {
return getChild(setOf(type), index, depth) return getChild(setOf(type), index, depth, reverse)
} }
fun KtSourceElement.getChild(types: TokenSet, index: Int = 0, depth: Int = -1): KtSourceElement? { fun KtSourceElement.getChild(types: TokenSet, index: Int = 0, depth: Int = -1, reverse: Boolean = false): KtSourceElement? {
return getChild(types.types.toSet(), index, depth) return getChild(types.types.toSet(), index, depth, reverse)
} }
fun KtSourceElement.getChild(types: Set<IElementType>, index: Int = 0, depth: Int = -1): KtSourceElement? { fun KtSourceElement.getChild(types: Set<IElementType>, index: Int = 0, depth: Int = -1, reverse: Boolean = false): KtSourceElement? {
return when (this) { return when (this) {
is KtPsiSourceElement -> { is KtPsiSourceElement -> {
getChild(types, index, depth) getChild(types, index, depth, reverse)
} }
is KtLightSourceElement -> { is KtLightSourceElement -> {
getChild(types, index, depth) getChild(types, index, depth, reverse)
} }
else -> null else -> null
} }
} }
private fun KtPsiSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): KtSourceElement? { private fun KtPsiSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int, reverse: Boolean): KtSourceElement? {
val visitor = PsiElementFinderByType(types, index, depth) val visitor = PsiElementFinderByType(types, index, depth, reverse)
return visitor.find(psi)?.toKtPsiSourceElement() return visitor.find(psi)?.toKtPsiSourceElement()
} }
private fun KtLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): KtSourceElement? { private fun KtLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int, reverse: Boolean): KtSourceElement? {
val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth) val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth, reverse)
val childNode = visitor.find(lighterASTNode) ?: return null val childNode = visitor.find(lighterASTNode) ?: return null
return buildChildSourceElement(childNode) return buildChildSourceElement(childNode)
} }
@@ -14,7 +14,8 @@ class LighterTreeElementFinderByType(
private val tree: FlyweightCapableTreeStructure<LighterASTNode>, private val tree: FlyweightCapableTreeStructure<LighterASTNode>,
private var types: Collection<IElementType>, private var types: Collection<IElementType>,
private var index: Int, private var index: Int,
private val depth: Int private val depth: Int,
private val reverse: Boolean,
) { ) {
fun find(node: LighterASTNode?): LighterASTNode? { fun find(node: LighterASTNode?): LighterASTNode? {
if (node == null) return null if (node == null) return null
@@ -33,7 +34,8 @@ class LighterTreeElementFinderByType(
if (currentDepth == depth) return null if (currentDepth == depth) return null
for (child in node.getChildren()) { val children = if (reverse) node.getChildren().asReversed() else node.getChildren()
for (child in children) {
val result = visitNode(child, currentDepth + 1) val result = visitNode(child, currentDepth + 1)
if (result != null) return result if (result != null) return result
} }
@@ -12,7 +12,8 @@ import org.jetbrains.kotlin.psi.psiUtil.allChildren
class PsiElementFinderByType( class PsiElementFinderByType(
private val types: Collection<IElementType>, private val types: Collection<IElementType>,
private var index: Int, private var index: Int,
private val depth: Int private val depth: Int,
private val reverse: Boolean,
) { ) {
fun find(root: PsiElement): PsiElement? { fun find(root: PsiElement): PsiElement? {
return visitElement(root, 0) return visitElement(root, 0)
@@ -30,7 +31,8 @@ class PsiElementFinderByType(
if (currentDepth == depth) return null if (currentDepth == depth) return null
for (child in element.allChildren) { val children = if (reverse) element.allChildren.toList().asReversed().iterator() else element.allChildren.iterator()
for (child in children) {
val result = visitElement(child, currentDepth + 1) val result = visitElement(child, currentDepth + 1)
if (result != null) return result if (result != null) return result
} }
@@ -120,6 +120,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirTopLevelFunctionsChecker, FirTopLevelFunctionsChecker,
FirTopLevelPropertiesChecker, FirTopLevelPropertiesChecker,
FirImportsChecker, FirImportsChecker,
FirUnresolvedInMiddleOfImportChecker,
) )
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
@@ -11,15 +11,14 @@ import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirErrorImport import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
import org.jetbrains.kotlin.fir.declarations.utils.isOperator import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
@@ -63,23 +62,37 @@ object FirImportsChecker : FirFileChecker() {
//empty name come from LT in some erroneous cases //empty name come from LT in some erroneous cases
if (importedName.isSpecial || importedName.identifier.isEmpty()) return if (importedName.isSpecial || importedName.identifier.isEmpty()) return
val classId = (import as? FirResolvedImport)?.resolvedParentClassId val symbolProvider = context.session.symbolProvider
if (classId != null) { val parentClassId = (import as? FirResolvedImport)?.resolvedParentClassId
val classSymbol = classId.resolveToClass(context) ?: return if (parentClassId != null) {
if (classSymbol.classKind.isSingleton) return val parentClassSymbol = parentClassId.resolveToClass(context) ?: return
if (!classSymbol.canBeImported(context, importedName)) { when (val status = parentClassSymbol.getImportStatusOfCallableMembers(context, importedName)) {
reporter.reportOn(import.source, FirErrors.CANNOT_BE_IMPORTED, importedName, context) ImportStatus.OK -> return
else -> {
val classId = parentClassSymbol.classId.createNestedClassId(importedName)
if (symbolProvider.getClassLikeSymbolByClassId(classId) != null) return
if (status == ImportStatus.UNRESOLVED) {
reporter.reportOn(import.source, FirErrors.UNRESOLVED_IMPORT, importedName.asString(), context)
} else {
reporter.reportOn(import.source, FirErrors.CANNOT_BE_IMPORTED, importedName, context)
}
}
} }
} else { } else {
val importedClassId = ClassId.topLevel(importedFqName) val importedClassId = ClassId.topLevel(importedFqName)
if (importedClassId.resolveToClass(context) != null val resolvedToClass = importedClassId.resolveToClass(context) != null
|| context.session.symbolProvider.getTopLevelCallableSymbols(importedFqName.parent(), importedName).isNotEmpty() val resolvedToSymbols = symbolProvider.getTopLevelCallableSymbols(importedFqName.parent(), importedName).isNotEmpty()
) { val resolvedToPackages = symbolProvider.getPackage(importedFqName) != null
return when {
} resolvedToClass || resolvedToSymbols -> return
context.session.symbolProvider.getPackage(importedFqName)?.let { resolvedToPackages -> reporter.reportOn(import.source, FirErrors.PACKAGE_CANNOT_BE_IMPORTED, context)
reporter.reportOn(import.source, FirErrors.PACKAGE_CANNOT_BE_IMPORTED, context) else -> reporter.reportOn(
import.source,
FirErrors.UNRESOLVED_IMPORT,
importedName.asString(),
context,
)
} }
} }
} }
@@ -88,9 +101,9 @@ object FirImportsChecker : FirFileChecker() {
val interestingImports = imports val interestingImports = imports
.filterIsInstance<FirResolvedImport>() .filterIsInstance<FirResolvedImport>()
.filter { import -> .filter { import ->
!import.isAllUnder !import.isAllUnder &&
&& import.importedName?.identifierOrNullIfSpecial?.isNotEmpty() == true import.importedName?.identifierOrNullIfSpecial?.isNotEmpty() == true &&
&& import.resolvesToClass(context) import.resolvesToClass(context)
} }
interestingImports interestingImports
.groupBy { it.aliasName ?: it.importedName!! } .groupBy { it.aliasName ?: it.importedName!! }
@@ -160,26 +173,74 @@ object FirImportsChecker : FirFileChecker() {
return result return result
} }
private fun FirRegularClassSymbol.canBeImported( private enum class ImportStatus {
OK,
CANNOT_BE_IMPORTED,
UNRESOLVED
}
@OptIn(SymbolInternals::class)
private fun FirRegularClassSymbol.getImportStatusOfCallableMembers(context: CheckerContext, name: Name): ImportStatus {
return if (classKind.isSingleton) {
getImportStatusOfCallableMembersFromSingleton(context, name)
} else {
getImportStatusOfCallableMembersFromNonSingleton(context, name)
}
}
private fun FirRegularClassSymbol.getImportStatusOfCallableMembersFromSingleton(
context: CheckerContext, context: CheckerContext,
name: Name name: Name,
): Boolean { ): ImportStatus {
// Use declaredMemberScope first because it's faster and it's relatively rare to import members declared from super types.
for (scope in listOf(context.session.declaredMemberScope(this), unsubstitutedScope(context))) {
var found = false
scope.processFunctionsByName(name) {
found = true
}
if (found) return ImportStatus.OK
scope.processPropertiesByName(name) {
found = true
}
if (found) return ImportStatus.OK
}
return ImportStatus.UNRESOLVED
}
@OptIn(SymbolInternals::class)
private fun FirRegularClassSymbol.getImportStatusOfCallableMembersFromNonSingleton(
context: CheckerContext,
name: Name,
): ImportStatus {
var hasStatic = false var hasStatic = false
var hasIllegal = false var found = false
val scope = context.session.declaredMemberScope(this) for (scope in listOfNotNull(
scope.processFunctionsByName(name) { sym -> // We first try resolution with declaredMemberScope because it's faster and typically imported members are not from
if (sym.isStatic) hasStatic = true // super types.
else hasIllegal = true context.session.declaredMemberScope(this),
}
if (hasStatic) return true
if (hasIllegal) return false
scope.processPropertiesByName(name) { sym -> // Next, we try static scope, which can provide static (Java) members from super classes. Note that it's not available
if (sym.isStatic) hasStatic = true // for pure Kotlin classes.
else hasIllegal = true fir.staticScope(context.sessionHolder),
}
return hasStatic || !hasIllegal // Finally, we fallback to unsubstitutedScope to catch all
unsubstitutedScope(context)
)) {
scope.processFunctionsByName(name) { sym ->
if (sym.isStatic) hasStatic = true
found = true
}
if (hasStatic) return ImportStatus.OK
scope.processPropertiesByName(name) { sym ->
if (sym.isStatic) hasStatic = true
found = true
}
if (hasStatic) return ImportStatus.OK
}
return if (found) ImportStatus.CANNOT_BE_IMPORTED
else ImportStatus.UNRESOLVED
} }
private fun checkDeprecatedImport(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) { private fun checkDeprecatedImport(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -0,0 +1,95 @@
/*
* 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.syntax
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedParentInImport
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtFile
object FirUnresolvedInMiddleOfImportChecker : FirDeclarationSyntaxChecker<FirFile, KtFile>() {
override fun checkPsiOrLightTree(element: FirFile, source: KtSourceElement, context: CheckerContext, reporter: DiagnosticReporter) {
for (import in element.imports) {
if (import is FirErrorImport) processErrorImport(import, context, reporter)
}
}
private fun processErrorImport(import: FirErrorImport, context: CheckerContext, reporter: DiagnosticReporter) {
when (val diagnostic = import.diagnostic) {
is ConeUnresolvedParentInImport -> {
val source = import.source ?: return
var segmentSource: KtSourceElement? = source.dotQualifiedExpression() ?: return
val symbolProvider = context.session.symbolProvider
val parentClassId = diagnostic.parentClassId
if (import.isAllUnder && isClassIdPointingToEnumEntry(parentClassId, symbolProvider)) {
// Enum entries cannot be resolved as class so star import of enum falls in here and we treat it as
// CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON
reporter.reportOn(
source,
FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON,
parentClassId.shortClassName,
context,
)
return
}
// For star import, the PSI structure has one less level of qualified references. Hence we start from 0. Otherwise, we start
// from 1 to skip the last imported name.
var errorSegmentIndexFromLast = if (import.isAllUnder) 0 else 1
var currentClassId = parentClassId.parentClassId
while (currentClassId != null && symbolProvider.getClassLikeSymbolByClassId(currentClassId) == null) {
currentClassId = currentClassId.parentClassId
errorSegmentIndexFromLast++
}
// Finds the right segment from the last that causes resolution to fail. Note that FirImportResolveTransformer always create
// an error import with resolvable package segments. That is, the segment corresponding to the outermost class name is where
// resolution failed.
for (i in 1..errorSegmentIndexFromLast) {
segmentSource = segmentSource?.dotQualifiedExpression()
}
val unresolvedSource = segmentSource?.selectorExpression() ?: return
reporter.reportOn(
unresolvedSource,
FirErrors.UNRESOLVED_IMPORT,
parentClassId.getOutermostClassName(),
context,
)
}
else -> {
}
}
}
/**
* Gets the short outermost class name. For example, `foo.bar.Foo` -> `Foo`. `foo.bar.Outer.Inner.InnerAgain` -> `Outer`.
*/
private fun ClassId.getOutermostClassName() = relativeClassName.pathSegments().first().asString()
private fun isClassIdPointingToEnumEntry(classId: ClassId, symbolProvider: FirSymbolProvider): Boolean {
val enumClassId = classId.parentClassId ?: return false
val enumClass =
(symbolProvider.getClassLikeSymbolByClassId(enumClassId) as? FirRegularClassSymbol)?.takeIf { it.isEnumClass } ?: return false
return enumClass.collectEnumEntries().any { it.callableId.callableName == classId.shortClassName }
}
private fun KtSourceElement.dotQualifiedExpression() = getChild(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, depth = 1)
private fun KtSourceElement.selectorExpression() = getChild(KtNodeTypes.REFERENCE_EXPRESSION, depth = 1, reverse = true)
}
@@ -476,6 +476,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEI
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_SAFE_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_SAFE_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNREACHABLE_CODE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNREACHABLE_CODE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_IMPORT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER
@@ -578,6 +579,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
NAME_OF_CONTAINING_DECLARATION_OR_FILE NAME_OF_CONTAINING_DECLARATION_OR_FILE
) )
map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", NULLABLE_STRING) map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", NULLABLE_STRING)
map.put(UNRESOLVED_IMPORT, "Unresolved reference: {0}", NULLABLE_STRING) // &
map.put(UNRESOLVED_LABEL, "Unresolved label") map.put(UNRESOLVED_LABEL, "Unresolved label")
map.put(DESERIALIZATION_ERROR, "Deserialization error") map.put(DESERIALIZATION_ERROR, "Deserialization error")
map.put(ERROR_FROM_JAVA_RESOLUTION, "Java resolution error") map.put(ERROR_FROM_JAVA_RESOLUTION, "Java resolution error")
@@ -113,6 +113,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source) is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source)
is ConeUnderscoreUsageWithoutBackticks -> FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.createOn(this.source) is ConeUnderscoreUsageWithoutBackticks -> FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.createOn(this.source)
is ConeAmbiguousSuper -> FirErrors.AMBIGUOUS_SUPER.createOn(source, this.candidateTypes) is ConeAmbiguousSuper -> FirErrors.AMBIGUOUS_SUPER.createOn(source, this.candidateTypes)
is ConeUnresolvedParentInImport -> null // reported in FirUnresolvedImportChecker
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}") else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
} }
@@ -194,7 +194,12 @@ class DeclarationsConverter(
var aliasSource: KtSourceElement? = null var aliasSource: KtSourceElement? = null
importDirective.forEachChildren { importDirective.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.asText) REFERENCE_EXPRESSION, DOT_QUALIFIED_EXPRESSION -> {
importedFqName = mutableListOf<String>()
.apply { collectSegments(it) }
.joinToString(".")
.let { FqName(it) }
}
MUL -> isAllUnder = true MUL -> isAllUnder = true
IMPORT_ALIAS -> { IMPORT_ALIAS -> {
val importAlias = convertImportAlias(it) val importAlias = convertImportAlias(it)
@@ -215,6 +220,18 @@ class DeclarationsConverter(
} }
} }
private fun MutableList<String>.collectSegments(expression: LighterASTNode) {
when (expression.tokenType) {
REFERENCE_EXPRESSION -> add(expression.asText)
DOT_QUALIFIED_EXPRESSION -> {
expression.forEachChildren {
collectSegments(it)
}
}
else -> {}
}
}
/** /**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseImportDirectives * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseImportDirectives
*/ */
@@ -13,9 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildErrorImport import org.jetbrains.kotlin.fir.declarations.builder.buildErrorImport
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.lookupTracker import org.jetbrains.kotlin.fir.lookupTracker
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeImportFromSingleton import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeImportFromSingleton
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedParentInImport
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
@@ -73,7 +75,13 @@ open class FirImportResolveTransformer protected constructor(
get() = true get() = true
private fun transformImportForFqName(fqName: FqName, delegate: FirImport): FirImport { private fun transformImportForFqName(fqName: FqName, delegate: FirImport): FirImport {
val (packageFqName, relativeClassFqName, classSymbol) = resolveToPackageOrClass(symbolProvider, fqName) ?: return delegate val (packageFqName, relativeClassFqName, classSymbol) = when (val result = resolveToPackageOrClass(symbolProvider, fqName)) {
is PackageResolutionResult.Error -> return buildErrorImport {
this.delegate = delegate
this.diagnostic = result.diagnostic
}
is PackageResolutionResult.PackageOrClass -> result
}
val firClass = classSymbol?.fir as? FirRegularClass val firClass = classSymbol?.fir as? FirRegularClass
if (delegate.isAllUnder && firClass?.classKind?.isSingleton == true) { if (delegate.isAllUnder && firClass?.classKind?.isSingleton == true) {
return buildErrorImport { return buildErrorImport {
@@ -89,7 +97,7 @@ open class FirImportResolveTransformer protected constructor(
} }
} }
fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): PackageOrClass? { fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): PackageResolutionResult {
var currentPackage = fqName var currentPackage = fqName
val pathSegments = fqName.pathSegments() val pathSegments = fqName.pathSegments()
@@ -102,14 +110,21 @@ fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName):
prefixSize-- prefixSize--
} }
if (currentPackage == fqName) return PackageOrClass(currentPackage, null, null) if (currentPackage == fqName) return PackageResolutionResult.PackageOrClass(currentPackage, null, null)
val relativeClassFqName = val relativeClassFqName = FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() })
FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() })
val classId = ClassId(currentPackage, relativeClassFqName, false) val classId = ClassId(currentPackage, relativeClassFqName, false)
val symbol = symbolProvider.getClassLikeSymbolByClassId(classId) ?: return null val symbol = symbolProvider.getClassLikeSymbolByClassId(classId) ?: return PackageResolutionResult.Error(
ConeUnresolvedParentInImport(classId)
)
return PackageOrClass(currentPackage, relativeClassFqName, symbol) return PackageResolutionResult.PackageOrClass(currentPackage, relativeClassFqName, symbol)
} }
data class PackageOrClass(val packageFqName: FqName, val relativeClassFqName: FqName?, val classSymbol: FirClassLikeSymbol<*>?) sealed class PackageResolutionResult {
data class PackageOrClass(
val packageFqName: FqName, val relativeClassFqName: FqName?, val classSymbol: FirClassLikeSymbol<*>?
) : PackageResolutionResult()
class Error(val diagnostic: ConeDiagnostic) : PackageResolutionResult()
}
@@ -196,6 +196,6 @@ fun ImplicitReceiverValue<*>.asTowerDataElement(): FirTowerDataElement =
fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement = fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement =
FirTowerDataElement(this, implicitReceiver = null, isLocal) FirTowerDataElement(this, implicitReceiver = null, isLocal)
private fun FirClass.staticScope(sessionHolder: SessionHolder) = fun FirClass.staticScope(sessionHolder: SessionHolder) =
scopeProvider.getStaticScope(this, sessionHolder.session, sessionHolder.scopeSession) scopeProvider.getStaticScope(this, sessionHolder.session, sessionHolder.scopeSession)
typealias FirLocalScopes = PersistentList<FirLocalScope> typealias FirLocalScopes = PersistentList<FirLocalScope>
@@ -198,6 +198,11 @@ class ConeImportFromSingleton(val name: Name) : ConeDiagnostic {
open class ConeUnsupported(override val reason: String, val source: KtSourceElement? = null) : ConeDiagnostic open class ConeUnsupported(override val reason: String, val source: KtSourceElement? = null) : ConeDiagnostic
class ConeUnresolvedParentInImport(val parentClassId: ClassId) : ConeDiagnostic {
override val reason: String
get() = "unresolved import"
}
class ConeUnsupportedDynamicType : ConeUnsupported("Dynamic types are not supported in this context") class ConeUnsupportedDynamicType : ConeUnsupported("Dynamic types are not supported in this context")
class ConeDeprecated( class ConeDeprecated(
+6 -6
View File
@@ -7,15 +7,15 @@ import b.ext //extension function
import b.value //property import b.value //property
import b.C.Companion.bar //function from companion object import b.C.Companion.bar //function from companion object
import b.C.Companion.cValue //property from companion object import b.C.Companion.cValue //property from companion object
import b.constant.fff //function from val import b.<!UNRESOLVED_IMPORT!>constant<!>.fff //function from val
import b.constant.dValue //property from val import b.<!UNRESOLVED_IMPORT!>constant<!>.dValue //property from val
import b.constant import b.constant
import b.E.Companion.f //val from companion object import b.E.Companion.f //val from companion object
import smth.illegal import smth.illegal
import b.C.smth.illegal import b.C.<!UNRESOLVED_IMPORT!>smth<!>.illegal
import b.bar.smth import b.<!UNRESOLVED_IMPORT!>bar<!>.smth
import b.bar.* import b.<!UNRESOLVED_IMPORT!>bar<!>.*
import b.unr.unr.unr import b.<!UNRESOLVED_IMPORT!>unr<!>.unr.unr
import unr.unr.unr import unr.unr.unr
fun test(arg: B) { fun test(arg: B) {
@@ -52,27 +52,27 @@ import <!PACKAGE_CANNOT_BE_IMPORTED!>a<!>
import a.<!PACKAGE_CANNOT_BE_IMPORTED!>b<!> import a.<!PACKAGE_CANNOT_BE_IMPORTED!>b<!>
import a.foo import a.foo
import a.foo.bar import a.<!UNRESOLVED_IMPORT!>foo<!>.bar
import a.bar import a.bar
import a.bar.foo import a.<!UNRESOLVED_IMPORT!>bar<!>.foo
import a.B.<!CANNOT_BE_IMPORTED!>foo<!> import a.B.<!CANNOT_BE_IMPORTED!>foo<!>
import a.B.foo.bar import a.B.<!UNRESOLVED_IMPORT!>foo<!>.bar
import a.B.<!CANNOT_BE_IMPORTED!>bar<!> import a.B.<!CANNOT_BE_IMPORTED!>bar<!>
import a.B.bar.foo import a.B.<!UNRESOLVED_IMPORT!>bar<!>.foo
import a.C.foo import a.C.foo
import a.C.foo.bar import a.C.<!UNRESOLVED_IMPORT!>foo<!>.bar
import a.C.bar import a.C.bar
import a.C.bar.foo import a.C.<!UNRESOLVED_IMPORT!>bar<!>.foo
import a.C.Nested import a.C.Nested
import a.D.foo import a.D.<!UNRESOLVED_IMPORT!>foo<!>
import a.D.foo.bar import a.D.<!UNRESOLVED_IMPORT!>foo<!>.bar
import a.D.bar import a.D.<!UNRESOLVED_IMPORT!>bar<!>
import a.D.bar.foo import a.D.<!UNRESOLVED_IMPORT!>bar<!>.foo
import a.D.Companion.foo import a.D.Companion.foo
import a.D.Companion.foo.bar import a.D.Companion.<!UNRESOLVED_IMPORT!>foo<!>.bar
import a.D.Companion.bar import a.D.Companion.bar
import a.D.Companion.bar.foo import a.D.Companion.<!UNRESOLVED_IMPORT!>bar<!>.foo
+2 -2
View File
@@ -18,7 +18,7 @@ interface IInterfaceOutput<out T> {
package mypackage.nestedpackage package mypackage.nestedpackage
import mypackage.nestedpackage.Bar.Baz import mypackage.nestedpackage.Bar.<!UNRESOLVED_IMPORT!>Baz<!>
import anotherpackage.IInterfaceInput import anotherpackage.IInterfaceInput
import anotherpackage.IInterfaceOutput import anotherpackage.IInterfaceOutput
@@ -43,4 +43,4 @@ class Bar() : IInterfaceInput<Baz>, IInterfaceOutput<Baz> {
} }
data class Baz(val myField: Int) data class Baz(val myField: Int)
@@ -8,15 +8,15 @@ import b.ext //extension function
import b.value //property import b.value //property
import b.C.Companion.bar //function from companion object import b.C.Companion.bar //function from companion object
import b.C.Companion.cValue //property from companion object import b.C.Companion.cValue //property from companion object
import b.constant.fff //function from val import b.<!UNRESOLVED_IMPORT!>constant<!>.fff //function from val
import b.constant.dValue //property from val import b.<!UNRESOLVED_IMPORT!>constant<!>.dValue //property from val
import smth.illegal import smth.illegal
import b.C.smth.illegal import b.C.<!UNRESOLVED_IMPORT!>smth<!>.illegal
<!SYNTAX!><<!><!SYNTAX!><<!><!SYNTAX!><<!><!SYNTAX!>HEAD<!><!SYNTAX!><!> <!SYNTAX!><<!><!SYNTAX!><<!><!SYNTAX!><<!><!SYNTAX!>HEAD<!><!SYNTAX!><!>
import b.bar.smth import b.<!UNRESOLVED_IMPORT!>bar<!>.smth
import b.bar.* import b.<!UNRESOLVED_IMPORT!>bar<!>.*
import b.unr.unr.unr import b.<!UNRESOLVED_IMPORT!>unr<!>.unr.unr
import unr.unr.unr import unr.unr.unr
import b.constant import b.constant
import b.E.Companion.f //val from companion object import b.E.Companion.f //val from companion object
@@ -1,4 +1,4 @@
//KT-762 Wrong highlighting in imports (No errors reported on unresolved imports) //KT-762 Wrong highlighting in imports (No errors reported on unresolved imports)
import aaa // must be an error import <!UNRESOLVED_IMPORT!>aaa<!> // must be an error
fun main() {} fun main() {}
@@ -0,0 +1,45 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FILE: A.java
public class A {
static void foo() {}
int foo;
static void foo2() {}
int foo2;
static int bar;
int bar() {return 1;}
static int bar2;
int bar2() {return 1;}
static class quux {}
void quux() {}
int quux;
static class quux2 {}
void quux2() {}
int quux2;
static void baz() {}
}
// FILE: B.java
public class B extends A {
void baz(int i) {}
}
// FILE: 1.kt
// Below should be all good because there is always a static function, property, or class with the requested name.
import A.foo
import A.bar
import A.quux
import B.foo2
import B.bar2
import A.baz
import B.baz
// class cannot be imported by subclass
import B.<!CANNOT_BE_IMPORTED!>quux2<!>
@@ -0,0 +1,61 @@
package
public open class A {
public constructor A()
public/*package*/ final var foo: kotlin.Int
public/*package*/ final var foo2: kotlin.Int
public/*package*/ final var quux: kotlin.Int
public/*package*/ final var quux2: kotlin.Int
public/*package*/ open fun bar(): kotlin.Int
public/*package*/ open fun bar2(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open fun quux(): kotlin.Unit
public/*package*/ open fun quux2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public/*package*/ open class quux {
public/*package*/ constructor quux()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public/*package*/ open class quux2 {
public/*package*/ constructor quux2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
// Static members
public/*package*/ final var bar: kotlin.Int
public/*package*/ final var bar2: kotlin.Int
public/*package*/ open fun baz(): kotlin.Unit
public/*package*/ open fun foo(): kotlin.Unit
public/*package*/ open fun foo2(): kotlin.Unit
}
public open class B : A {
public constructor B()
public/*package*/ final override /*1*/ /*fake_override*/ var foo: kotlin.Int
public/*package*/ final override /*1*/ /*fake_override*/ var foo2: kotlin.Int
public/*package*/ final override /*1*/ /*fake_override*/ var quux: kotlin.Int
public/*package*/ final override /*1*/ /*fake_override*/ var quux2: kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun bar(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun bar2(): kotlin.Int
public/*package*/ open fun baz(/*0*/ i: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun quux(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun quux2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public/*package*/ final override /*1*/ /*fake_override*/ var bar: kotlin.Int
public/*package*/ final override /*1*/ /*fake_override*/ var bar2: kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun baz(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun foo2(): kotlin.Unit
}
@@ -4,6 +4,8 @@
public class A { public class A {
static void foo() {} static void foo() {}
static int bar() {return 1;} static int bar() {return 1;}
void nonStatic1() {}
void nonStatic2() {}
} }
// FILE: B.java // FILE: B.java
@@ -17,6 +19,8 @@ public class C {
// FILE: 1.kt // FILE: 1.kt
import A.foo import A.foo
import B.bar import B.bar
import A.<!CANNOT_BE_IMPORTED!>nonStatic1<!>
import B.<!CANNOT_BE_IMPORTED!>nonStatic2<!>
class E: A() { class E: A() {
init { init {
@@ -4,6 +4,8 @@ public open class A {
public constructor A() public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open fun nonStatic1(): kotlin.Unit
public/*package*/ open fun nonStatic2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members // Static members
@@ -15,6 +17,8 @@ public open class B : A {
public constructor B() public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic1(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members // Static members
@@ -36,6 +40,8 @@ public final class E : A {
public constructor E() public constructor E()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic1(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -43,6 +49,8 @@ public final class F : B {
public constructor F() public constructor F()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic1(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -50,6 +58,8 @@ public final class Q : A {
public constructor Q() public constructor Q()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic1(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -57,5 +67,8 @@ public final class Z : A {
public constructor Z() public constructor Z()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic1(): kotlin.Unit
public/*package*/ open override /*1*/ /*fake_override*/ fun nonStatic2(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
+1 -1
View File
@@ -6,7 +6,7 @@ package kt1080
import reflect.Constructor import reflect.Constructor
import b.* import b.*
import d import <!UNRESOLVED_IMPORT!>d<!>
import d.Test import d.Test
import b.<!PACKAGE_CANNOT_BE_IMPORTED!>d<!> import b.<!PACKAGE_CANNOT_BE_IMPORTED!>d<!>
@@ -28,19 +28,19 @@ import test.ClassAlias
import test.ClassAlias.Nested1 import test.ClassAlias.Nested1
import test.ClassSample.Nested1.* import test.ClassSample.Nested1.*
import test.ClassAlias.Nested1.* import test.ClassAlias.<!UNRESOLVED_IMPORT!>Nested1<!>.*
import test.ObjectAlias import test.ObjectAlias
import test.ObjectAlias.Nested2 import test.ObjectAlias.Nested2
import test.ObjectSample.Nested2.* import test.ObjectSample.Nested2.*
import test.ObjectAlias.Nested2.* import test.ObjectAlias.<!UNRESOLVED_IMPORT!>Nested2<!>.*
import test.EnumAlias import test.EnumAlias
import test.EnumAlias.Nested3 import test.EnumAlias.Nested3
import test.EnumSample.Nested3.* import test.EnumSample.Nested3.*
import test.EnumAlias.Nested3.* import test.EnumAlias.<!UNRESOLVED_IMPORT!>Nested3<!>.*
import test.EnumAlias.Entry import test.EnumAlias.Entry
@@ -26023,6 +26023,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt"); runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/overloadStatic.kt");
} }
@Test
@TestMetadata("staticFunAndPropertyImport.kt")
public void testStaticFunAndPropertyImport() throws Exception {
runTest("compiler/testData/diagnostics/tests/scopes/inheritance/statics/staticFunAndPropertyImport.kt");
}
@Test @Test
@TestMetadata("staticFunVsImport.kt") @TestMetadata("staticFunVsImport.kt")
public void testStaticFunVsImport() throws Exception { public void testStaticFunVsImport() throws Exception {