diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 686696c5eba..410c99efb1a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -328,6 +328,7 @@ public interface Errors { DiagnosticFactory0 PROPERTY_INITIALIZER_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_INITIALIZER_IN_TRAIT = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 FINAL_PROPERTY_IN_TRAIT = DiagnosticFactory0.create(ERROR, FINAL_MODIFIER); + DiagnosticFactory0 PRIVATE_PROPERTY_IN_TRAIT = DiagnosticFactory0.create(ERROR, PRIVATE_MODIFIER); DiagnosticFactory0 BACKING_FIELD_IN_TRAIT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 BACKING_FIELD_SYNTAX_DEPRECATED = DiagnosticFactory0.create(WARNING); @@ -355,6 +356,7 @@ public interface Errors { DiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory1 FINAL_FUNCTION_WITH_NO_BODY = DiagnosticFactory1.create(ERROR, FINAL_MODIFIER); + DiagnosticFactory1 PRIVATE_FUNCTION_WITH_NO_BODY = DiagnosticFactory1.create(ERROR, PRIVATE_MODIFIER); DiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 5a08815254b..a0be395befd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -192,13 +192,11 @@ public object PositioningStrategies { public val ABSTRACT_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.ABSTRACT_KEYWORD) - public val INNER_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.INNER_KEYWORD) - public val OVERRIDE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.OVERRIDE_KEYWORD) public val FINAL_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.FINAL_KEYWORD) - public val SEALED_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.SEALED_KEYWORD) + public val PRIVATE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.PRIVATE_KEYWORD) public val VARIANCE_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 4cc80cd89c9..4e40d43eeac 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -217,6 +217,7 @@ public class DefaultErrorMessages { MAP.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, "Property must be initialized or be abstract"); MAP.put(PROPERTY_INITIALIZER_IN_TRAIT, "Property initializers are not allowed in interfaces"); MAP.put(FINAL_PROPERTY_IN_TRAIT, "Abstract property in an interface cannot be final"); + MAP.put(PRIVATE_PROPERTY_IN_TRAIT, "Abstract property in an interface cannot be private"); MAP.put(EXTENSION_PROPERTY_WITH_BACKING_FIELD, "Extension property cannot be initialized because it has no backing field"); MAP.put(PROPERTY_INITIALIZER_NO_BACKING_FIELD, "Initializer is not allowed here because this property has no backing field"); MAP.put(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, "Abstract property ''{0}'' in non-abstract class ''{1}''", STRING, NAME); @@ -224,6 +225,7 @@ public class DefaultErrorMessages { MAP.put(ABSTRACT_FUNCTION_WITH_BODY, "A function ''{0}'' with body cannot be abstract", NAME); MAP.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without a body must be abstract", NAME); MAP.put(FINAL_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be final", NAME); + MAP.put(PRIVATE_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be private", NAME); MAP.put(NON_MEMBER_FUNCTION_NO_BODY, "Function ''{0}'' must have a body", NAME); MAP.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java index 5809fea4ee0..30dde3715b3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java @@ -428,14 +428,17 @@ public class DeclarationsChecker { boolean hasAccessorImplementation = (getter != null && getter.hasBody()) || (setter != null && setter.hasBody()); + DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); + boolean inTrait = containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor)containingDeclaration).getKind() == ClassKind.INTERFACE; if (propertyDescriptor.getModality() == Modality.ABSTRACT) { if (!property.hasDelegateExpressionOrInitializer() && property.getTypeReference() == null) { trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); } + if (inTrait && property.hasModifier(JetTokens.PRIVATE_KEYWORD) && !property.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { + trace.report(PRIVATE_PROPERTY_IN_TRAIT.on(property)); + } return; } - DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); - boolean inTrait = containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor)containingDeclaration).getKind() == ClassKind.INTERFACE; JetExpression initializer = property.getInitializer(); JetPropertyDelegate delegate = property.getDelegate(); boolean backingFieldRequired = @@ -501,8 +504,13 @@ public class DeclarationsChecker { if (hasBody && hasAbstractModifier) { trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor)); } - if (!hasBody && function.hasModifier(JetTokens.FINAL_KEYWORD) && inTrait) { - trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); + if (!hasBody && inTrait) { + if (function.hasModifier(JetTokens.FINAL_KEYWORD)) { + trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); + } + if (function.hasModifier(JetTokens.PRIVATE_KEYWORD)) { + trace.report(PRIVATE_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); + } } if (!hasBody && !hasAbstractModifier && !inTrait) { trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); diff --git a/compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.out b/compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.out index 7e40c2b5d7b..ea764f7d861 100644 --- a/compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.out +++ b/compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.out @@ -10,4 +10,7 @@ compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.kt:6:14: error: m compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.kt:6:24: error: modifier 'private' is incompatible with 'override' override protected private val c: Int ^ +compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.kt:6:24: error: abstract property in an interface cannot be private + override protected private val c: Int + ^ COMPILATION_ERROR diff --git a/compiler/testData/diagnostics/tests/modifiers/privateInInterface.kt b/compiler/testData/diagnostics/tests/modifiers/privateInInterface.kt new file mode 100644 index 00000000000..3eddb87b0a3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/modifiers/privateInInterface.kt @@ -0,0 +1,12 @@ +interface My { + private val x: Int + private abstract val xx: Int + private val xxx: Int + get() = 0 + final val y: Int + final val yy: Int + get() = 1 + private fun foo(): Int + // ok + private fun bar() = 42 +} diff --git a/compiler/testData/diagnostics/tests/modifiers/privateInInterface.txt b/compiler/testData/diagnostics/tests/modifiers/privateInInterface.txt new file mode 100644 index 00000000000..159f54a6d33 --- /dev/null +++ b/compiler/testData/diagnostics/tests/modifiers/privateInInterface.txt @@ -0,0 +1,14 @@ +package + +public interface My { + private abstract val x: kotlin.Int + private abstract val xx: kotlin.Int + private final val xxx: kotlin.Int + public final val y: kotlin.Int + public final val yy: kotlin.Int + private final fun bar(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + private abstract fun foo(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/variance/Visibility.kt b/compiler/testData/diagnostics/tests/variance/Visibility.kt index 04e2a29c45a..da68aafd7b1 100644 --- a/compiler/testData/diagnostics/tests/variance/Visibility.kt +++ b/compiler/testData/diagnostics/tests/variance/Visibility.kt @@ -2,7 +2,7 @@ interface Test { val internal_val: I public val public_val: I protected val protected_val: I - private val private_val: I + private val private_val: I var interlan_private_set: O private set @@ -10,11 +10,11 @@ interface Test { private set protected var protected_private_set: O private set - private var private_private_set: O + private var private_private_set: O private set fun internal_fun(i: O) : I public fun public_fun(i: O) : I protected fun protected_fun(i: O) : I - private fun private_fun(i: O) : I + private fun private_fun(i: O) : I } \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt b/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt index 56b6a97f8d0..99d16451aa4 100644 --- a/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt +++ b/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.kt @@ -2,11 +2,11 @@ package test public interface Super1 { public fun foo(): CharSequence - private fun bar(): String + private fun bar(): String = "" } public interface Super2 { - private fun foo(): String + private fun foo(): String = "" public fun bar(): CharSequence } diff --git a/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt b/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt index bd668dfd827..528ec2ff23d 100644 --- a/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt +++ b/compiler/testData/loadJava/compiledKotlin/fun/InheritMethodsDifferentReturnTypesAndVisibilities.txt @@ -6,11 +6,11 @@ public interface Sub : test.Super1, test.Super2 { } public interface Super1 { - private abstract fun bar(): kotlin.String + private final fun bar(): kotlin.String public abstract fun foo(): kotlin.CharSequence } public interface Super2 { public abstract fun bar(): kotlin.CharSequence - private abstract fun foo(): kotlin.String + private final fun foo(): kotlin.String } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index d4ff2a9f881..15987b12a4c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -9162,6 +9162,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("privateInInterface.kt") + public void testPrivateInInterface() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/privateInInterface.kt"); + doTest(fileName); + } + @TestMetadata("redundantTargets.kt") public void testRedundantTargets() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/redundantTargets.kt");