REDUNDANT_OPEN_FOR_INTERFACE warning: reported for open members without implementation #KT-12452 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-05-24 11:46:47 +03:00
parent e66acd8101
commit 9a69b8b7b5
10 changed files with 58 additions and 13 deletions
@@ -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)
@@ -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))
}
}
@@ -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
View File
@@ -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))