diff options
author | Manoj Palat | 2020-08-14 07:52:16 +0000 |
---|---|---|
committer | Manoj Palat | 2020-08-14 11:50:38 +0000 |
commit | 0d3a39e6b9eb5cda3a498cd5d8329042abbd25f7 (patch) | |
tree | 824df40a435b5790f33a410b776242ac5a56f696 | |
parent | 7a1b357d9a108bbb81939ab1fab7ec689a126c9f (diff) | |
download | eclipse.jdt.core-0d3a39e6b9eb5cda3a498cd5d8329042abbd25f7.tar.gz eclipse.jdt.core-0d3a39e6b9eb5cda3a498cd5d8329042abbd25f7.tar.xz eclipse.jdt.core-0d3a39e6b9eb5cda3a498cd5d8329042abbd25f7.zip |
Bug 566063 - [15] allow local enums and interfacesY20200817-0450Y20200816-1200Y20200815-1200Y20200814-1200
Change-Id: I0a570219d4715ed05e1a90279202894b38818772
Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
9 files changed, 168 insertions, 14 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java index f3303ad76d..973ae05589 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java @@ -1262,6 +1262,7 @@ public void test011_problem_categories() { expectedProblemAttributes.put("RecordIllegalParameterNameInCanonicalConstructor", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("RecordIllegalExplicitFinalFieldAssignInCompactConstructor", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("RecordMissingExplicitConstructorCallInNonCanonicalConstructor", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); + expectedProblemAttributes.put("RecordIllegalStaticModifierForLocalClassOrInterface", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("SealedMissingClassModifier", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("SealedDisAllowedNonSealedModifierInClass", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("SealedSuperClassDoesNotPermit", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); @@ -2305,6 +2306,7 @@ public void test012_compiler_problems_tuning() { expectedProblemAttributes.put("RecordStaticReferenceToOuterLocalVariable",SKIP); expectedProblemAttributes.put("RecordCannotDefineRecordInLocalType",SKIP); expectedProblemAttributes.put("RecordMissingExplicitConstructorCallInNonCanonicalConstructor",SKIP); + expectedProblemAttributes.put("RecordIllegalStaticModifierForLocalClassOrInterface", SKIP); expectedProblemAttributes.put("RecordComponentsCannotHaveModifiers",SKIP); expectedProblemAttributes.put("RecordIllegalParameterNameInCanonicalConstructor",SKIP); expectedProblemAttributes.put("RecordIllegalExplicitFinalFieldAssignInCompactConstructor",SKIP); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java index 9e77fc5888..0761bc4e31 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java @@ -33,7 +33,7 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { static { // TESTS_NUMBERS = new int [] { 40 }; // TESTS_RANGE = new int[] { 1, -1 }; -// TESTS_NAMES = new String[] { "testBug565786_001"}; +// TESTS_NAMES = new String[] { "testBug566063"}; } public static Class<?> testClass() { @@ -2327,7 +2327,7 @@ public void testBug560893_006() { "X.java", "class X {\n"+ " public static void main(String[] args) {\n"+ - " static record R(int x, int y) {}\n"+ + " record R(int x, int y) {}\n"+ " R r = new R(100,200);\n"+ " System.out.println(r.x());\n"+ " }\n"+ @@ -7597,8 +7597,8 @@ public void testBug563182_07() { }, "java.lang.Record"); } -public void testBug565830_01() { - runConformTest( + public void testBug565830_01() { + runConformTest( new String[] { "X.java", "class X {\n"+ @@ -7620,5 +7620,113 @@ public void testBug565830_01() { "}", }, "private final int X$1Bar.x"); + } +public void testBug566063_001() { + runConformTest( + new String[] { + "X.java", + "class X {\n"+ + " void bar() throws Exception {\n"+ + " enum E {\n"+ + " ONE,\n"+ + " TWO\n"+ + " }\n"+ + " interface I {}\n"+ + " record Bar(E x) implements I{}\n"+ + " E e = new Bar(E.ONE).x();\n"+ + " System.out.println(e);\n"+ + " }\n"+ + " public static void main(String[] args) throws Exception {\n"+ + " new X().bar();\n"+ + " }\n"+ + "}" + }, + "ONE"); +} +public void testBug566063_002() { + runNegativeTest( + new String[] { + "X.java", + "class X {\n"+ + " void bar() throws Exception {\n"+ + " static enum E {\n"+ + " ONE,\n"+ + " TWO\n"+ + " }\n"+ + " interface I {}\n"+ + " record Bar(E x) implements I{}\n"+ + " E e = new Bar(E.ONE).x();\n"+ + " System.out.println(e);\n"+ + " }\n"+ + " public static void main(String[] args) throws Exception {\n"+ + " new X().bar();\n"+ + " }\n"+ + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " static enum E {\n" + + " ^\n" + + "A local interface, enum or record E is implicitly static; cannot have explicit static declaration\n" + + "----------\n"); +} +public void testBug566063_003() { + runNegativeTest( + new String[] { + "X.java", + "class X {\n"+ + " void bar() throws Exception {\n"+ + " static enum E {\n"+ + " ONE,\n"+ + " TWO\n"+ + " }\n"+ + " interface I {}\n"+ + " static record Bar(E x) implements I{}\n"+ + " E e = new Bar(E.ONE).x();\n"+ + " System.out.println(e);\n"+ + " }\n"+ + " public static void main(String[] args) throws Exception {\n"+ + " new X().bar();\n"+ + " }\n"+ + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " static enum E {\n" + + " ^\n" + + "A local interface, enum or record E is implicitly static; cannot have explicit static declaration\n" + + "----------\n" + + "2. ERROR in X.java (at line 8)\n" + + " static record Bar(E x) implements I{}\n" + + " ^^^\n" + + "A local interface, enum or record Bar is implicitly static; cannot have explicit static declaration\n" + + "----------\n"); +} +public void testBug566063_004() { + runNegativeTest( + new String[] { + "X.java", + "class X {\n"+ + " void bar() throws Exception {\n"+ + " enum E {\n"+ + " ONE,\n"+ + " TWO\n"+ + " }\n"+ + " static interface I {}\n"+ + " record Bar(E x) implements I{}\n"+ + " E e = new Bar(E.ONE).x();\n"+ + " System.out.println(e);\n"+ + " }\n"+ + " public static void main(String[] args) throws Exception {\n"+ + " new X().bar();\n"+ + " }\n"+ + "}" + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " static interface I {}\n" + + " ^\n" + + "Illegal modifier for the interface I; only public & abstract are permitted\n" + + "----------\n"); } }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index d514c153d3..677ee71272 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java @@ -2352,6 +2352,9 @@ void setSourceStart(int sourceStart); /** @since 3.23 * @noreference preview feature error */ int RecordMissingExplicitConstructorCallInNonCanonicalConstructor= PreviewRelated + 1760; + /** @since 3.23 + * @noreference preview feature error */ + int RecordIllegalStaticModifierForLocalClassOrInterface = PreviewRelated + 1761; /* records - end */ /* instanceof pattern: */ /** @since 3.22 diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java index 9acea3d9fb..b67ac849d0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java @@ -95,7 +95,6 @@ public class TypeDeclaration extends Statement implements ProblemSeverities, Ref // 14 Records preview support public RecordComponent[] recordComponents; public int nRecordComponents; - public boolean isLocalRecord; public static Set<String> disallowedComponentNames; // 15 Sealed Type preview support diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java index f423dd2e43..3e94497257 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java @@ -564,6 +564,8 @@ public class ClassScope extends Scope { private void checkAndSetModifiers() { SourceTypeBinding sourceType = this.referenceContext.binding; int modifiers = sourceType.modifiers; + boolean isPreviewEnabled = compilerOptions().sourceLevel == ClassFileConstants.getLatestJDKLevel() && + compilerOptions().enablePreviewFeatures; if (sourceType.isRecord()) { /* JLS 14 Records Sec 8.10 - A record declaration is implicitly final. */ modifiers |= ClassFileConstants.AccFinal; @@ -592,14 +594,26 @@ public class ClassScope extends Scope { } } else if (sourceType.isLocalType()) { if (sourceType.isEnum()) { - problemReporter().illegalLocalTypeDeclaration(this.referenceContext); - sourceType.modifiers = 0; - return; + if (!isPreviewEnabled) { + problemReporter().illegalLocalTypeDeclaration(this.referenceContext); + sourceType.modifiers = 0; + return; + } + if ((modifiers & ClassFileConstants.AccStatic) != 0) { + problemReporter().recordIllegalStaticModifierForLocalClassOrInterface(sourceType); + return; + } + modifiers |= ClassFileConstants.AccStatic; } else if (sourceType.isRecord()) { if (enclosingType != null && enclosingType.isLocalType()) { problemReporter().illegalLocalTypeDeclaration(this.referenceContext); return; } + if ((modifiers & ClassFileConstants.AccStatic) != 0) { + problemReporter().recordIllegalStaticModifierForLocalClassOrInterface(sourceType); + return; + } + modifiers |= ClassFileConstants.AccStatic; } if (sourceType.isAnonymousType()) { if (compilerOptions().complianceLevel < ClassFileConstants.JDK9) @@ -681,6 +695,12 @@ public class ClassScope extends Scope { else problemReporter().illegalModifierForInterface(sourceType); } + if (isPreviewEnabled && sourceType.isLocalType()) { +// if ((modifiers & ClassFileConstants.AccStatic) != 0) { +// problemReporter().recordIllegalStaticModifierForLocalClassOrInterface(sourceType); +// } + modifiers |= ClassFileConstants.AccStatic; + } } /* * AccSynthetic must be set if the target is greater than 1.5. 1.5 VM don't support AccSynthetics flag. @@ -690,8 +710,6 @@ public class ClassScope extends Scope { } modifiers |= ClassFileConstants.AccAbstract; } else if ((realModifiers & ClassFileConstants.AccEnum) != 0) { - boolean isPreviewEnabled = compilerOptions().sourceLevel >= ClassFileConstants.JDK15 && - compilerOptions().enablePreviewFeatures; boolean flagSealedNonModifiers = isPreviewEnabled && (modifiers & (ExtraCompilerModifiers.AccSealed | ExtraCompilerModifiers.AccNonSealed)) != 0; // detect abnormal cases for enums diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java index 90f7a9beef..15462264d4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java @@ -82,7 +82,8 @@ public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actual public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEnclosingType) { if (!isPrototype()) throw new IllegalStateException(); if (isStatic()) { - assert this.isRecord();// a local record is implicitly static; no other local type can be static + // Ref JLS 6.1 due to record preview add-on doc: Local Static Interfaces and Enum Classes + // a local record, enum and interface allowed, and will be implicitly static return null; } SyntheticArgumentBinding synthLocal = null; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java index d7730f5afe..9baa6f99fa 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java @@ -973,6 +973,7 @@ protected boolean parsingJava8Plus; protected boolean parsingJava9Plus; protected boolean parsingJava14Plus; protected boolean parsingJava15Plus; +protected boolean previewEnabled; protected boolean parsingJava11Plus; protected int unstackedAct = ERROR_ACTION; private boolean haltOnSyntaxError = false; @@ -997,6 +998,7 @@ public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) { this.parsingJava11Plus = this.options.sourceLevel >= ClassFileConstants.JDK11; this.parsingJava14Plus = this.options.sourceLevel >= ClassFileConstants.JDK14; this.parsingJava15Plus = this.options.sourceLevel >= ClassFileConstants.JDK15; + this.previewEnabled = this.options.sourceLevel == ClassFileConstants.getLatestJDKLevel() && this.options.enablePreviewFeatures; this.astLengthStack = new int[50]; this.patternLengthStack = new int[20]; this.expressionLengthStack = new int[30]; @@ -4875,6 +4877,13 @@ protected void consumeInvalidConstructorDeclaration(boolean hasBody) { } protected void consumeInvalidEnumDeclaration() { // BlockStatement ::= EnumDeclaration + if (this.previewEnabled) { + /* JLS 15 Local Static Interfaces and Enum Classes - Records preview - Sec 6.1 + * A local class or interface (14.3), declared in one of the following: A class declaration, An enum declaration, + * An interface declaration + */ + return; + } TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); // remove the ast node created in interface header @@ -4885,6 +4894,13 @@ protected void consumeInvalidEnumDeclaration() { protected void consumeInvalidInterfaceDeclaration() { // BlockStatement ::= InvalidInterfaceDeclaration //InterfaceDeclaration ::= Modifiersopt 'interface' 'Identifier' ExtendsInterfacesopt InterfaceHeader InterfaceBody + if (this.previewEnabled) { + /* JLS 15 Local Static Interfaces and Enum Classes - Records preview - Sec 6.1 + * A local class or interface (14.3), declared in one of the following: A class declaration, An enum declaration, + * An interface declaration + */ + return; + } TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); // remove the ast node created in interface header @@ -10917,9 +10933,6 @@ protected void consumeRecordComponentHeaderRightParen() { this.astPtr -= length; TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; int nestedMethodLevel = this.nestedMethod[this.nestedType]; - typeDecl.isLocalRecord = nestedMethodLevel > 0; - if (typeDecl.isLocalRecord) - typeDecl.modifiers |= ClassFileConstants.AccStatic; // JLS 14 Sec 14.3 this.recordNestedMethodLevels.put(typeDecl, new Integer[] {this.nestedType, nestedMethodLevel}); this.astStack[this.astPtr] = typeDecl; // rd.sourceEnd = this.rParenPos; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 2ea3d0d547..b472255352 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -11864,6 +11864,15 @@ public void recordMissingExplicitConstructorCallInNonCanonicalConstructor(ASTNod location.sourceStart, location.sourceEnd); } +public void recordIllegalStaticModifierForLocalClassOrInterface(SourceTypeBinding type) { + String[] arguments = new String[] {new String(type.sourceName())}; + this.handle( + IProblem.RecordIllegalStaticModifierForLocalClassOrInterface, + arguments, + arguments, + type.sourceStart(), + type.sourceEnd()); +} private void sealedMissingModifier(int problem, SourceTypeBinding type, TypeDeclaration typeDecl, TypeBinding superTypeBinding) { if (!this.options.enablePreviewFeatures) return; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index 6f180f2ea2..d0a0e3da7c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -1059,6 +1059,7 @@ 1758 = Illegal parameter name {0} in canonical constructor, expected {1}, the corresponding component name 1759 = Illegal explicit assignment of a final field {0} in compact constructor 1760 = A non-canonical constructor must start with an explicit invocation to a constructor +1761 = A local interface, enum or record {0} is implicitly static; cannot have explicit static declaration 1780 = The pattern variable {0} is not in scope in this location |