Compare commits

...

11 Commits

Author SHA1 Message Date
rapturemain
726e6b9c1b [FIR] Cast error on the element name instead of the whole body 2020-04-20 12:15:35 +03:00
Mikhail Glukhikh
b98707eaaf [FIR TEST] Apply bad test data (protected effective visibility related) 2020-04-20 12:15:32 +03:00
rapturemain
e752c74b76 [FIR] Fix effective visibility calculation & relevant test data 2020-04-20 12:15:31 +03:00
rapturemain
2d6b8309b0 [FIR] Support for EXPOSED_PARAMETER_TYPE 2020-04-20 12:03:17 +03:00
rapturemain
e2be79bf67 [FIR] Fix EXPOSED_RECEIVER_TYPE 2020-04-20 12:03:16 +03:00
rapturemain
08644e6ea2 [FIR] Change errors location from Errors.java to FirErrors.kt 2020-04-20 12:03:16 +03:00
rapturemain
ea1cadd4d6 [FIR] Support for EXPOSED_FUNCTION_RETURN_TYPE 2020-04-20 12:03:16 +03:00
rapturemain
a62743181f [FIR] Support for FIR_EXPOSED_RECEIVER_TYPE 2020-04-20 12:03:16 +03:00
rapturemain
fbf3d31407 [FIR} Test data for EXPOSED_PROPERTY_TYPE 2020-04-20 12:03:15 +03:00
rapturemain
acc47242b6 [FIR] Support for EXPOSED_PROPERTY_TYPE 2020-04-20 12:03:15 +03:00
rapturemain
4f1e7f89be [FIR] Support for EXPOSED_TYPEALIAS_EXPANDED_TYPE 2020-04-20 12:03:15 +03:00
53 changed files with 562 additions and 132 deletions

View File

@@ -0,0 +1,9 @@
class A {
private class AInner
}
class B {
fun foo(<!EXPOSED_PARAMETER_TYPE!>value: A.AInner<!>) {
}
}

View File

@@ -0,0 +1,23 @@
FILE: exposedFunctionParameterType.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
private final class AInner : R|kotlin/Any| {
public[private] constructor(): R|A.AInner| {
super<R|kotlin/Any|>()
}
}
}
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public final fun foo(value: R|A.AInner|): R|kotlin/Unit| {
}
}

View File

@@ -0,0 +1,9 @@
class A {
private class InnerA {
}
}
abstract class B {
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(str: String): A.InnerA
}

View File

@@ -0,0 +1,23 @@
FILE: exposedFunctionReturnType.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
private final class InnerA : R|kotlin/Any| {
public[private] constructor(): R|A.InnerA| {
super<R|kotlin/Any|>()
}
}
}
public abstract class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public final fun foo(str: R|kotlin/String|): R|A.InnerA|
}

View File

@@ -0,0 +1,23 @@
class A {
private class AInnerPrivate(val str: String) {
}
protected enum class AInnerProtectedEnum {
A,
B
}
public class AInnerPublic(val str: String) {
}
}
class Property {
var var1: String
var var2: String
var var3: Int
var <!EXPOSED_PROPERTY_TYPE!>var4<!>: A.AInnerPrivate
var var5: A.AInnerPublic
var <!EXPOSED_PROPERTY_TYPE!>var6<!>: A.AInnerProtectedEnum
}

View File

