[FIR] Report INVISIBLE_REFERENCE in imports
#KT-55405 Fixed
This commit is contained in:
committed by
Space Team
parent
7dde3603b5
commit
38f0ac332d
@@ -9,6 +9,7 @@ import com.intellij.lang.LighterASTNode
|
|||||||
import com.intellij.psi.tree.IElementType
|
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.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||||
|
|
||||||
fun KtSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1, reverse: Boolean = false): KtSourceElement? {
|
fun KtSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1, reverse: Boolean = false): KtSourceElement? {
|
||||||
return getChild(setOf(type), index, depth, reverse)
|
return getChild(setOf(type), index, depth, reverse)
|
||||||
@@ -53,3 +54,18 @@ internal fun KtLightSourceElement.buildChildSourceElement(childNode: LighterASTN
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val IMPORT_PARENT_TOKEN_TYPES = TokenSet.create(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, KtNodeTypes.REFERENCE_EXPRESSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a source element for the import segment that is [indexFromLast]th from last.
|
||||||
|
*/
|
||||||
|
fun FirImport.getSourceForImportSegment(indexFromLast: Int): KtSourceElement? {
|
||||||
|
var segmentSource: KtSourceElement = source ?: return null
|
||||||
|
|
||||||
|
repeat(indexFromLast + 1) {
|
||||||
|
segmentSource = segmentSource.getChild(IMPORT_PARENT_TOKEN_TYPES, depth = 1) ?: return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return segmentSource.takeIf { it.elementType == KtNodeTypes.REFERENCE_EXPRESSION }
|
||||||
|
?: segmentSource.getChild(KtNodeTypes.REFERENCE_EXPRESSION, depth = 1, reverse = true)
|
||||||
|
}
|
||||||
|
|||||||
+109
-65
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
@@ -12,19 +13,26 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationCheck
|
|||||||
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
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.analysis.getSourceForImportSegment
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
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.declarations.utils.isStatic
|
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
|
||||||
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.SymbolInternals
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.filterIsInstanceWithChecker
|
import org.jetbrains.kotlin.utils.addToStdlib.filterIsInstanceWithChecker
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
object FirImportsChecker : FirFileChecker() {
|
object FirImportsChecker : FirFileChecker() {
|
||||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
declaration.imports.forEach { import ->
|
declaration.imports.forEach { import ->
|
||||||
@@ -65,12 +73,27 @@ object FirImportsChecker : FirFileChecker() {
|
|||||||
if (parentClassId != null) {
|
if (parentClassId != null) {
|
||||||
val parentClassSymbol = parentClassId.resolveToClass(context) ?: return
|
val parentClassSymbol = parentClassId.resolveToClass(context) ?: return
|
||||||
|
|
||||||
|
fun reportInvisibleParentClasses(classSymbol: FirRegularClassSymbol, depth: Int) {
|
||||||
|
if (!classSymbol.fir.isVisible(context)) {
|
||||||
|
val source = import.getSourceForImportSegment(indexFromLast = depth)
|
||||||
|
reporter.reportOn(source, FirErrors.INVISIBLE_REFERENCE, classSymbol, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
classSymbol.classId.outerClassId?.resolveToClass(context)?.let { reportInvisibleParentClasses(it, depth + 1) }
|
||||||
|
}
|
||||||
|
|
||||||
|
reportInvisibleParentClasses(parentClassSymbol, 1)
|
||||||
|
|
||||||
when (val status = parentClassSymbol.getImportStatusOfCallableMembers(context, importedName)) {
|
when (val status = parentClassSymbol.getImportStatusOfCallableMembers(context, importedName)) {
|
||||||
ImportStatus.OK -> return
|
ImportStatus.OK -> return
|
||||||
|
is ImportStatus.Invisible -> {
|
||||||
|
val source = import.getSourceForImportSegment(0)
|
||||||
|
reporter.reportOn(source, FirErrors.INVISIBLE_REFERENCE, status.symbol, context)
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val classId = parentClassSymbol.classId.createNestedClassId(importedName)
|
val classId = parentClassSymbol.classId.createNestedClassId(importedName)
|
||||||
if (symbolProvider.getClassLikeSymbolByClassId(classId) != null) return
|
if (symbolProvider.getClassLikeSymbolByClassId(classId) != null) return
|
||||||
if (status == ImportStatus.UNRESOLVED) {
|
if (status == ImportStatus.Unresolved) {
|
||||||
reporter.reportOn(import.source, FirErrors.UNRESOLVED_IMPORT, importedName.asString(), context)
|
reporter.reportOn(import.source, FirErrors.UNRESOLVED_IMPORT, importedName.asString(), context)
|
||||||
} else {
|
} else {
|
||||||
reporter.reportOn(import.source, FirErrors.CANNOT_BE_IMPORTED, importedName, context)
|
reporter.reportOn(import.source, FirErrors.CANNOT_BE_IMPORTED, importedName, context)
|
||||||
@@ -79,22 +102,54 @@ object FirImportsChecker : FirFileChecker() {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
when {
|
|
||||||
ClassId.topLevel(importedFqName).resolveToClass(context) != null -> return
|
val resolvedClassSymbol = ClassId.topLevel(importedFqName).resolveToClass(context)
|
||||||
// Note: two checks below are both heavyweight, so we should do them lazily!
|
|
||||||
symbolProvider.getTopLevelCallableSymbols(importedFqName.parent(), importedName).isNotEmpty() -> return
|
if (resolvedClassSymbol != null) {
|
||||||
symbolProvider.getPackage(importedFqName) != null -> reporter.reportOn(
|
if (!resolvedClassSymbol.fir.isVisible(context)) {
|
||||||
import.source,
|
reporter.reportOn(import.getSourceForImportSegment(0), FirErrors.INVISIBLE_REFERENCE, resolvedClassSymbol, context)
|
||||||
FirErrors.PACKAGE_CANNOT_BE_IMPORTED,
|
}
|
||||||
context
|
|
||||||
)
|
return
|
||||||
else -> reporter.reportOn(
|
|
||||||
import.source,
|
|
||||||
FirErrors.UNRESOLVED_IMPORT,
|
|
||||||
importedName.asString(),
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: two checks below are both heavyweight, so we should do them lazily!
|
||||||
|
|
||||||
|
val topLevelCallableSymbol = symbolProvider.getTopLevelCallableSymbols(importedFqName.parent(), importedName)
|
||||||
|
if (topLevelCallableSymbol.isNotEmpty()) {
|
||||||
|
if (topLevelCallableSymbol.none { it.fir.isVisible(context) }) {
|
||||||
|
val source = import.getSourceForImportSegment(0)
|
||||||
|
reporter.reportOn(source, FirErrors.INVISIBLE_REFERENCE, topLevelCallableSymbol.first(), context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbolProvider.getPackage(importedFqName) != null) {
|
||||||
|
reporter.reportOn(import.source, FirErrors.PACKAGE_CANNOT_BE_IMPORTED, context)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(import.source, FirErrors.UNRESOLVED_IMPORT, importedName.asString(), context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirMemberDeclaration.isVisible(context: CheckerContext): Boolean {
|
||||||
|
val useSiteFile = context.containingFile ?: return false
|
||||||
|
|
||||||
|
val visibility = visibility
|
||||||
|
|
||||||
|
if (visibility != Visibilities.Unknown && !visibility.mustCheckInImports()) return true
|
||||||
|
if (visibility == Visibilities.Private || visibility == Visibilities.PrivateToThis) {
|
||||||
|
return useSiteFile == context.session.firProvider.getContainingFile(symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.session.visibilityChecker.isVisible(
|
||||||
|
this,
|
||||||
|
context.session,
|
||||||
|
useSiteFile,
|
||||||
|
emptyList(),
|
||||||
|
null,
|
||||||
|
skipCheckForContainingClassVisibility = true,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkConflictingImports(imports: List<FirImport>, context: CheckerContext, reporter: DiagnosticReporter) {
|
private fun checkConflictingImports(imports: List<FirImport>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
@@ -172,74 +227,63 @@ object FirImportsChecker : FirFileChecker() {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class ImportStatus {
|
private sealed class ImportStatus {
|
||||||
OK,
|
data object OK : ImportStatus()
|
||||||
CANNOT_BE_IMPORTED,
|
data class Invisible(val symbol: FirCallableSymbol<*>) : ImportStatus()
|
||||||
UNRESOLVED
|
data object CannotBeImported : ImportStatus()
|
||||||
|
data object Unresolved : ImportStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
|
||||||
private fun FirRegularClassSymbol.getImportStatusOfCallableMembers(context: CheckerContext, name: Name): ImportStatus {
|
private fun FirRegularClassSymbol.getImportStatusOfCallableMembers(context: CheckerContext, name: Name): ImportStatus {
|
||||||
return if (classKind.isSingleton) {
|
return if (classKind.isSingleton) {
|
||||||
getImportStatusOfCallableMembersFromSingleton(context, name)
|
// Use declaredMemberScope first because it's faster, and it's relatively rare to import members declared from super types.
|
||||||
|
val scopes = listOf(context.session.declaredMemberScope(this), unsubstitutedScope(context))
|
||||||
|
getImportStatus(scopes, context, name) { true }
|
||||||
} else {
|
} else {
|
||||||
getImportStatusOfCallableMembersFromNonSingleton(context, name)
|
val scopes = listOfNotNull(
|
||||||
|
// We first try resolution with declaredMemberScope because it's faster and typically imported members are not from
|
||||||
|
// super types.
|
||||||
|
context.session.declaredMemberScope(this),
|
||||||
|
|
||||||
|
// Next, we try static scope, which can provide static (Java) members from super classes. Note that it's not available
|
||||||
|
// for pure Kotlin classes.
|
||||||
|
fir.staticScope(context.sessionHolder),
|
||||||
|
|
||||||
|
// Finally, we fall back to unsubstitutedScope to catch all
|
||||||
|
unsubstitutedScope(context)
|
||||||
|
)
|
||||||
|
getImportStatus(scopes, context, name) { it.isStatic }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirRegularClassSymbol.getImportStatusOfCallableMembersFromSingleton(
|
private inline fun getImportStatus(
|
||||||
|
scopes: List<FirContainingNamesAwareScope>,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
name: Name,
|
name: Name,
|
||||||
|
crossinline isApplicable: (FirCallableSymbol<*>) -> Boolean
|
||||||
): ImportStatus {
|
): 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 found = false
|
var found = false
|
||||||
for (scope in listOfNotNull(
|
var symbol: FirCallableSymbol<*>? = null
|
||||||
// We first try resolution with declaredMemberScope because it's faster and typically imported members are not from
|
|
||||||
// super types.
|
|
||||||
context.session.declaredMemberScope(this),
|
|
||||||
|
|
||||||
// Next, we try static scope, which can provide static (Java) members from super classes. Note that it's not available
|
for (scope in scopes) {
|
||||||
// for pure Kotlin classes.
|
|
||||||
fir.staticScope(context.sessionHolder),
|
|
||||||
|
|
||||||
// Finally, we fallback to unsubstitutedScope to catch all
|
|
||||||
unsubstitutedScope(context)
|
|
||||||
)) {
|
|
||||||
scope.processFunctionsByName(name) { sym ->
|
scope.processFunctionsByName(name) { sym ->
|
||||||
if (sym.isStatic) hasStatic = true
|
if (sym.fir.isVisible(context) && isApplicable(sym)) found = true
|
||||||
found = true
|
symbol = sym
|
||||||
}
|
}
|
||||||
if (hasStatic) return ImportStatus.OK
|
if (found) return ImportStatus.OK
|
||||||
|
|
||||||
scope.processPropertiesByName(name) { sym ->
|
scope.processPropertiesByName(name) { sym ->
|
||||||
if (sym.isStatic) hasStatic = true
|
if (sym.fir.isVisible(context) && isApplicable(sym)) found = true
|
||||||
found = true
|
symbol = sym
|
||||||
}
|
}
|
||||||
if (hasStatic) return ImportStatus.OK
|
if (found) return ImportStatus.OK
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
symbol?.let(isApplicable) == true -> ImportStatus.Invisible(symbol!!)
|
||||||
|
symbol != null -> ImportStatus.CannotBeImported
|
||||||
|
else -> ImportStatus.Unresolved
|
||||||
}
|
}
|
||||||
return if (found) ImportStatus.CANNOT_BE_IMPORTED
|
|
||||||
else ImportStatus.UNRESOLVED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkImportApiStatus(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) {
|
private fun checkImportApiStatus(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
|||||||
+4
-16
@@ -5,14 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.syntax
|
package org.jetbrains.kotlin.fir.analysis.checkers.syntax
|
||||||
|
|
||||||
import com.intellij.psi.tree.TokenSet
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
import org.jetbrains.kotlin.fir.analysis.getSourceForImportSegment
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
import org.jetbrains.kotlin.fir.declarations.FirErrorImport
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
|
import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
|
||||||
@@ -35,7 +33,6 @@ object FirUnresolvedInMiddleOfImportChecker : FirDeclarationSyntaxChecker<FirFil
|
|||||||
when (val diagnostic = import.diagnostic) {
|
when (val diagnostic = import.diagnostic) {
|
||||||
is ConeUnresolvedParentInImport -> {
|
is ConeUnresolvedParentInImport -> {
|
||||||
val source = import.source ?: return
|
val source = import.source ?: return
|
||||||
var segmentSource: KtSourceElement? = source.dotQualifiedExpression() ?: return
|
|
||||||
|
|
||||||
val symbolProvider = context.session.symbolProvider
|
val symbolProvider = context.session.symbolProvider
|
||||||
val parentClassId = diagnostic.parentClassId
|
val parentClassId = diagnostic.parentClassId
|
||||||
@@ -60,13 +57,12 @@ object FirUnresolvedInMiddleOfImportChecker : FirDeclarationSyntaxChecker<FirFil
|
|||||||
currentClassId = currentClassId.parentClassId
|
currentClassId = currentClassId.parentClassId
|
||||||
errorSegmentIndexFromLast++
|
errorSegmentIndexFromLast++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds the right segment from the last that causes resolution to fail. Note that FirImportResolveTransformer always create
|
// 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
|
// an error import with resolvable package segments. That is, the segment corresponding to the outermost class name is where
|
||||||
// resolution failed.
|
// resolution failed.
|
||||||
for (i in 1..errorSegmentIndexFromLast) {
|
val unresolvedSource = import.getSourceForImportSegment(errorSegmentIndexFromLast) ?: return
|
||||||
segmentSource = segmentSource?.dotQualifiedExpression()
|
|
||||||
}
|
|
||||||
val unresolvedSource = segmentSource?.selectorExpression() ?: return
|
|
||||||
reporter.reportOn(
|
reporter.reportOn(
|
||||||
unresolvedSource,
|
unresolvedSource,
|
||||||
FirErrors.UNRESOLVED_IMPORT,
|
FirErrors.UNRESOLVED_IMPORT,
|
||||||
@@ -90,12 +86,4 @@ object FirUnresolvedInMiddleOfImportChecker : FirDeclarationSyntaxChecker<FirFil
|
|||||||
(symbolProvider.getClassLikeSymbolByClassId(enumClassId) as? FirRegularClassSymbol)?.takeIf { it.isEnumClass } ?: return false
|
(symbolProvider.getClassLikeSymbolByClassId(enumClassId) as? FirRegularClassSymbol)?.takeIf { it.isEnumClass } ?: return false
|
||||||
return enumClass.collectEnumEntries().any { it.callableId.callableName == classId.shortClassName }
|
return enumClass.collectEnumEntries().any { it.callableId.callableName == classId.shortClassName }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IMPORT_PARENT_TOKEN_TYPES = TokenSet.create(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, KtNodeTypes.REFERENCE_EXPRESSION)
|
|
||||||
|
|
||||||
private fun KtSourceElement.dotQualifiedExpression(): KtSourceElement? = getChild(IMPORT_PARENT_TOKEN_TYPES, depth = 1)
|
|
||||||
|
|
||||||
private fun KtSourceElement.selectorExpression(): KtSourceElement? =
|
|
||||||
takeIf { it.elementType == KtNodeTypes.REFERENCE_EXPRESSION }
|
|
||||||
?: getChild(KtNodeTypes.REFERENCE_EXPRESSION, depth = 1, reverse = true)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.resolve.isSubclassOf
|
|||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
|
|
||||||
|
|
||||||
@NoMutableState
|
@NoMutableState
|
||||||
object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
object FirJavaVisibilityChecker : FirVisibilityChecker() {
|
||||||
|
|||||||
@@ -17,16 +17,15 @@ import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
|||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
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.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
|
||||||
@@ -237,18 +236,8 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
if (declaration.moduleData == session.moduleData) {
|
if (declaration.moduleData == session.moduleData) {
|
||||||
when {
|
when {
|
||||||
ownerLookupTag == null -> {
|
ownerLookupTag == null -> {
|
||||||
val candidateFile = when (symbol) {
|
|
||||||
is FirSyntheticFunctionSymbol -> {
|
|
||||||
// SAM case
|
|
||||||
val classId = ClassId(symbol.callableId.packageName, symbol.callableId.callableName)
|
|
||||||
provider.getFirClassifierContainerFile(classId)
|
|
||||||
}
|
|
||||||
is FirClassLikeSymbol<*> -> provider.getFirClassifierContainerFileIfAny(symbol)
|
|
||||||
is FirCallableSymbol<*> -> provider.getFirCallableContainerFile(symbol)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
// Top-level: visible in file
|
// Top-level: visible in file
|
||||||
candidateFile == useSiteFile
|
provider.getContainingFile(symbol) == useSiteFile
|
||||||
}
|
}
|
||||||
declaration is FirConstructor && declaration.isFromSealedClass -> {
|
declaration is FirConstructor && declaration.isFromSealedClass -> {
|
||||||
// Sealed class constructor: visible in same package
|
// Sealed class constructor: visible in same package
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.resolve.providers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
|
fun FirProvider.getContainingFile(symbol: FirBasedSymbol<*>): FirFile? = when (symbol) {
|
||||||
|
is FirSyntheticFunctionSymbol -> {
|
||||||
|
// SAM case
|
||||||
|
val classId = ClassId(symbol.callableId.packageName, symbol.callableId.callableName)
|
||||||
|
getFirClassifierContainerFile(classId)
|
||||||
|
}
|
||||||
|
is FirClassLikeSymbol<*> -> getFirClassifierContainerFileIfAny(symbol)
|
||||||
|
is FirCallableSymbol<*> -> getFirCallableContainerFile(symbol)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ private class B
|
|||||||
// FILE: b.kt
|
// FILE: b.kt
|
||||||
package outer.p1
|
package outer.p1
|
||||||
|
|
||||||
import outer.a
|
import outer.<!INVISIBLE_REFERENCE!>a<!>
|
||||||
|
|
||||||
fun use() {
|
fun use() {
|
||||||
<!INVISIBLE_REFERENCE!>a<!>()
|
<!INVISIBLE_REFERENCE!>a<!>()
|
||||||
@@ -17,7 +17,7 @@ fun use() {
|
|||||||
// FILE: c.kt
|
// FILE: c.kt
|
||||||
package outer.p1.p2
|
package outer.p1.p2
|
||||||
|
|
||||||
import outer.a
|
import outer.<!INVISIBLE_REFERENCE!>a<!>
|
||||||
|
|
||||||
fun use() {
|
fun use() {
|
||||||
<!INVISIBLE_REFERENCE!>a<!>()
|
<!INVISIBLE_REFERENCE!>a<!>()
|
||||||
|
|||||||
+2
-2
@@ -29,9 +29,9 @@ private class D {
|
|||||||
package b
|
package b
|
||||||
|
|
||||||
import a.A
|
import a.A
|
||||||
import a.B
|
import a.<!INVISIBLE_REFERENCE!>B<!>
|
||||||
import a.C
|
import a.C
|
||||||
import a.D
|
import a.<!INVISIBLE_REFERENCE!>D<!>
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
f(A)
|
f(A)
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
// FILE: j/JavaPublic.java
|
|
||||||
package j;
|
|
||||||
|
|
||||||
public class JavaPublic {
|
|
||||||
public static void javaM() {}
|
|
||||||
public static int javaP = 4;
|
|
||||||
static int javaPackageLocal = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: j/JavaPackageLocal.java
|
|
||||||
package j;
|
|
||||||
|
|
||||||
class JavaPackageLocal {
|
|
||||||
static void javaMPackage() {}
|
|
||||||
static int javaPPackage = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: j/JavaProtected.java
|
|
||||||
package j;
|
|
||||||
|
|
||||||
public class JavaProtected {
|
|
||||||
protected static void javaMProtected() {}
|
|
||||||
protected static int javaPProtected = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: j/JavaPrivate.java
|
|
||||||
package j;
|
|
||||||
|
|
||||||
public class JavaPrivate {
|
|
||||||
private static void javaMPrivate() {}
|
|
||||||
private static int javaPPrivate = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FILE: k1.kt
|
|
||||||
package k
|
|
||||||
|
|
||||||
import j.JavaPublic
|
|
||||||
import j.JavaPublic.javaM
|
|
||||||
import j.JavaPublic.javaP
|
|
||||||
import j.JavaPublic.javaPackageLocal
|
|
||||||
|
|
||||||
import j.JavaPackageLocal
|
|
||||||
import j.JavaPackageLocal.javaMPackage
|
|
||||||
import j.JavaPackageLocal.javaPPackage
|
|
||||||
|
|
||||||
import j.JavaProtected
|
|
||||||
import j.JavaProtected.javaMProtected
|
|
||||||
import j.JavaProtected.javaPProtected
|
|
||||||
|
|
||||||
import j.JavaPrivate
|
|
||||||
import j.JavaPrivate.javaMPrivate
|
|
||||||
import j.JavaPrivate.javaPPrivate
|
|
||||||
|
|
||||||
// FILE: k2.kt
|
|
||||||
package j
|
|
||||||
|
|
||||||
import j.JavaPublic
|
|
||||||
import j.JavaPublic.javaM
|
|
||||||
import j.JavaPublic.javaP
|
|
||||||
import j.JavaPublic.javaPackageLocal
|
|
||||||
|
|
||||||
import j.JavaPackageLocal
|
|
||||||
import j.JavaPackageLocal.javaMPackage
|
|
||||||
import j.JavaPackageLocal.javaPPackage
|
|
||||||
|
|
||||||
import j.JavaProtected
|
|
||||||
import j.JavaProtected.javaMProtected
|
|
||||||
import j.JavaProtected.javaPProtected
|
|
||||||
|
|
||||||
import j.JavaPrivate
|
|
||||||
import j.JavaPrivate.javaMPrivate
|
|
||||||
import j.JavaPrivate.javaPPrivate
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
|
||||||
// FILE: j/JavaPublic.java
|
// FILE: j/JavaPublic.java
|
||||||
package j;
|
package j;
|
||||||
|
|
||||||
@@ -5,6 +7,7 @@ public class JavaPublic {
|
|||||||
public static void javaM() {}
|
public static void javaM() {}
|
||||||
public static int javaP = 4;
|
public static int javaP = 4;
|
||||||
static int javaPackageLocal = 5;
|
static int javaPackageLocal = 5;
|
||||||
|
protected static int javaProtected = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: j/JavaPackageLocal.java
|
// FILE: j/JavaPackageLocal.java
|
||||||
@@ -39,6 +42,7 @@ import j.JavaPublic
|
|||||||
import j.JavaPublic.javaM
|
import j.JavaPublic.javaM
|
||||||
import j.JavaPublic.javaP
|
import j.JavaPublic.javaP
|
||||||
import j.JavaPublic.<!INVISIBLE_REFERENCE!>javaPackageLocal<!>
|
import j.JavaPublic.<!INVISIBLE_REFERENCE!>javaPackageLocal<!>
|
||||||
|
import j.JavaPublic.javaProtected
|
||||||
|
|
||||||
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>
|
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>
|
||||||
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>.<!INVISIBLE_REFERENCE!>javaMPackage<!>
|
import j.<!INVISIBLE_REFERENCE!>JavaPackageLocal<!>.<!INVISIBLE_REFERENCE!>javaMPackage<!>
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ package j {
|
|||||||
// Static members
|
// Static members
|
||||||
public final var javaP: kotlin.Int
|
public final var javaP: kotlin.Int
|
||||||
public/*package*/ final var javaPackageLocal: kotlin.Int
|
public/*package*/ final var javaPackageLocal: kotlin.Int
|
||||||
|
protected/*protected static*/ final var javaProtected: kotlin.Int
|
||||||
public open fun javaM(): kotlin.Unit
|
public open fun javaM(): kotlin.Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
// MODULE: m1
|
|
||||||
// FILE: k1.kt
|
|
||||||
package k
|
|
||||||
|
|
||||||
private class KPrivate
|
|
||||||
internal class KInternal
|
|
||||||
public class KPublic
|
|
||||||
|
|
||||||
class A {
|
|
||||||
protected class KProtected
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: k2.kt
|
|
||||||
package k2
|
|
||||||
|
|
||||||
import k.KPrivate
|
|
||||||
import k.KInternal
|
|
||||||
import k.KPublic
|
|
||||||
import k.A.KProtected
|
|
||||||
|
|
||||||
// MODULE: m2(m1)
|
|
||||||
// FILE: k3.kt
|
|
||||||
package k3
|
|
||||||
|
|
||||||
import k.KPrivate
|
|
||||||
import k.KInternal
|
|
||||||
import k.KPublic
|
|
||||||
import k.A.KProtected
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// MODULE: m1
|
// MODULE: m1
|
||||||
// FILE: k1.kt
|
// FILE: k1.kt
|
||||||
package k
|
package k
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ fun all(a: String) {}
|
|||||||
|
|
||||||
// FILE: 2.kt
|
// FILE: 2.kt
|
||||||
|
|
||||||
import k.zero
|
import k.<!INVISIBLE_REFERENCE!>zero<!>
|
||||||
import k.one
|
import k.one
|
||||||
import k.two
|
import k.two
|
||||||
import k.all
|
import k.all
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ public class B {
|
|||||||
// FILE: C.kt
|
// FILE: C.kt
|
||||||
|
|
||||||
import A.Nested.*
|
import A.Nested.*
|
||||||
import B.JC.JC1
|
import B.<!INVISIBLE_REFERENCE!>JC<!>.JC1
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
<!INVISIBLE_REFERENCE!>O1<!>
|
<!INVISIBLE_REFERENCE!>O1<!>
|
||||||
|
|||||||
@@ -3,12 +3,33 @@ package pkg
|
|||||||
|
|
||||||
private class Klass
|
private class Klass
|
||||||
|
|
||||||
|
private class Foo {
|
||||||
|
object Bar {
|
||||||
|
fun baz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo2 {
|
||||||
|
private object Bar {
|
||||||
|
fun baz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Foo3 {
|
||||||
|
private object Bar {
|
||||||
|
private fun baz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
package pack
|
package pack
|
||||||
|
|
||||||
import <!UNRESOLVED_IMPORT!>foo<!>.bar.baz
|
import <!UNRESOLVED_IMPORT!>foo<!>.bar.baz
|
||||||
import <!UNRESOLVED_IMPORT!>Outer<!>.`<no name provided>`.getInner
|
import <!UNRESOLVED_IMPORT!>Outer<!>.`<no name provided>`.getInner
|
||||||
import pack.<!UNRESOLVED_IMPORT!>UnresolvedName<!>
|
import pack.<!UNRESOLVED_IMPORT!>UnresolvedName<!>
|
||||||
import pkg.Klass
|
import pkg.<!INVISIBLE_REFERENCE!>Klass<!>
|
||||||
|
import pkg.<!INVISIBLE_REFERENCE!>Foo<!>.Bar.baz
|
||||||
|
import pkg.Foo2.<!INVISIBLE_REFERENCE!>Bar<!>.baz
|
||||||
|
import pkg.<!INVISIBLE_REFERENCE!>Foo3<!>.<!INVISIBLE_REFERENCE!>Bar<!>.<!INVISIBLE_REFERENCE!>baz<!>
|
||||||
|
|
||||||
class MainSource
|
class MainSource
|
||||||
|
|||||||
@@ -3,6 +3,24 @@ package pkg
|
|||||||
|
|
||||||
private class Klass
|
private class Klass
|
||||||
|
|
||||||
|
private class Foo {
|
||||||
|
object Bar {
|
||||||
|
fun baz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo2 {
|
||||||
|
private object Bar {
|
||||||
|
fun baz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Foo3 {
|
||||||
|
private object Bar {
|
||||||
|
private fun baz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
package pack
|
package pack
|
||||||
|
|
||||||
@@ -10,5 +28,8 @@ import <!UNRESOLVED_REFERENCE!>foo<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>bar<!>.<!
|
|||||||
import <!UNRESOLVED_REFERENCE!>Outer<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>`<no name provided>`<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>getInner<!>
|
import <!UNRESOLVED_REFERENCE!>Outer<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>`<no name provided>`<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>getInner<!>
|
||||||
import pack.<!UNRESOLVED_REFERENCE!>UnresolvedName<!>
|
import pack.<!UNRESOLVED_REFERENCE!>UnresolvedName<!>
|
||||||
import pkg.<!INVISIBLE_REFERENCE!>Klass<!>
|
import pkg.<!INVISIBLE_REFERENCE!>Klass<!>
|
||||||
|
import pkg.<!INVISIBLE_REFERENCE!>Foo<!>.Bar.baz
|
||||||
|
import pkg.Foo2.<!INVISIBLE_REFERENCE!>Bar<!>.baz
|
||||||
|
import pkg.<!INVISIBLE_REFERENCE!>Foo3<!>.<!INVISIBLE_REFERENCE!>Bar<!>.<!INVISIBLE_REFERENCE!>baz<!>
|
||||||
|
|
||||||
class MainSource
|
class MainSource
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// FILE: A.kt
|
// FILE: A.kt
|
||||||
|
|
||||||
import B.foo
|
import B.<!INVISIBLE_REFERENCE!>foo<!>
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
<!INVISIBLE_REFERENCE!>foo<!>
|
<!INVISIBLE_REFERENCE!>foo<!>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ val <!EXPOSED_PROPERTY_TYPE!>z<!> = MyJavaClass.NestedClass()
|
|||||||
//FILE: b.kt
|
//FILE: b.kt
|
||||||
package b
|
package b
|
||||||
|
|
||||||
import a.MyJavaClass
|
import a.<!INVISIBLE_REFERENCE!>MyJavaClass<!>
|
||||||
|
|
||||||
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INVISIBLE_REFERENCE!>MyJavaClass<!>()
|
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INVISIBLE_REFERENCE!>MyJavaClass<!>()
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ val <!EXPOSED_PROPERTY_TYPE!>z<!> = <!INVISIBLE_REFERENCE, NO_COMPANION_OBJECT!>
|
|||||||
//FILE: c.kt
|
//FILE: c.kt
|
||||||
package a.c
|
package a.c
|
||||||
|
|
||||||
import a.MyJavaClass
|
import a.<!INVISIBLE_REFERENCE!>MyJavaClass<!>
|
||||||
|
|
||||||
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INVISIBLE_REFERENCE!>MyJavaClass<!>()
|
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INVISIBLE_REFERENCE!>MyJavaClass<!>()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ class Foo {
|
|||||||
// FILE: foo.kt
|
// FILE: foo.kt
|
||||||
package a
|
package a
|
||||||
|
|
||||||
import p.Foo
|
import p.<!INVISIBLE_REFERENCE!>Foo<!>
|
||||||
import p.Foo.Nested
|
import p.<!INVISIBLE_REFERENCE!>Foo<!>.Nested
|
||||||
|
|
||||||
class Bar : <!EXPOSED_SUPER_CLASS, INVISIBLE_REFERENCE, INVISIBLE_REFERENCE!>Foo<!>() {
|
class Bar : <!EXPOSED_SUPER_CLASS, INVISIBLE_REFERENCE, INVISIBLE_REFERENCE!>Foo<!>() {
|
||||||
protected fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(): <!INVISIBLE_REFERENCE!>Nested<!>? = null
|
protected fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(): <!INVISIBLE_REFERENCE!>Nested<!>? = null
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ private object PO {}
|
|||||||
//+JDK
|
//+JDK
|
||||||
package b
|
package b
|
||||||
|
|
||||||
import a.A
|
import a.<!INVISIBLE_REFERENCE!>A<!>
|
||||||
import a.foo
|
import a.<!INVISIBLE_REFERENCE!>foo<!>
|
||||||
import a.makeA
|
import a.makeA
|
||||||
import a.PO
|
import a.<!INVISIBLE_REFERENCE!>PO<!>
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val y = makeA()
|
val y = makeA()
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ private class Private {
|
|||||||
|
|
||||||
// FILE: 2.kt
|
// FILE: 2.kt
|
||||||
|
|
||||||
import Private.Public
|
import <!INVISIBLE_REFERENCE!>Private<!>.Public
|
||||||
|
|
||||||
private fun test_1(x: <!INVISIBLE_REFERENCE!>Private.Public<!>, y: <!INVISIBLE_REFERENCE!>Public<!>) {
|
private fun test_1(x: <!INVISIBLE_REFERENCE!>Private.Public<!>, y: <!INVISIBLE_REFERENCE!>Public<!>) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user