FIR checker: add diagnostic CANNOT_WEAKEN_ACCESS_PRIVILEGE
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
3a07ca4c64
commit
ca314c5bb9
+51
@@ -103,6 +103,31 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
return overriddenSymbols.find { (it.fir as? FirProperty)?.isVar == true }?.fir?.safeAs()
|
return overriddenSymbols.find { (it.fir as? FirProperty)?.isVar == true }?.fir?.safeAs()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirCallableMemberDeclaration<*>.checkVisibility(
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||||
|
) {
|
||||||
|
val visibilities = overriddenSymbols.mapNotNull {
|
||||||
|
if (it.fir !is FirMemberDeclaration) return@mapNotNull null
|
||||||
|
it to (it.fir as FirMemberDeclaration).visibility
|
||||||
|
}.sortedBy { pair ->
|
||||||
|
// Regard `null` compare as Int.MIN so that we can report CANNOT_CHANGE_... first deterministically
|
||||||
|
visibility.compareTo(pair.second) ?: Int.MIN_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((overridden, overriddenVisibility) in visibilities) {
|
||||||
|
val compare = visibility.compareTo(overriddenVisibility)
|
||||||
|
if (compare == null) {
|
||||||
|
// TODO: not ready yet (even after determinism massage), e.g., a Kotlin class that extends a Java class
|
||||||
|
// reporter.reportCannotChangeAccessPrivilege(this, overridden.fir)
|
||||||
|
return
|
||||||
|
} else if (compare < 0) {
|
||||||
|
reporter.reportCannotWeakenAccessPrivilege(this, overridden.fir)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirCallableMemberDeclaration<*>.checkReturnType(
|
private fun FirCallableMemberDeclaration<*>.checkReturnType(
|
||||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||||
typeCheckerContext: AbstractTypeCheckerContext,
|
typeCheckerContext: AbstractTypeCheckerContext,
|
||||||
@@ -152,6 +177,8 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
reporter.reportOverridingFinalMember(function, it)
|
reporter.reportOverridingFinalMember(function, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function.checkVisibility(reporter, overriddenFunctionSymbols)
|
||||||
|
|
||||||
val restriction = function.checkReturnType(
|
val restriction = function.checkReturnType(
|
||||||
overriddenSymbols = overriddenFunctionSymbols,
|
overriddenSymbols = overriddenFunctionSymbols,
|
||||||
typeCheckerContext = typeCheckerContext,
|
typeCheckerContext = typeCheckerContext,
|
||||||
@@ -189,6 +216,8 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
reporter.reportVarOverriddenByVal(property, it)
|
reporter.reportVarOverriddenByVal(property, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property.checkVisibility(reporter, overriddenPropertySymbols)
|
||||||
|
|
||||||
val restriction = property.checkReturnType(
|
val restriction = property.checkReturnType(
|
||||||
overriddenSymbols = overriddenPropertySymbols,
|
overriddenSymbols = overriddenPropertySymbols,
|
||||||
typeCheckerContext = typeCheckerContext,
|
typeCheckerContext = typeCheckerContext,
|
||||||
@@ -227,6 +256,28 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
overriding.source?.let { report(FirErrors.VAR_OVERRIDDEN_BY_VAL.on(it, overriding, overridden)) }
|
overriding.source?.let { report(FirErrors.VAR_OVERRIDDEN_BY_VAL.on(it, overriding, overridden)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun DiagnosticReporter.reportCannotWeakenAccessPrivilege(
|
||||||
|
overriding: FirMemberDeclaration,
|
||||||
|
overridden: FirCallableDeclaration<*>,
|
||||||
|
) {
|
||||||
|
overriding.source?.let { source ->
|
||||||
|
overridden.containingClass()?.let { containingClass ->
|
||||||
|
report(FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(source, overriding.visibility, overridden, containingClass.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun DiagnosticReporter.reportCannotChangeAccessPrivilege(
|
||||||
|
overriding: FirMemberDeclaration,
|
||||||
|
overridden: FirCallableDeclaration<*>,
|
||||||
|
) {
|
||||||
|
overriding.source?.let { source ->
|
||||||
|
overridden.containingClass()?.let { containingClass ->
|
||||||
|
report(FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE.on(source, overriding.visibility, overridden, containingClass.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportReturnTypeMismatchOnFunction(
|
private fun DiagnosticReporter.reportReturnTypeMismatchOnFunction(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirMemberDeclaration
|
overridden: FirMemberDeclaration
|
||||||
|
|||||||
+18
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.REND
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VISIBILITY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_DELEGATED_PROPERTY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_DELEGATED_PROPERTY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_WITH_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_WITH_BODY
|
||||||
@@ -34,6 +35,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OP
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGNED_VALUE_IS_NEVER_READ
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGNED_VALUE_IS_NEVER_READ
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGN_OPERATOR_AMBIGUITY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGN_OPERATOR_AMBIGUITY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_VAL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_VAL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE
|
||||||
@@ -335,6 +338,21 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
map.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", DECLARATION_NAME)
|
map.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", DECLARATION_NAME)
|
||||||
map.put(OVERRIDING_FINAL_MEMBER, "''{0}'' in ''{1}'' is final and cannot be overridden", NAME, TO_STRING)
|
map.put(OVERRIDING_FINAL_MEMBER, "''{0}'' in ''{1}'' is final and cannot be overridden", NAME, TO_STRING)
|
||||||
|
|
||||||
|
map.put(
|
||||||
|
CANNOT_WEAKEN_ACCESS_PRIVILEGE,
|
||||||
|
"Cannot weaken access privilege ''{0}'' for ''{1}'' in ''{2}''",
|
||||||
|
VISIBILITY,
|
||||||
|
NAME,
|
||||||
|
TO_STRING
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
CANNOT_CHANGE_ACCESS_PRIVILEGE,
|
||||||
|
"Cannot change access privilege ''{0}'' for ''{1}'' in ''{2}''",
|
||||||
|
VISIBILITY,
|
||||||
|
NAME,
|
||||||
|
TO_STRING
|
||||||
|
)
|
||||||
|
|
||||||
map.put(
|
map.put(
|
||||||
RETURN_TYPE_MISMATCH_ON_OVERRIDE,
|
RETURN_TYPE_MISMATCH_ON_OVERRIDE,
|
||||||
"Return type of ''{0}'' is not a subtype of the return type of the overridden member ''{1}''",
|
"Return type of ''{0}'' is not a subtype of the return type of the overridden member ''{1}''",
|
||||||
|
|||||||
+5
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirRenderer
|
import org.jetbrains.kotlin.fir.FirRenderer
|
||||||
@@ -55,6 +56,10 @@ object FirDiagnosticRenderers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val VISIBILITY = Renderer { visibility: Visibility ->
|
||||||
|
visibility.externalDisplayName
|
||||||
|
}
|
||||||
|
|
||||||
val DECLARATION_NAME = Renderer { declaration: FirMemberDeclaration ->
|
val DECLARATION_NAME = Renderer { declaration: FirMemberDeclaration ->
|
||||||
val name = when (declaration) {
|
val name = when (declaration) {
|
||||||
is FirProperty -> declaration.name
|
is FirProperty -> declaration.name
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiTypeElement
|
import com.intellij.psi.PsiTypeElement
|
||||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
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.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
@@ -141,6 +142,9 @@ object FirErrors {
|
|||||||
val NOTHING_TO_OVERRIDE by error1<FirSourceElement, KtModifierListOwner, FirMemberDeclaration>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
val NOTHING_TO_OVERRIDE by error1<FirSourceElement, KtModifierListOwner, FirMemberDeclaration>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
||||||
val OVERRIDING_FINAL_MEMBER by error2<FirSourceElement, KtNamedDeclaration, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
val OVERRIDING_FINAL_MEMBER by error2<FirSourceElement, KtNamedDeclaration, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
||||||
|
|
||||||
|
val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3<FirSourceElement, KtModifierListOwner, Visibility, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
|
val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3<FirSourceElement, KtModifierListOwner, Visibility, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
|
|
||||||
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||||
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||||
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||||
|
|||||||
+2
-2
@@ -65,7 +65,7 @@ open class L : T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class M : L() {
|
class M : L() {
|
||||||
internal override fun foo() {}
|
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>internal<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
//---------------
|
//---------------
|
||||||
interface R {
|
interface R {
|
||||||
@@ -81,5 +81,5 @@ interface Q : R {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class S : P, Q {
|
class S : P, Q {
|
||||||
internal override fun foo() {}
|
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>internal<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
//KT-1248 Control visibility of overrides needed
|
|
||||||
package kt1248
|
|
||||||
|
|
||||||
interface ParseResult<out T> {
|
|
||||||
public val success : Boolean
|
|
||||||
public val value : T
|
|
||||||
}
|
|
||||||
|
|
||||||
class Success<T>(internal override val value : T) : ParseResult<T> {
|
|
||||||
internal override val success : Boolean = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
//KT-1248 Control visibility of overrides needed
|
//KT-1248 Control visibility of overrides needed
|
||||||
package kt1248
|
package kt1248
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -28,11 +28,11 @@ class D : C(), T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class E : C(), T {
|
class E : C(), T {
|
||||||
internal override fun foo() {}
|
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>internal<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class F : C(), T {
|
class F : C(), T {
|
||||||
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>override<!> fun foo() {}
|
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE, INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>override<!> fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class G : C(), T {
|
class G : C(), T {
|
||||||
|
|||||||
Reference in New Issue
Block a user