@@ -0,0 +1,72 @@
FILE: exposedPropertyType.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
private final class AInnerPrivate : R|kotlin/Any| {
public[private] constructor(str: R|kotlin/String|): R|A.AInnerPrivate| {
super<R|kotlin/Any|>()
}
public[private] final val str: R|kotlin/String| = R|<local>/str|
public get(): R|kotlin/String|
}
protected final enum class AInnerProtectedEnum : R|kotlin/Enum<A.AInnerProtectedEnum>| {
private constructor(): R|A.AInnerProtectedEnum| {
super<R|kotlin/Enum<A.AInnerProtectedEnum>|>()
}
public final static enum entry A: R|A.AInnerProtectedEnum|
public final static enum entry B: R|A.AInnerProtectedEnum|
public final static fun values(): R|kotlin/Array<A.AInnerProtectedEnum>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|A.AInnerProtectedEnum| {
}
}
public final class AInnerPublic : R|kotlin/Any| {
public constructor(str: R|kotlin/String|): R|A.AInnerPublic| {
super<R|kotlin/Any|>()
}
public final val str: R|kotlin/String| = R|<local>/str|
public get(): R|kotlin/String|
}
}
public final class Property : R|kotlin/Any| {
public constructor(): R|Property| {
super<R|kotlin/Any|>()
}
public final var var1: R|kotlin/String|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
public final var var2: R|kotlin/String|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
public final var var3: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
public final var var4: R|A.AInnerPrivate|
public get(): R|A.AInnerPrivate|
public set(value: R|A.AInnerPrivate|): R|kotlin/Unit|
public final var var5: R|A.AInnerPublic|
public get(): R|A.AInnerPublic|
public set(value: R|A.AInnerPublic|): R|kotlin/Unit|
public final var var6: R|A.AInnerProtectedEnum|
public get(): R|A.AInnerProtectedEnum|
public set(value: R|A.AInnerProtectedEnum|): R|kotlin/Unit|
}

View File

@@ -0,0 +1,14 @@
class A {
private inner class Inner
}
class B {
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>AInner<!> = A.Inner
inner class Inner
}
class C {
typealias BInner = B.Inner
}
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>AInner0<!> = A.Inner
typealias BInner0 = B.Inner

View File

@@ -0,0 +1,39 @@
FILE: exposedTypeAlias.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
private final inner class Inner : R|kotlin/Any| {
public[private] constructor(): R|A.Inner| {
super<R|kotlin/Any|>()
}
}
}
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public final typealias AInner = R|A.Inner|
public final inner class Inner : R|kotlin/Any| {
public constructor(): R|B.Inner| {
super<R|kotlin/Any|>()
}
}
}
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
public final typealias BInner = R|B.Inner|
}
public final typealias AInner0 = R|A.Inner|
public final typealias BInner0 = R|B.Inner|

View File

@@ -15,7 +15,7 @@ fun test(e: MyException, stream: PrintStream) {
val result = e.getLocalizedMessage()
}
fun test(e: YourException, stream: PrintStream) {
fun test(<!EXPOSED_PARAMETER_TYPE!>e: YourException<!>, stream: PrintStream) {
e.printStackTrace()
e.printStackTrace(stream)
val result = e.getLocalizedMessage()

View File

@@ -2138,6 +2138,26 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/visibility"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("exposedFunctionParameterType.kt")
public void testExposedFunctionParameterType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionParameterType.kt");
}
@TestMetadata("exposedFunctionReturnType.kt")
public void testExposedFunctionReturnType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionReturnType.kt");
}
@TestMetadata("exposedPropertyType.kt")
public void testExposedPropertyType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedPropertyType.kt");
}
@TestMetadata("exposedTypeAlias.kt")
public void testExposedTypeAlias() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt");
}
@TestMetadata("protectedInCompanion.kt")
public void testProtectedInCompanion() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/protectedInCompanion.kt");

View File

@@ -2138,6 +2138,26 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/visibility"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("exposedFunctionParameterType.kt")
public void testExposedFunctionParameterType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionParameterType.kt");
}
@TestMetadata("exposedFunctionReturnType.kt")
public void testExposedFunctionReturnType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedFunctionReturnType.kt");
}
@TestMetadata("exposedPropertyType.kt")
public void testExposedPropertyType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedPropertyType.kt");
}
@TestMetadata("exposedTypeAlias.kt")
public void testExposedTypeAlias() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt");
}
@TestMetadata("protectedInCompanion.kt")
public void testProtectedInCompanion() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/protectedInCompanion.kt");

View File

