REDUNDANT_OPEN_FOR_INTERFACE warning: reported for open members without implementation #KT-12452 Fixed
This commit is contained in:
@@ -239,6 +239,8 @@ public interface Errors {
|
||||
|
||||
// Interface-specific
|
||||
|
||||
DiagnosticFactory0<KtModifierListOwner> REDUNDANT_OPEN_IN_INTERFACE = DiagnosticFactory0.create(WARNING, OPEN_MODIFIER);
|
||||
|
||||
DiagnosticFactory0<KtDeclaration> CONSTRUCTOR_IN_INTERFACE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtDeclaration> METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
|
||||
@@ -195,6 +195,8 @@ object PositioningStrategies {
|
||||
|
||||
@JvmField val ABSTRACT_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.ABSTRACT_KEYWORD)
|
||||
|
||||
@JvmField val OPEN_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OPEN_KEYWORD)
|
||||
|
||||
@JvmField val OVERRIDE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OVERRIDE_KEYWORD)
|
||||
|
||||
@JvmField val PRIVATE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.PRIVATE_KEYWORD)
|
||||
|
||||
+1
@@ -158,6 +158,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(REDUNDANT_ANNOTATION_TARGET, "Redundant annotation target ''{0}''", STRING);
|
||||
|
||||
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
||||
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
|
||||
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
||||
MAP.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters");
|
||||
MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM,
|
||||
|
||||
@@ -409,7 +409,7 @@ class DeclarationsChecker(
|
||||
private fun checkProperty(property: KtProperty, propertyDescriptor: PropertyDescriptor) {
|
||||
val containingDeclaration = propertyDescriptor.containingDeclaration
|
||||
if (containingDeclaration is ClassDescriptor) {
|
||||
checkPropertyAbstractness(property, propertyDescriptor, containingDeclaration)
|
||||
checkMemberProperty(property, propertyDescriptor, containingDeclaration)
|
||||
}
|
||||
checkPropertyLateInit(property, propertyDescriptor)
|
||||
checkPropertyInitializer(property, propertyDescriptor)
|
||||
@@ -506,17 +506,24 @@ class DeclarationsChecker(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPropertyAbstractness(
|
||||
private fun checkMemberProperty(
|
||||
property: KtProperty,
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
classDescriptor: ClassDescriptor) {
|
||||
val modifierList = property.modifierList
|
||||
|
||||
if (modifierList != null && modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
|
||||
//has abstract modifier
|
||||
if (!classCanHaveAbstractMembers(classDescriptor)) {
|
||||
trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, property.name ?: "", classDescriptor))
|
||||
return
|
||||
if (modifierList != null) {
|
||||
if (modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
|
||||
//has abstract modifier
|
||||
if (!classCanHaveAbstractMembers(classDescriptor)) {
|
||||
trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, property.name ?: "", classDescriptor))
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (classDescriptor.kind == ClassKind.INTERFACE &&
|
||||
modifierList.hasModifier(KtTokens.OPEN_KEYWORD) &&
|
||||
propertyDescriptor.modality == Modality.ABSTRACT) {
|
||||
trace.report(REDUNDANT_OPEN_IN_INTERFACE.on(property))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,7 +614,7 @@ class DeclarationsChecker(
|
||||
val hasExternalModifier = function.hasModifier(KtTokens.EXTERNAL_KEYWORD)
|
||||
|
||||
if (containingDescriptor is ClassDescriptor) {
|
||||
val inTrait = containingDescriptor.kind == ClassKind.INTERFACE
|
||||
val inInterface = containingDescriptor.kind == ClassKind.INTERFACE
|
||||
if (hasAbstractModifier && !classCanHaveAbstractMembers(containingDescriptor)) {
|
||||
trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.name.asString(), containingDescriptor))
|
||||
}
|
||||
@@ -615,12 +622,15 @@ class DeclarationsChecker(
|
||||
if (hasBody && hasAbstractModifier) {
|
||||
trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor))
|
||||
}
|
||||
if (!hasBody && inTrait) {
|
||||
if (!hasBody && inInterface) {
|
||||
if (function.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
|
||||
trace.report(PRIVATE_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
||||
}
|
||||
if (!hasAbstractModifier && function.hasModifier(KtTokens.OPEN_KEYWORD)) {
|
||||
trace.report(REDUNDANT_OPEN_IN_INTERFACE.on(function))
|
||||
}
|
||||
}
|
||||
if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inTrait) {
|
||||
if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inInterface) {
|
||||
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
// !DIAGNOSTICS: -CONFLICTING_JVM_DECLARATIONS
|
||||
interface One {
|
||||
public open fun foo() : Int
|
||||
public <!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun foo() : Int
|
||||
private fun boo() = 10
|
||||
}
|
||||
interface Two {
|
||||
public open fun foo() : Int
|
||||
public <!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun foo() : Int
|
||||
}
|
||||
|
||||
interface OneImpl : One {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
interface My {
|
||||
<!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun foo()
|
||||
open fun bar() {}
|
||||
<!REDUNDANT_MODIFIER!>open<!> abstract fun baz(): Int
|
||||
|
||||
<!REDUNDANT_OPEN_IN_INTERFACE!>open<!> val x: Int
|
||||
open val y: String
|
||||
get() = ""
|
||||
<!REDUNDANT_MODIFIER!>open<!> abstract val z: Double
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
public interface My {
|
||||
public abstract val x: kotlin.Int
|
||||
public open val y: kotlin.String
|
||||
public abstract val z: kotlin.Double
|
||||
public open fun bar(): kotlin.Unit
|
||||
public abstract fun baz(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// KT-880 Overload resolution ambiguity
|
||||
|
||||
public interface I {
|
||||
open fun test() : Unit
|
||||
<!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun test() : Unit
|
||||
}
|
||||
|
||||
abstract public class A() {
|
||||
|
||||
@@ -10986,6 +10986,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("openInInterface.kt")
|
||||
public void testOpenInInterface() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/openInInterface.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorMissingKeyword.kt")
|
||||
public void testPrimaryConstructorMissingKeyword() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/primaryConstructorMissingKeyword.kt");
|
||||
|
||||
@@ -101,6 +101,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
|
||||
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true)
|
||||
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
|
||||
REDUNDANT_OPEN_IN_INTERFACE.registerFactory(removeRedundantModifierFactory)
|
||||
|
||||
REDUNDANT_PROJECTION.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(true))
|
||||
INCOMPATIBLE_MODIFIERS.registerFactory(RemoveModifierFix.createRemoveModifierFactory(false))
|
||||
|
||||
Reference in New Issue
Block a user