[FIR] Fix redundant calls to firEffectiveVisibility()

This commit is contained in:
Nick
2020-07-10 15:19:02 +03:00
parent 5340cf5567
commit 67e58ff152
11 changed files with 73 additions and 55 deletions
@@ -15,7 +15,7 @@ fun test(e: MyException, stream: PrintStream) {
val result = e.getLocalizedMessage() val result = e.getLocalizedMessage()
} }
fun test(<!EXPOSED_PARAMETER_TYPE!>e: YourException<!>, stream: PrintStream) { fun test(e: YourException, stream: PrintStream) {
e.printStackTrace() e.printStackTrace()
e.printStackTrace(stream) e.printStackTrace(stream)
val result = e.getLocalizedMessage() val result = e.getLocalizedMessage()
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.PsiNameIdentifierOwner
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.RelationToType
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
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.toRegularClass import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
@@ -17,8 +18,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory3 import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory3
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
// TODO: check why coneTypeSafe is necessary at some points inside // TODO: check why coneTypeSafe is necessary at some points inside
object FirExposedVisibilityChecker : FirMemberDeclarationChecker() { object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
@@ -37,7 +40,7 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
} }
private fun checkSupertypes(declaration: FirRegularClass, reporter: DiagnosticReporter) { private fun checkSupertypes(declaration: FirRegularClass, reporter: DiagnosticReporter) {
val classVisibility = declaration.firEffectiveVisibility(declaration.session) val classVisibility = declaration.effectiveVisibility
val supertypes = declaration.superTypeRefs val supertypes = declaration.superTypeRefs
val isInterface = declaration.classKind == ClassKind.INTERFACE val isInterface = declaration.classKind == ClassKind.INTERFACE
for (supertypeRef in supertypes) { for (supertypeRef in supertypes) {
@@ -47,13 +50,13 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
if (superIsInterface != isInterface) { if (superIsInterface != isInterface) {
continue continue
} }
val restricting = supertype.leastPermissiveDescriptor(declaration.session, classVisibility) val restricting = supertype.findVisibilityExposure(declaration.session, classVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
if (isInterface) FirErrors.EXPOSED_SUPER_INTERFACE else FirErrors.EXPOSED_SUPER_CLASS, if (isInterface) FirErrors.EXPOSED_SUPER_INTERFACE else FirErrors.EXPOSED_SUPER_CLASS,
restricting, restricting,
classVisibility, classVisibility,
restricting.firEffectiveVisibility(declaration.session), restricting.effectiveVisibility,
supertypeRef.source ?: declaration.source supertypeRef.source ?: declaration.source
) )
} }
@@ -61,16 +64,16 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
} }
private fun checkParameterBounds(declaration: FirRegularClass, reporter: DiagnosticReporter) { private fun checkParameterBounds(declaration: FirRegularClass, reporter: DiagnosticReporter) {
val classVisibility = declaration.firEffectiveVisibility(declaration.session) val classVisibility = declaration.effectiveVisibility
for (parameter in declaration.typeParameters) { for (parameter in declaration.typeParameters) {
for (bound in parameter.symbol.fir.bounds) { for (bound in parameter.symbol.fir.bounds) {
val restricting = bound.coneType.leastPermissiveDescriptor(declaration.session, classVisibility) val restricting = bound.coneType.findVisibilityExposure(declaration.session, classVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
FirErrors.EXPOSED_TYPE_PARAMETER_BOUND, FirErrors.EXPOSED_TYPE_PARAMETER_BOUND,
restricting, restricting,
classVisibility, classVisibility,
restricting.firEffectiveVisibility(declaration.session), restricting.effectiveVisibility,
bound.source bound.source
) )
} }
@@ -81,13 +84,13 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
private fun checkTypeAlias(declaration: FirTypeAlias, reporter: DiagnosticReporter) { private fun checkTypeAlias(declaration: FirTypeAlias, reporter: DiagnosticReporter) {
val expandedType = declaration.expandedConeType val expandedType = declaration.expandedConeType
val typeAliasVisibility = declaration.firEffectiveVisibility(declaration.session) val typeAliasVisibility = declaration.firEffectiveVisibility(declaration.session)
val restricting = expandedType?.leastPermissiveDescriptor(declaration.session, typeAliasVisibility) val restricting = expandedType?.findVisibilityExposure(declaration.session, typeAliasVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE, FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE,
restricting, restricting,
typeAliasVisibility, typeAliasVisibility,
restricting.firEffectiveVisibility(declaration.session), restricting.effectiveVisibility,
declaration.source?.getIdentifierSource() ?: declaration.source declaration.source?.getIdentifierSource() ?: declaration.source
) )
} }
@@ -97,13 +100,13 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
val functionVisibility = (declaration as FirMemberDeclaration).effectiveVisibility val functionVisibility = (declaration as FirMemberDeclaration).effectiveVisibility
if (declaration !is FirConstructor) { if (declaration !is FirConstructor) {
val restricting = declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>() val restricting = declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.leastPermissiveDescriptor(declaration.session, functionVisibility) ?.findVisibilityExposure(declaration.session, functionVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
FirErrors.EXPOSED_FUNCTION_RETURN_TYPE, FirErrors.EXPOSED_FUNCTION_RETURN_TYPE,
restricting, restricting,
functionVisibility, functionVisibility,
restricting.firEffectiveVisibility(declaration.session), restricting.effectiveVisibility,
declaration.source?.getIdentifierSource() ?: declaration.source declaration.source?.getIdentifierSource() ?: declaration.source
) )
} }
@@ -112,13 +115,13 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
if (i < declaration.valueParameters.size) { if (i < declaration.valueParameters.size) {
val restricting = val restricting =
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>() valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.leastPermissiveDescriptor(declaration.session, functionVisibility) ?.findVisibilityExposure(declaration.session, functionVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
FirErrors.EXPOSED_PARAMETER_TYPE, FirErrors.EXPOSED_PARAMETER_TYPE,
restricting, restricting,
functionVisibility, functionVisibility,
restricting.firEffectiveVisibility(declaration.session), restricting.effectiveVisibility,
valueParameter.source valueParameter.source
) )
} }
@@ -128,15 +131,16 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
} }
private fun checkProperty(declaration: FirProperty, reporter: DiagnosticReporter) { private fun checkProperty(declaration: FirProperty, reporter: DiagnosticReporter) {
val propertyVisibility = declaration.firEffectiveVisibility(declaration.session) val propertyVisibility = declaration.effectiveVisibility
val restricting = val restricting =
declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.leastPermissiveDescriptor(declaration.session, propertyVisibility) declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.findVisibilityExposure(declaration.session, propertyVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
FirErrors.EXPOSED_PROPERTY_TYPE, FirErrors.EXPOSED_PROPERTY_TYPE,
restricting, restricting,
propertyVisibility, propertyVisibility,
restricting.firEffectiveVisibility(declaration.session), restricting.effectiveVisibility,
declaration.source?.getIdentifierSource() ?: declaration.source declaration.source?.getIdentifierSource() ?: declaration.source
) )
} }
@@ -149,22 +153,52 @@ object FirExposedVisibilityChecker : FirMemberDeclarationChecker() {
) { ) {
if (typeRef == null || memberDeclaration == null) return if (typeRef == null || memberDeclaration == null) return
val receiverParameterType = typeRef.coneType val receiverParameterType = typeRef.coneType
val memberVisibility = memberDeclaration.firEffectiveVisibility(memberDeclaration.session) val memberVisibility = memberDeclaration.effectiveVisibility
val restricting = receiverParameterType.leastPermissiveDescriptor(memberDeclaration.session, memberVisibility) val restricting = receiverParameterType.findVisibilityExposure(memberDeclaration.session, memberVisibility)
if (restricting != null) { if (restricting != null) {
reporter.reportExposure( reporter.reportExposure(
FirErrors.EXPOSED_RECEIVER_TYPE, FirErrors.EXPOSED_RECEIVER_TYPE,
restricting, restricting,
memberVisibility, memberVisibility,
restricting.firEffectiveVisibility(memberDeclaration.session), restricting.effectiveVisibility,
typeRef.source typeRef.source
) )
} }
} }
private fun ConeKotlinType.findVisibilityExposure(session: FirSession, base: FirEffectiveVisibility): FirMemberDeclaration? {
val type = this as? ConeClassLikeType
?: return null
val fir = type.lookupTag.toSymbol(session)
?.fir
?: return null
if (
fir is FirMemberDeclaration &&
fir.effectiveVisibility != FirEffectiveVisibility.Default // because abstract interface List<out T> returns it here
) {
when (fir.effectiveVisibility.relation(base)) {
FirEffectiveVisibility.Permissiveness.LESS,
FirEffectiveVisibility.Permissiveness.UNKNOWN -> {
return fir
}
else -> {
}
}
}
for (it in type.typeArguments) {
it.safeAs<ConeClassLikeType>()?.findVisibilityExposure(session, base)?.let {
return it
}
}
return null
}
private inline fun <reified E : FirSourceElement, P : PsiElement> DiagnosticReporter.reportExposure( private inline fun <reified E : FirSourceElement, P : PsiElement> DiagnosticReporter.reportExposure(
error: FirDiagnosticFactory3<E, P, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>, error: FirDiagnosticFactory3<E, P, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>,
restrictingDeclaration: DeclarationWithRelation, restrictingDeclaration: FirMemberDeclaration,
elementVisibility: FirEffectiveVisibility, elementVisibility: FirEffectiveVisibility,
restrictingVisibility: FirEffectiveVisibility, restrictingVisibility: FirEffectiveVisibility,
source: FirSourceElement? source: FirSourceElement?
@@ -7,10 +7,9 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.fir.DeclarationWithRelation
import org.jetbrains.kotlin.fir.FirEffectiveVisibility import org.jetbrains.kotlin.fir.FirEffectiveVisibility
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -62,14 +61,14 @@ object FirErrors {
val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER) val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER)
// Exposed visibility group // Exposed visibility group
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_FUNCTION_RETURN_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_FUNCTION_RETURN_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_RECEIVER_TYPE by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_RECEIVER_TYPE by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_PROPERTY_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_PROPERTY_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_PARAMETER_TYPE by error3<FirSourceElement, KtParameter, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_PARAMETER_TYPE by error3<FirSourceElement, KtParameter, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_SUPER_INTERFACE by error3<FirSourceElement, KtSuperTypeListEntry, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_SUPER_INTERFACE by error3<FirSourceElement, KtSuperTypeListEntry, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_SUPER_CLASS by error3<FirSourceElement, KtSuperTypeListEntry, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_SUPER_CLASS by error3<FirSourceElement, KtSuperTypeListEntry, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeParameter, FirEffectiveVisibility, DeclarationWithRelation, FirEffectiveVisibility>() val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeParameter, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>() val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>() val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
@@ -6,7 +6,7 @@ interface A extends C {
// FILE: B.kt // FILE: B.kt
interface B : <!EXPOSED_SUPER_INTERFACE!>A<!> { interface B : A {
fun bar() fun bar()
} }
@@ -6,6 +6,6 @@ class J extends K {
// FILE: K.kt // FILE: K.kt
class K : <!EXPOSED_SUPER_CLASS!>J<!>() { class K : J() {
fun bar() {} fun bar() {}
} }
@@ -12,6 +12,6 @@ class J extends I {
// FILE: K.kt // FILE: K.kt
open class K : <!EXPOSED_SUPER_CLASS!>J<!>() { open class K : J() {
fun baz() {} fun baz() {}
} }
@@ -1,6 +1,6 @@
// FILE: ExceptionTracker.kt // FILE: ExceptionTracker.kt
interface ExceptionTracker : <!EXPOSED_SUPER_INTERFACE!>LockBasedStorageManager.ExceptionHandlingStrategy<!> { interface ExceptionTracker : LockBasedStorageManager.ExceptionHandlingStrategy {
} }
// FILE: StorageManager.kt // FILE: StorageManager.kt
@@ -1,16 +0,0 @@
// 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()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: Outer.java // FILE: Outer.java
public abstract class Outer { public abstract class Outer {
@@ -16,10 +16,10 @@ class MyJavaClass {
//FILE:a.kt //FILE:a.kt
package a package a
val <!EXPOSED_PROPERTY_TYPE!>mc<!> = MyJavaClass() val mc = MyJavaClass()
val x = MyJavaClass.staticMethod() val x = MyJavaClass.staticMethod()
val y = MyJavaClass.NestedClass.staticMethodOfNested() val y = MyJavaClass.NestedClass.staticMethodOfNested()
val <!EXPOSED_PROPERTY_TYPE!>z<!> = MyJavaClass.NestedClass() val z = MyJavaClass.NestedClass()
//FILE: b.kt //FILE: b.kt
package b package b
@@ -10,6 +10,6 @@ package kotlin.sequences
import p.* import p.*
interface I { interface I {
val <!EXPOSED_PROPERTY_TYPE!>v1<!>: FilteringSequence val v1: FilteringSequence
val <!EXPOSED_PROPERTY_TYPE!>v2<!>: IndexingSequence<String> val v2: IndexingSequence<String>
} }