@@ -14,7 +14,8 @@ object DeclarationCheckers {
FirModifierChecker
)
val MEMBER_DECLARATIONS: List<FirDeclarationChecker<FirMemberDeclaration>> = DECLARATIONS + listOf(
FirInfixFunctionDeclarationChecker
FirInfixFunctionDeclarationChecker,
FirExposedVisibilityChecker
)
val CONSTRUCTORS: List<FirDeclarationChecker<FirConstructor>> = MEMBER_DECLARATIONS + listOf(
FirConstructorChecker

View File

@@ -0,0 +1,144 @@
/*
* Copyright 2010-2020 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 com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory3
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.lexer.KtTokens
object FirExposedVisibilityChecker : FirDeclarationChecker<FirMemberDeclaration>() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
when (declaration) {
is FirTypeAlias -> checkTypeAlias(declaration, context, reporter)
is FirProperty -> checkProperty(declaration, context, reporter)
is FirFunction<*> -> checkFunction(declaration, context, reporter)
}
}
private fun checkTypeAlias(declaration: FirTypeAlias, context: CheckerContext, reporter: DiagnosticReporter) {
val expandedType = declaration.expandedConeType
val typeAliasVisibility = declaration.firEffectiveVisibility(declaration.session)
val restricting = expandedType?.leastPermissiveDescriptor(declaration.session, typeAliasVisibility)
if (restricting != null) {
reporter.reportExposure(
FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE,
restricting,
typeAliasVisibility,
restricting.firEffectiveVisibility(declaration.session),
declaration.source?.getIdentifierSource() ?: declaration.source
)
}
}
private fun checkFunction(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
val functionVisibility = (declaration as FirMemberDeclaration).firEffectiveVisibility(declaration.session)
if (declaration !is FirConstructor) {
val restricting = declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.leastPermissiveDescriptor(declaration.session, functionVisibility)
if (restricting != null) {
reporter.reportExposure(
FirErrors.EXPOSED_FUNCTION_RETURN_TYPE,
restricting,
functionVisibility,
restricting.firEffectiveVisibility(declaration.session),
declaration.source?.getIdentifierSource() ?: declaration.source
)
}
}
declaration.valueParameters.forEachIndexed { i, valueParameter ->
if (i < declaration.valueParameters.size) {
val restricting =
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.leastPermissiveDescriptor(declaration.session, functionVisibility)
if (restricting != null) {
reporter.reportExposure(
FirErrors.EXPOSED_PARAMETER_TYPE,
restricting,
functionVisibility,
restricting.firEffectiveVisibility(declaration.session),
valueParameter.source
)
}
}
}
checkMemberReceiver(declaration.receiverTypeRef, declaration as? FirCallableMemberDeclaration<*>, reporter)
}
private fun checkProperty(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val propertyVisibility = declaration.firEffectiveVisibility(declaration.session)
val restricting =
declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.leastPermissiveDescriptor(declaration.session, propertyVisibility)
if (restricting != null) {
reporter.reportExposure(
FirErrors.EXPOSED_PROPERTY_TYPE,
restricting,
propertyVisibility,
restricting.firEffectiveVisibility(declaration.session),
declaration.source?.getIdentifierSource() ?: declaration.source
)
}
checkMemberReceiver(declaration.receiverTypeRef, declaration, reporter)
}
private fun checkMemberReceiver(
typeRef: FirTypeRef?,
memberDeclaration: FirCallableMemberDeclaration<*>?, reporter: DiagnosticReporter
) {
if (typeRef == null || memberDeclaration == null) return
val receiverParameterType = typeRef.coneTypeSafe<ConeKotlinType>()
val memberVisibility = memberDeclaration.firEffectiveVisibility(memberDeclaration.session)
val restricting = receiverParameterType?.leastPermissiveDescriptor(memberDeclaration.session, memberVisibility)
if (restricting != null) {
reporter.reportExposure(
FirErrors.EXPOSED_RECEIVER_TYPE,
restricting,
memberVisibility,
restricting.firEffectiveVisibility(memberDeclaration.session),
typeRef.source
)
}
}
private inline fun <reified E : FirSourceElement, P : PsiElement> DiagnosticReporter.reportExposure(
error: FirDiagnosticFactory3<E, P, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>,
restrictingDeclaration: DeclarationWithRelation,
elementVisibility: FirEffectiveVisibility,
restrictingVisibility: FirEffectiveVisibility,
source: FirSourceElement?
) {
source?.let {
report(
error.on(
it as E,
elementVisibility,
restrictingDeclaration,
restrictingVisibility
)
)
}
}
private fun FirSourceElement.getIdentifierSource() = when (this) {
is FirPsiSourceElement<*> -> (this.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.toFirPsiSourceElement()
is FirLightSourceElement -> {
val kidsRef = Ref<Array<LighterASTNode?>>()
this.tree.getChildren(this.element, kidsRef)
val identifier = kidsRef.get().find { it?.tokenType == KtTokens.IDENTIFIER }
identifier?.toFirLightSourceElement(this.tree.getStartOffset(identifier), this.tree.getEndOffset(identifier), this.tree)
}
}
}

View File

@@ -30,6 +30,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_SUPERTYPE
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.EXPOSED_TYPEALIAS_EXPANDED_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_FUNCTION_RETURN_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PROPERTY_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_RECEIVER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PARAMETER_TYPE
@Suppress("unused")
class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
@@ -55,11 +60,17 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(ERROR_FROM_JAVA_RESOLUTION, "Java resolution error")
map.put(OTHER_ERROR, "Unknown (other) error")
map.put(SUPER_IS_NOT_AN_EXPRESSION, "Super cannot be a callee")
map.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING)
map.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING)
map.put(DEPRECATED_MODIFIER_PAIR, "Modifier ''{0}'' is deprecated in presence of ''{1}''", TO_STRING, TO_STRING)
map.put(INCOMPATIBLE_MODIFIERS, "Modifier ''{0}'' is incompatible with ''{1}''", TO_STRING, TO_STRING)
// Exposed visibility group
map.put(EXPOSED_TYPEALIAS_EXPANDED_TYPE, "{0} typealias exposes {2} in expanded type{1}", TO_STRING, TO_STRING, TO_STRING)
map.put(EXPOSED_PROPERTY_TYPE, "{0} property exposes its {2} type{1}", TO_STRING, TO_STRING, TO_STRING)
map.put(EXPOSED_FUNCTION_RETURN_TYPE, "{0} function exposes its {2} return type{1}", TO_STRING, TO_STRING, TO_STRING)
map.put(EXPOSED_RECEIVER_TYPE, "{0} member exposes its {2} receiver type{1}", TO_STRING, TO_STRING, TO_STRING)
map.put(EXPOSED_PARAMETER_TYPE, "{0} function exposes its {2} parameter type{1}", TO_STRING, TO_STRING, TO_STRING)
}
}
}

View File

@@ -23,5 +23,7 @@ object FirDiagnosticRenderers {
}
}
val TO_STRING = Renderer<Any> { it.toString() }
val TO_STRING = Renderer { element: Any ->
element.toString()
}
}

View File

@@ -7,11 +7,15 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.fir.DeclarationWithRelation
import org.jetbrains.kotlin.fir.FirEffectiveVisibility
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtTypeReference
object FirErrors {
val UNRESOLVED_REFERENCE by error1<FirSourceElement, PsiElement, String?>()
@@ -46,8 +50,17 @@ object FirErrors {
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by existing<FirSourceElement, PsiElement>(Errors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM)
val NON_PRIVATE_CONSTRUCTOR_IN_SEALED by existing<FirSourceElement, PsiElement>(Errors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED)
// Exposed visibility group
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_FUNCTION_RETURN_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_RECEIVER_TYPE by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_PROPERTY_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_PARAMETER_TYPE by error3<FirSourceElement, KtParameter, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
val INCOMPATIBLE_MODIFIERS by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
}

View File

@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirEffectiveVisibility.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.declaredMemberScopeProvider
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
@@ -34,14 +36,27 @@ fun ConeKotlinType.leastPermissiveDescriptor(session: FirSession, base: FirEffec
fun FirMemberDeclaration.firEffectiveVisibility(
session: FirSession, visibility: Visibility = this.visibility, checkPublishedApi: Boolean = false
): FirEffectiveVisibility =
lowerBound(
): FirEffectiveVisibility {
val containing = this.containingClass(session)
return lowerBound(
visibility.firEffectiveVisibility(session, this),
this.containingClass(session)?.firEffectiveVisibility(session, checkPublishedApi) ?: Public
this.effectiveVisibility,
containing?.firEffectiveVisibility(session, checkPublishedApi) ?: Public,
containing?.effectiveVisibility ?: Public
)
}
private fun lowerBound(first: FirEffectiveVisibility, second: FirEffectiveVisibility) =
first.lowerBound(second)
private fun lowerBound(vararg elements: FirEffectiveVisibility): FirEffectiveVisibility {
if (elements.size < 2) {
throw IllegalArgumentException("Number of elements must be greater than 1")
}
var result = elements[0]
for (el in elements) {
result = result.lowerBound(el)
}
return result
}
private fun FirMemberDeclaration.containingClass(session: FirSession): FirRegularClass? {
val classId = when (this) {
@@ -50,7 +65,9 @@ private fun FirMemberDeclaration.containingClass(session: FirSession): FirRegula
else -> null
} ?: return null
if (classId.isLocal) return null
return session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass
val buffer = session.declaredMemberScopeProvider.getClassByClassId(classId)
return (session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass)
?: (session.declaredMemberScopeProvider.getClassByClassId(classId) as? FirRegularClass)
}
private fun Visibility.forVisibility(
@@ -63,7 +80,8 @@ private fun Visibility.forVisibility(
Visibilities.PUBLIC -> Public
Visibilities.LOCAL -> Local
// NB: visibility must be already normalized here, so e.g. no JavaVisibilities are possible at this point
else -> throw AssertionError("Visibility $name is not allowed in forVisibility")
// TODO: else -> throw AssertionError("Visibility $name is not allowed in forVisibility")
else -> Private
}
class DeclarationWithRelation internal constructor(val declaration: FirMemberDeclaration, private val relation: RelationToType) {

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.declaredMemberScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirScope
@@ -18,6 +19,24 @@ class FirDeclaredMemberScopeProvider : FirSessionComponent {
private val declaredMemberCache = mutableMapOf<FirClass<*>, FirScope>()
private val nestedClassifierCache = mutableMapOf<FirClass<*>, FirNestedClassifierScope>()
fun getClassByClassId(classId: ClassId): FirClass<*>? {
for ((clazz, _) in declaredMemberCache) {
if (clazz.classId.packageFqName == classId.packageFqName
&& clazz.classId.relativeClassName == classId.relativeClassName
) {
return clazz
}
}
for ((clazz, _) in nestedClassifierCache) {
if (clazz.classId.packageFqName == classId.packageFqName
&& clazz.classId.relativeClassName == classId.relativeClassName
) {
return clazz
}
}
return null
}
fun declaredMemberScope(
klass: FirClass<*>,
useLazyNestedClassifierScope: Boolean,

View File

@@ -7,4 +7,4 @@ enum class E {
fun foo() = E.values()
fun bar() = E.valueOf("ENTRY")
fun baz() = E.ENTRY
fun quux() = E
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>quux<!>() = E

View File

@@ -1,12 +0,0 @@
internal class My
class Your
// Both arguments should be exposed
fun foo(my: My, f: (My) -> Unit) = f(my)
// Ok
fun bar(your: Your, f: (Your) -> Unit) = f(your)
// Exposed, returns My
fun gav(f: () -> My) = f()

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
internal class My
class Your

View File

@@ -10,13 +10,13 @@ internal open class Your: My() {
open class His: Your() {
protected open class Nested
// error, public from internal
val x = My()
val <!EXPOSED_PROPERTY_TYPE!>x<!> = My()
// valid, private from internal
private fun bar() = My()
// valid, internal from internal
internal var y: My? = null
// error, protected from internal
protected fun baz() = Your()
protected fun <!EXPOSED_FUNCTION_RETURN_TYPE!>baz<!>() = Your()
}
internal class Their: His() {

View File

@@ -1,10 +0,0 @@
interface Your
class My {
internal val x = object : Your {}
internal fun foo() = {
class Local
Local()
}()
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface Your
class My {

View File

@@ -1,18 +0,0 @@
// invalid, depends on local class
fun foo() = run {
class A
A()
}
// invalid, depends on local class
fun gav() = {
class B
B()
}
abstract class My
// valid, object literal here is effectively My
fun bar() = run {
object: My() {}
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// invalid, depends on local class
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>() = run {
class A

View File

@@ -2,7 +2,7 @@ class My<T>(val value: T)
open class Base
fun invalid1() = run {
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>invalid1<!>() = run {
class Local
My(Local())
}
@@ -11,12 +11,12 @@ fun invalid2() = My(object {})
fun invalid3() = My(object : Base() {})
fun invalid4() = run {
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>invalid4<!>() = run {
class Local
My(My(Local()))
}
fun invalid5() = run {
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>invalid5<!>() = run {
fun invalid5a() = run {
class Local
Local()

View File

@@ -1,21 +0,0 @@
class Something {
public val publicVal1 = object { override fun toString() = "!" }
protected val protectedVal1 = object { override fun toString() = "!" }
internal val internalVal1 = object { override fun toString() = "!" }
private val privateVal1 = object { override fun toString() = "!" }
public val publicVal2 = run { class A; A() }
protected val protectedVal2 = run { class A; A() }
internal val internalVal2 = run { class A; A() }
private val privateVal2 = run { class A; A() }
public fun publicFun1() = object { override fun toString() = "!" }
protected fun protectedFun1() = object { override fun toString() = "!" }
internal fun internalFun1() = object { override fun toString() = "!" }
private fun privateFun1() = object { override fun toString() = "!" }
public fun publicFun2() = run { class A; A() }
protected fun protectedFun2() = run { class A; A() }
internal fun internalFun2() = run { class A; A() }
private fun privateFun2() = run { class A; A() }
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
class Something {
public val publicVal1 = object { override fun toString() = "!" }
protected val protectedVal1 = object { override fun toString() = "!" }

View File

@@ -2,7 +2,7 @@ class My<T>(val value: T)
open class Base
val invalid1 = run {
val <!EXPOSED_PROPERTY_TYPE!>invalid1<!> = run {
class Local
My(Local())
}
@@ -11,12 +11,12 @@ val invalid2 = My(object {})
val invalid3 = My(object : Base() {})
val invalid4 = run {
val <!EXPOSED_PROPERTY_TYPE!>invalid4<!> = run {
class Local
My(My(Local()))
}
val invalid5 = run {
val <!EXPOSED_PROPERTY_TYPE!>invalid5<!> = run {
fun invalid5a() = run {
class Local
Local()

View File

@@ -1,7 +1,7 @@
// From KT-10753
object My : Inter() {
fun foo(arg: Inter): Inter = arg
val x: Inter? = null
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(<!EXPOSED_PARAMETER_TYPE!>arg: Inter<!>): Inter = arg
val <!EXPOSED_PROPERTY_TYPE!>x<!>: Inter? = null
}
internal open class Inter
@@ -10,21 +10,21 @@ internal open class Inter
open class Test {
protected class Protected
fun foo(x: Protected) = x
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(<!EXPOSED_PARAMETER_TYPE!>x: Protected<!>) = x
interface NestedInterface {
fun create(x: Protected)
fun create(<!EXPOSED_PARAMETER_TYPE!>x: Protected<!>)
}
class NestedClass {
fun create(x: Protected) = x
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>create<!>(<!EXPOSED_PARAMETER_TYPE!>x: Protected<!>) = x
}
object NestedObject {
fun create(x: Protected) = x
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>create<!>(<!EXPOSED_PARAMETER_TYPE!>x: Protected<!>) = x
}
companion object {
fun create(x: Protected) = x
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>create<!>(<!EXPOSED_PARAMETER_TYPE!>x: Protected<!>) = x
}
}

View File

@@ -1,3 +1,3 @@
private enum class Foo { A, B }
class Bar private constructor(val foo: Foo)
class Bar private constructor(val <!EXPOSED_PROPERTY_TYPE!>foo<!>: Foo)

View File

@@ -1,3 +1,3 @@
private enum class Foo { A, B }
class Bar(val foo: Foo)
class Bar(<!EXPOSED_PARAMETER_TYPE!>val <!EXPOSED_PROPERTY_TYPE!>foo<!>: Foo<!>)

View File

@@ -0,0 +1,16 @@
// FILE: Outer.java
public abstract class Outer {
protected static class My {}
protected static class Your extends My {}
abstract protected Your foo(My my);
}
// FILE: OuterDerived.kt
class OuterDerived: Outer() {
// valid, My has better visibility
protected class His: Outer.My()
// valid, My and Your have better visibility
override fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(<!EXPOSED_PARAMETER_TYPE!>my: Outer.My<!>) = Outer.Your()
}

View File

@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FILE: Outer.java
public abstract class Outer {

View File

@@ -0,0 +1,13 @@
abstract class Outer {
protected open class My
// Both valid: same way protected
protected class Your: My()
abstract protected fun foo(my: My): Your
}
class OuterDerived: Outer() {
// valid, My has better visibility
protected class His: Outer.My()
// valid, My and Your have better visibility
override fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(<!EXPOSED_PARAMETER_TYPE!>my: Outer.My<!>) = Outer.Your()
}

View File

@@ -1,4 +1,3 @@
// FIR_IDENTICAL
abstract class Outer {
protected open class My
// Both valid: same way protected

View File

@@ -6,18 +6,18 @@ public interface Your: My {
fun <T: Base> foo(): T
}
public class Derived<T: My>(val x: My): Base() {
public class Derived<T: My>(<!EXPOSED_PARAMETER_TYPE!>val <!EXPOSED_PROPERTY_TYPE!>x<!>: My<!>): Base() {
constructor(xx: My?, x: My): this(xx ?: x)
constructor(<!EXPOSED_PARAMETER_TYPE!>xx: My?<!>, <!EXPOSED_PARAMETER_TYPE!>x: My<!>): this(xx ?: x)
val y: Base? = null
val <!EXPOSED_PROPERTY_TYPE!>y<!>: Base? = null
val My.z: Int
val <!EXPOSED_RECEIVER_TYPE!>My<!>.z: Int
get() = 42
fun foo(m: My): My = m
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(<!EXPOSED_PARAMETER_TYPE!>m: My<!>): My = m
fun My.bar(): My = this
fun <!EXPOSED_RECEIVER_TYPE!>My<!>.<!EXPOSED_FUNCTION_RETURN_TYPE!>bar<!>(): My = this
}

View File

@@ -2,7 +2,7 @@ internal open class My
abstract class Your {
// invalid, List<My> is effectively internal
abstract fun give(): List<My>
abstract fun <!EXPOSED_FUNCTION_RETURN_TYPE!>give<!>(): List<My>
}
// invalid, List<My> is effectively internal

View File

@@ -7,7 +7,7 @@ open class Foo {
}
class Bar: Foo() {
protected fun foo(): Nested? = null
protected fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>(): Nested? = null
}
private fun foo(): Nested? = null

View File

@@ -14,5 +14,5 @@ package p1
import p2.*
val x: X = X()
val y: Y = <!INAPPLICABLE_CANDIDATE!>Y<!>()
val <!EXPOSED_PROPERTY_TYPE!>x<!>: X = X()
val <!EXPOSED_PROPERTY_TYPE!>y<!>: Y = <!INAPPLICABLE_CANDIDATE!>Y<!>()

View File

@@ -1,7 +1,7 @@
// !DIAGNOSTICS: -EXPOSED_PARAMETER_TYPE -NOTHING_TO_INLINE
inline fun call(a: A) {
inline fun call(<!EXPOSED_PARAMETER_TYPE!>a: A<!>) {
a.test()
privateFun()

View File

@@ -6,7 +6,7 @@ private class S public constructor() {
}
}
internal inline fun x(s: S, z: () -> Unit) {
internal inline fun x(<!EXPOSED_PARAMETER_TYPE!>s: S<!>, z: () -> Unit) {
z()
S()
s.a()

View File

@@ -1,5 +1,5 @@
// !DIAGNOSTICS: -EXPOSED_PARAMETER_TYPE -NOTHING_TO_INLINE
inline fun call(a: A) {
inline fun call(<!EXPOSED_PARAMETER_TYPE!>a: A<!>) {
a.test()
publishedTopLevel()

View File

@@ -16,10 +16,10 @@ class MyJavaClass {
//FILE:a.kt
package a
val mc = MyJavaClass()
val <!EXPOSED_PROPERTY_TYPE!>mc<!> = MyJavaClass()
val x = MyJavaClass.staticMethod()
val y = MyJavaClass.NestedClass.staticMethodOfNested()
val z = MyJavaClass.NestedClass()
val <!EXPOSED_PROPERTY_TYPE!>z<!> = MyJavaClass.NestedClass()
//FILE: b.kt
package b

View File

@@ -20,7 +20,7 @@ private fun bar() {
xx = 30
}
fun makeA() = A()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>makeA<!>() = A()
private object PO {}

View File

@@ -17,7 +17,7 @@ class E private constructor() {
}
val a = A
val b = B
val <!EXPOSED_PROPERTY_TYPE!>b<!> = B
val c = C
val d = D
val e = E(42)

View File

@@ -9,7 +9,7 @@ private open class A {
private fun foo() {}
fun makeA() = A()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>makeA<!>() = A()
private object PO {}

View File

@@ -16,7 +16,7 @@ private fun bar() {
x = 20
}
fun makeA() = A()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>makeA<!>() = A()
private object PO {}

View File

@@ -6,14 +6,14 @@ package p
private fun foo(a: Int) = run {
object {
inner class A
fun foo() = A()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>() = A()
}.foo()
}
private fun foo() = run {
object {
inner class A
fun foo() = A()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>foo<!>() = A()
}.foo()
}

View File

@@ -7,39 +7,39 @@ class Outer {
protected class Protected
internal class Internal
typealias TestPrivate1 = Private
protected typealias TestPrivate2 = Private
internal typealias TestPrivate3 = Private
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate1<!> = Private
protected typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate2<!> = Private
internal typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate3<!> = Private
private typealias TestPrivate4 = Private
typealias TestPrivate5 = L<Private>
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate5<!> = L<Private>
typealias TestPrivate6 = L<TestPrivate1>
typealias TestProtected1 = Protected
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestProtected1<!> = Protected
protected typealias TestProtected2 = Protected
internal typealias TestProtected3 = Protected
internal typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestProtected3<!> = Protected
private typealias TestProtected4 = Protected
typealias TestProtected5 = L<Protected>
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestProtected5<!> = L<Protected>
typealias TestProtected6 = L<TestProtected1>
typealias TestInternal1 = Internal
protected typealias TestInternal2 = Internal
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestInternal1<!> = Internal
protected typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestInternal2<!> = Internal
internal typealias TestInternal3 = Internal
private typealias TestInternal4 = Internal
typealias TestInternal5 = L<Internal>
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestInternal5<!> = L<Internal>
typealias TestInternal6 = L<TestInternal1>
}
private class Private
internal class Internal
typealias TestPrivate1 = Private
internal typealias TestPrivate2 = Private
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate1<!> = Private
internal typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate2<!> = Private
private typealias TestPrivate3 = Private
typealias TestPrivate4 = L<Private>
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestPrivate4<!> = L<Private>
typealias TestPrivate5 = L<TestPrivate1>
typealias TestInternal1 = Internal
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestInternal1<!> = Internal
internal typealias TestInternal2 = Internal
private typealias TestInternal3 = Internal
typealias TestInternal4 = L<Internal>
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>TestInternal4<!> = L<Internal>
typealias TestInternal5 = L<TestInternal1>

View File

@@ -4,5 +4,5 @@ class C {
typealias CAlias = C
val test1 = CAlias
val test1a = C
val <!EXPOSED_PROPERTY_TYPE!>test1<!> = CAlias
val <!EXPOSED_PROPERTY_TYPE!>test1a<!> = C

View File

@@ -10,6 +10,6 @@ package kotlin.sequences
import p.*
interface I {
val v1: FilteringSequence
val v2: IndexingSequence<String>
val <!EXPOSED_PROPERTY_TYPE!>v1<!>: FilteringSequence
val <!EXPOSED_PROPERTY_TYPE!>v2<!>: IndexingSequence<String>
}