diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 0c9fdb15a8a..cb7138032a6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -614,6 +614,8 @@ public interface Errors { DiagnosticFactory1 INACCESSIBLE_OUTER_CLASS_EXPRESSION = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 NESTED_CLASS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, DECLARATION_NAME); + DiagnosticFactory0 INNER_CLASS_IN_TRAIT = DiagnosticFactory0.create(ERROR, PositioningStrategies.INNER_MODIFIER); + //Inline and inlinable parameters DiagnosticFactory2 INVISIBLE_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT); DiagnosticFactory3 NON_LOCAL_RETURN_NOT_ALLOWED = DiagnosticFactory3.create(ERROR, CALL_ELEMENT); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index cbd461e9010..9e17d56173a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -159,6 +159,8 @@ 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) 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 6be59581ced..89de65d92f2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -325,6 +325,8 @@ public class DefaultErrorMessages { MAP.put(INACCESSIBLE_OUTER_CLASS_EXPRESSION, "Expression is inaccessible from a nested class ''{0}'', use ''inner'' keyword to make the class inner", NAME); MAP.put(NESTED_CLASS_NOT_ALLOWED, "Nested class is not allowed here, use ''inner'' keyword to make the class inner"); + MAP.put(INNER_CLASS_IN_TRAIT, "Inner classes are not allowed in traits"); + MAP.put(HAS_NEXT_MISSING, "hasNext() cannot be called on iterator() of type ''{0}''", RENDER_TYPE); MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "hasNext() is ambiguous for iterator() of type ''{0}''", RENDER_TYPE); MAP.put(HAS_NEXT_FUNCTION_NONE_APPLICABLE, "None of the hasNext() functions is applicable for iterator() of type ''{0}''", RENDER_TYPE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index abc640b8fa1..a1880da739f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.kotlin.diagnostics.Errors; +import org.jetbrains.kotlin.diagnostics.*; import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.name.FqName; @@ -195,8 +195,17 @@ public class ModifiersChecker { private void checkInnerModifier(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) { if (modifierListOwner.hasModifier(INNER_KEYWORD)) { - if (isIllegalInner(descriptor)) { - checkIllegalInThisContextModifiers(modifierListOwner, Collections.singletonList(INNER_KEYWORD)); + switch (checkIllegalInner(descriptor)) { + case ALLOWED: + break; + case ILLEGAL_POSITION: + checkIllegalInThisContextModifiers(modifierListOwner, Collections.singletonList(INNER_KEYWORD)); + break; + case IN_TRAIT: + if (modifierListOwner instanceof JetClass) { + trace.report(INNER_CLASS_IN_TRAIT.on((JetClass) modifierListOwner)); + } + break; } return; } @@ -210,12 +219,28 @@ public class ModifiersChecker { } public static boolean isIllegalInner(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof ClassDescriptor)) return true; + return checkIllegalInner(descriptor) != InnerModifierCheckResult.ALLOWED; + } + + private enum InnerModifierCheckResult { + ALLOWED, + ILLEGAL_POSITION, + IN_TRAIT + } + + @NotNull + private static InnerModifierCheckResult checkIllegalInner(DeclarationDescriptor descriptor) { + if (!(descriptor instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION; ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; - if (classDescriptor.getKind() != ClassKind.CLASS) return true; + if (classDescriptor.getKind() != ClassKind.CLASS) return InnerModifierCheckResult.ILLEGAL_POSITION; DeclarationDescriptor containingDeclaration = classDescriptor.getContainingDeclaration(); - if (!(containingDeclaration instanceof ClassDescriptor)) return true; - return ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.TRAIT; + if (!(containingDeclaration instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION; + if (((ClassDescriptor) containingDeclaration).getKind() == ClassKind.TRAIT) { + return InnerModifierCheckResult.IN_TRAIT; + } + else { + return InnerModifierCheckResult.ALLOWED; + } } private static boolean isIllegalNestedClass(@NotNull DeclarationDescriptor descriptor) { diff --git a/compiler/testData/diagnostics/tests/inner/illegalModifier.kt b/compiler/testData/diagnostics/tests/inner/illegalModifier.kt index 2c98ac6fead..dc82914fe3c 100644 --- a/compiler/testData/diagnostics/tests/inner/illegalModifier.kt +++ b/compiler/testData/diagnostics/tests/inner/illegalModifier.kt @@ -23,7 +23,7 @@ enum class H { } trait K { - inner class L + inner class L } object N {