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
|
// 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> CONSTRUCTOR_IN_INTERFACE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||||
DiagnosticFactory0<KtDeclaration> METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
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 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 OVERRIDE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OVERRIDE_KEYWORD)
|
||||||
|
|
||||||
@JvmField val PRIVATE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.PRIVATE_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_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_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(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
||||||
MAP.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters");
|
MAP.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters");
|
||||||
MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM,
|
MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM,
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ class DeclarationsChecker(
|
|||||||
private fun checkProperty(property: KtProperty, propertyDescriptor: PropertyDescriptor) {
|
private fun checkProperty(property: KtProperty, propertyDescriptor: PropertyDescriptor) {
|
||||||
val containingDeclaration = propertyDescriptor.containingDeclaration
|
val containingDeclaration = propertyDescriptor.containingDeclaration
|
||||||
if (containingDeclaration is ClassDescriptor) {
|
if (containingDeclaration is ClassDescriptor) {
|
||||||
checkPropertyAbstractness(property, propertyDescriptor, containingDeclaration)
|
checkMemberProperty(property, propertyDescriptor, containingDeclaration)
|
||||||
}
|
}
|
||||||
checkPropertyLateInit(property, propertyDescriptor)
|
checkPropertyLateInit(property, propertyDescriptor)
|
||||||
checkPropertyInitializer(property, propertyDescriptor)
|
checkPropertyInitializer(property, propertyDescriptor)
|
||||||
@@ -506,17 +506,24 @@ class DeclarationsChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyAbstractness(
|
private fun checkMemberProperty(
|
||||||
property: KtProperty,
|
property: KtProperty,
|
||||||
propertyDescriptor: PropertyDescriptor,
|
propertyDescriptor: PropertyDescriptor,
|
||||||
classDescriptor: ClassDescriptor) {
|
classDescriptor: ClassDescriptor) {
|
||||||
val modifierList = property.modifierList
|
val modifierList = property.modifierList
|
||||||
|
|
||||||
if (modifierList != null && modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
|
if (modifierList != null) {
|
||||||
//has abstract modifier
|
if (modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
|
||||||
if (!classCanHaveAbstractMembers(classDescriptor)) {
|
//has abstract modifier
|
||||||
trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, property.name ?: "", classDescriptor))
|
if (!classCanHaveAbstractMembers(classDescriptor)) {
|
||||||
return
|
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)
|
val hasExternalModifier = function.hasModifier(KtTokens.EXTERNAL_KEYWORD)
|
||||||
|
|
||||||
if (containingDescriptor is ClassDescriptor) {
|
if (containingDescriptor is ClassDescriptor) {
|
||||||
val inTrait = containingDescriptor.kind == ClassKind.INTERFACE
|
val inInterface = containingDescriptor.kind == ClassKind.INTERFACE
|
||||||
if (hasAbstractModifier && !classCanHaveAbstractMembers(containingDescriptor)) {
|
if (hasAbstractModifier && !classCanHaveAbstractMembers(containingDescriptor)) {
|
||||||
trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.name.asString(), containingDescriptor))
|
trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.name.asString(), containingDescriptor))
|
||||||
}
|
}
|
||||||
@@ -615,12 +622,15 @@ class DeclarationsChecker(
|
|||||||
if (hasBody && hasAbstractModifier) {
|
if (hasBody && hasAbstractModifier) {
|
||||||
trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor))
|
trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
if (!hasBody && inTrait) {
|
if (!hasBody && inInterface) {
|
||||||
if (function.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
|
if (function.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
|
||||||
trace.report(PRIVATE_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
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))
|
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
// !DIAGNOSTICS: -CONFLICTING_JVM_DECLARATIONS
|
// !DIAGNOSTICS: -CONFLICTING_JVM_DECLARATIONS
|
||||||
interface One {
|
interface One {
|
||||||
public open fun foo() : Int
|
public <!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun foo() : Int
|
||||||
private fun boo() = 10
|
private fun boo() = 10
|
||||||
}
|
}
|
||||||
interface Two {
|
interface Two {
|
||||||
public open fun foo() : Int
|
public <!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun foo() : Int
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OneImpl : One {
|
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
|
// KT-880 Overload resolution ambiguity
|
||||||
|
|
||||||
public interface I {
|
public interface I {
|
||||||
open fun test() : Unit
|
<!REDUNDANT_OPEN_IN_INTERFACE!>open<!> fun test() : Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public class A() {
|
abstract public class A() {
|
||||||
|
|||||||
@@ -10986,6 +10986,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("primaryConstructorMissingKeyword.kt")
|
||||||
public void testPrimaryConstructorMissingKeyword() throws Exception {
|
public void testPrimaryConstructorMissingKeyword() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/primaryConstructorMissingKeyword.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/primaryConstructorMissingKeyword.kt");
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
|
|
||||||
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true)
|
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true)
|
||||||
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
|
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
|
||||||
|
REDUNDANT_OPEN_IN_INTERFACE.registerFactory(removeRedundantModifierFactory)
|
||||||
|
|
||||||
REDUNDANT_PROJECTION.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(true))
|
REDUNDANT_PROJECTION.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(true))
|
||||||
INCOMPATIBLE_MODIFIERS.registerFactory(RemoveModifierFix.createRemoveModifierFactory(false))
|
INCOMPATIBLE_MODIFIERS.registerFactory(RemoveModifierFix.createRemoveModifierFactory(false))
|
||||||
|
|||||||
Reference in New Issue
Block a user