[FIR] Support for EXPOSED_TYPE_PARAMETER_BOUND

This commit is contained in:
rapturemain
2020-04-30 00:25:22 +03:00
committed by Mikhail Glukhikh
parent bfffcf6b23
commit 02aa11a0a0
8 changed files with 161 additions and 7 deletions
@@ -0,0 +1,35 @@
private open class A
internal open class B
public open class C {
protected open class D
}
public open class E
// invalid, A is private
public class Test1<T: <!EXPOSED_TYPE_PARAMETER_BOUND!>A<!>>
// valid, both type parameters is public
public class Test2<T: C, P: E>
// invalid, D is protected
public class Test3<T: E, P: <!EXPOSED_TYPE_PARAMETER_BOUND!>C.D<!>>
// valid, B is internal
internal class Test4<T: B>
// valid, B is internal
private class Test5<T: B>
public class Container : C {
// valid, D is protected in C
protected class Test6<T: C.D>
// invalid, B is internal
protected class Test7<T: <!EXPOSED_TYPE_PARAMETER_BOUND!>B<!>>
}
// invalid, A is private, B is internal, D is protected
public interface Test8<T: <!EXPOSED_TYPE_PARAMETER_BOUND!>A<!>, P: <!EXPOSED_TYPE_PARAMETER_BOUND!>B<!>, F: C, N: <!EXPOSED_TYPE_PARAMETER_BOUND!>C.D<!>, M: E>
@@ -0,0 +1,84 @@
FILE: exposedTypeParameters.kt
private open class A : R|kotlin/Any| {
public[private] constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
internal open class B : R|kotlin/Any| {
public[internal] constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public open class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
protected open class D : R|kotlin/Any| {
public[protected] constructor(): R|C.D| {
super<R|kotlin/Any|>()
}
}
}
public open class E : R|kotlin/Any| {
public constructor(): R|E| {
super<R|kotlin/Any|>()
}
}
public final class Test1<T : R|A|> : R|kotlin/Any| {
public constructor<T : R|A|>(): R|Test1<T>| {
super<R|kotlin/Any|>()
}
}
public final class Test2<T : R|C|, P : R|E|> : R|kotlin/Any| {
public constructor<T : R|C|, P : R|E|>(): R|Test2<T, P>| {
super<R|kotlin/Any|>()
}
}
public final class Test3<T : R|E|, P : R|C.D|> : R|kotlin/Any| {
public constructor<T : R|E|, P : R|C.D|>(): R|Test3<T, P>| {
super<R|kotlin/Any|>()
}
}
internal final class Test4<T : R|B|> : R|kotlin/Any| {
public[internal] constructor<T : R|B|>(): R|Test4<T>| {
super<R|kotlin/Any|>()
}
}
private final class Test5<T : R|B|> : R|kotlin/Any| {
public[private] constructor<T : R|B|>(): R|Test5<T>| {
super<R|kotlin/Any|>()
}
}
public final class Container : R|C| {
public constructor(): R|Container| {
super<R|C|>()
}
protected final class Test6<T : R|C.D|> : R|kotlin/Any| {
public[protected] constructor<T : R|C.D|>(): R|Container.Test6<T>| {
super<R|kotlin/Any|>()
}
}
protected final class Test7<T : R|B|> : R|kotlin/Any| {
public[protected] constructor<T : R|B|>(): R|Container.Test7<T>| {
super<R|kotlin/Any|>()
}
}
}
public abstract interface Test8<T : R|A|, P : R|B|, F : R|C|, N : R|C.D|, M : R|E|> : R|kotlin/Any| {
}
@@ -2193,6 +2193,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt");
}
@TestMetadata("exposedTypeParameters.kt")
public void testExposedTypeParameters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeParameters.kt");
}
@TestMetadata("protectedInCompanion.kt")
public void testProtectedInCompanion() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/protectedInCompanion.kt");
@@ -2193,6 +2193,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeAlias.kt");
}
@TestMetadata("exposedTypeParameters.kt")
public void testExposedTypeParameters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/exposedTypeParameters.kt");
}
@TestMetadata("protectedInCompanion.kt")
public void testProtectedInCompanion() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/visibility/protectedInCompanion.kt");
@@ -17,6 +17,7 @@ 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.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -29,10 +30,15 @@ object FirExposedVisibilityChecker : FirDeclarationChecker<FirMemberDeclaration>
is FirTypeAlias -> checkTypeAlias(declaration, reporter)
is FirProperty -> checkProperty(declaration, reporter)
is FirFunction<*> -> checkFunction(declaration, reporter)
is FirRegularClass -> checkSupertypes(declaration, reporter)
is FirRegularClass -> checkClass(declaration, reporter)
}
}
private fun checkClass(declaration: FirRegularClass, reporter: DiagnosticReporter) {
checkSupertypes(declaration, reporter)
checkParameterBounds(declaration, reporter)
}
private fun checkSupertypes(declaration: FirRegularClass, reporter: DiagnosticReporter) {
val classVisibility = declaration.firEffectiveVisibility(declaration.session)
val supertypes = declaration.superTypeRefs
@@ -57,6 +63,24 @@ object FirExposedVisibilityChecker : FirDeclarationChecker<FirMemberDeclaration>
}
}
private fun checkParameterBounds(declaration: FirRegularClass, reporter: DiagnosticReporter) {
val classVisibility = declaration.firEffectiveVisibility(declaration.session)
for (parameter in declaration.typeParameters) {
for (bound in parameter.symbol.fir.bounds) {
val restricting = bound.coneTypeSafe<ConeKotlinType>()?.leastPermissiveDescriptor(declaration.session, classVisibility)
if (restricting != null) {
reporter.reportExposure(
FirErrors.EXPOSED_TYPE_PARAMETER_BOUND,
restricting,
classVisibility,
restricting.firEffectiveVisibility(declaration.session),
bound.source
)
}
}
}
}
private fun checkTypeAlias(declaration: FirTypeAlias, reporter: DiagnosticReporter) {
val expandedType = declaration.expandedConeType
val typeAliasVisibility = declaration.firEffectiveVisibility(declaration.session)
@@ -6,17 +6,17 @@
package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DescriptorWithRelation
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3
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.KtSuperTypeListEntry
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.*
object FirErrors {
val UNRESOLVED_REFERENCE by error1<FirSourceElement, PsiElement, String?>()
@@ -61,6 +61,7 @@ object FirErrors {
val EXPOSED_PARAMETER_TYPE by error3<FirSourceElement, KtParameter, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_SUPER_INTERFACE by error3<FirSourceElement, KtSuperTypeListEntry, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_SUPER_CLASS by error3<FirSourceElement, KtSuperTypeListEntry, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeParameter, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>()
val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
+1 -1
View File
@@ -6,7 +6,7 @@ public interface Your: <!EXPOSED_SUPER_INTERFACE!>My<!> {
fun <T: Base> foo(): T
}
public class Derived<T: My>(<!EXPOSED_PARAMETER_TYPE!>val <!EXPOSED_PROPERTY_TYPE!>x<!>: My<!>): <!EXPOSED_SUPER_CLASS!>Base<!>() {
public class Derived<T: <!EXPOSED_TYPE_PARAMETER_BOUND!>My<!>>(<!EXPOSED_PARAMETER_TYPE!>val <!EXPOSED_PROPERTY_TYPE!>x<!>: My<!>): <!EXPOSED_SUPER_CLASS!>Base<!>() {
constructor(<!EXPOSED_PARAMETER_TYPE!>xx: My?<!>, <!EXPOSED_PARAMETER_TYPE!>x: My<!>): this(xx ?: x)
@@ -9,7 +9,7 @@ abstract class Your {
interface His: <!EXPOSED_SUPER_INTERFACE!>List<My><!>
// invalid, My is internal
interface Generic<E: My>
interface Generic<E: <!EXPOSED_TYPE_PARAMETER_BOUND!>My<!>>
interface Our {
// invalid, Generic<My> is effectively internal