Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2020-05-21 17:35:57 +0000
committerStephan Herrmann2020-05-24 15:49:24 +0000
commit58a50904739546681d02ab1b39483a53e0c4d816 (patch)
tree0061554aef47a493aa1794451c978c74ba4ddde3
parent7f8076f82d8176978d063aa9b63ab0965712e4ca (diff)
downloadorg.eclipse.objectteams-58a50904739546681d02ab1b39483a53e0c4d816.tar.gz
org.eclipse.objectteams-58a50904739546681d02ab1b39483a53e0c4d816.tar.xz
org.eclipse.objectteams-58a50904739546681d02ab1b39483a53e0c4d816.zip
update jdt.core to I20200521-1000 for 4.16 M3
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java8
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceElementParserTest.java19
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceType.java18
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestSourceElementRequestor.java2
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java7
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java6
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java38
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java8
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java65
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaShapeTests.java2
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java462
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java1060
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java64
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java2985
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java528
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java3
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java1
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest2.java20
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java6
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java29
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionWithMissingTypesTests_1_8.java93
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CopyMoveTests.java14
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs14Tests.java67
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java53
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RecordsElementTests.java124
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java1
-rw-r--r--org.eclipse.jdt.core/.settings/org.eclipse.jdt.ui.prefs4
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java30
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java224
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java128
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java42
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java45
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java32
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java35
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java24
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java28
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java14
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordComponent.java158
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java25
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java29
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java57
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java30
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java64
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerStats.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java29
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java58
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtendedTagBits.java22
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java14
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RecordComponentBinding.java146
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java275
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java31
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java82
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java74
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java429
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java125
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java167
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java4
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java8
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java23
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java131
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java17
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java76
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java10
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java30
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java46
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java66
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java14
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java14
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java10
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java7
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java3
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java35
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java42
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java2
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java63
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java193
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java33
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java256
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java12
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/OTType.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/PhantomType.java7
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java9
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java5
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java15
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java2
-rw-r--r--testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/SourceElementRequestorTest.java13
-rw-r--r--testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/smap/AbstractSourceMapGeneratorTest.java25
-rw-r--r--testplugins/org.eclipse.objectteams.otdt.tests/parser/org/eclipse/objectteams/otdt/tests/parser/SourceElementParserTest.java11
124 files changed, 5786 insertions, 3775 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java
index c70decd56..6b181e77a 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 IBM Corporation and others.
+ * Copyright (c) 2012, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -446,6 +446,8 @@ public class AbstractSyntaxTreeTest extends AbstractCompilerTest implements IDoc
}
+ public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
+ }
public void enterInitializer(int declarationStart, int modifiers) {
@@ -486,6 +488,10 @@ public class AbstractSyntaxTreeTest extends AbstractCompilerTest implements IDoc
}
+ @Override
+ public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+
+ }
//{ObjectTeams: new methods
public void acceptBaseReference(char[][] typeName, int sourceStart, int sourceEnd) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceElementParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceElementParserTest.java
index d15208ff8..dd28daac3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceElementParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceElementParserTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -38,6 +38,7 @@ public class SourceElementParserTest extends AbstractCompilerTest implements ISo
private SourceType currentType;
private SourceMethod currentMethod;
private SourceField currentField;
+ private SourceField currentRecordComp;
private SourceInitializer currentInitializer;
private char[] source;
private SourcePackage currentPackage;
@@ -258,6 +259,19 @@ public void enterField(FieldInfo fieldInfo) {
this.source));
}
+public void enterRecordComponent(RecordComponentInfo compInfo) {
+ this.currentType.addRecordComponent(
+ this.currentRecordComp =
+ new SourceField(
+ compInfo.declarationStart,
+ compInfo.modifiers,
+ compInfo.type,
+ compInfo.name,
+ compInfo.nameSourceStart,
+ compInfo.nameSourceEnd,
+ this.source));
+
+}
public void enterInitializer(int declarationSourceStart, int modifiers) {
this.currentType.addField(
this.currentInitializer = new SourceInitializer(
@@ -329,6 +343,9 @@ public void exitConstructor(int declarationEnd) {
public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
this.currentField.setDeclarationSourceEnd(declarationEnd);
}
+public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ this.currentRecordComp.setDeclarationSourceEnd(declarationEnd);
+}
public void exitMethod(int declarationEnd, Expression defaultValue) {
exitAbstractMethod(declarationEnd);
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceType.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceType.java
index 097928723..e606ed7d5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceType.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SourceType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -33,7 +33,9 @@ public final class SourceType {
private SourceMethod[] methods;
private int numberOfMethods;
private SourceField[] fields;
+ private SourceField[] recordComponents;
private int numberOfFields;
+ private int numberOfComponents;
private char[] source;
SourceType parent;
char[][] typeParameterNames;
@@ -79,6 +81,20 @@ protected void addField(SourceField sourceField) {
}
this.fields[this.numberOfFields++] = sourceField;
}
+protected void addRecordComponent(SourceField comp) {
+ if (this.recordComponents == null) {
+ this.recordComponents = new SourceField[4];
+ }
+ if (this.numberOfComponents == this.recordComponents.length) {
+ System.arraycopy(
+ this.recordComponents,
+ 0,
+ this.recordComponents = new SourceField[this.numberOfComponents * 2],
+ 0,
+ this.numberOfComponents);
+ }
+ this.recordComponents[this.numberOfComponents++] = comp;
+}
protected void addMemberType(SourceType sourceMemberType) {
if(this.memberTypes == null) {
this.memberTypes = new SourceType[4];
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestSourceElementRequestor.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestSourceElementRequestor.java
index 669dae820..153d80296 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestSourceElementRequestor.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestSourceElementRequestor.java
@@ -90,6 +90,7 @@ public void enterConstructor(MethodInfo methodInfo) {}
* enterField method comment.
*/
public void enterField(FieldInfo fieldInfo) {}
+public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {}
/**
* enterMethod method comment.
*/
@@ -110,6 +111,7 @@ public void exitConstructor(int declarationEnd) {}
* exitField method comment.
*/
public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {}
+public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {}
/**
* exitMethod method comment.
*/
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index a76df3a1c..ae23301ee 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -1093,6 +1093,13 @@ protected static class JavacTestOptions {
return compiler.compliance < ClassFileConstants.JDK9 ? null : this;
}
}: null;
+ public static JavacHasABug
+ NoWarningForMissingJavadocTag = RUN_JAVAC ?
+ new JavacHasABug(MismatchType.EclipseErrorsJavacNone)
+ : null,
+ NoWarningForDuplicateJavadocTag = RUN_JAVAC ?
+ new JavacHasABug(MismatchType.EclipseErrorsJavacNone)
+ : null;
}
public static class JavacBug8179483 extends JavacHasABug {
String extraJavacOptions;
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 78ba4f594..abdb30da8 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
@@ -761,6 +761,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("JavadocNonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
expectedProblemAttributes.put("JavadocNonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
expectedProblemAttributes.put("JavadocNonStaticTypeFromStaticInvocation", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+ expectedProblemAttributes.put("JavadocNotAccessibleType", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
expectedProblemAttributes.put("JavadocNotVisibleConstructor", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
expectedProblemAttributes.put("JavadocNotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
expectedProblemAttributes.put("JavadocNotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
@@ -1100,6 +1101,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("UnqualifiedFieldAccess", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("UnreachableCatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("UnresolvedVariable", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("UnsafeCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("UnsafeElementTypeConversion", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeGenericArrayForVarargs", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeGenericCast", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
@@ -1312,6 +1314,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("SwitchExpressionsNotSupported", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("SwitchExpressionsBreakOutOfSwitchExpression", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("SwitchExpressionsContinueOutOfSwitchExpression", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
+ expectedProblemAttributes.put("SwitchExpressionsReturnWithinSwitchExpression", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("RecordIllegalModifierForRecord", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("RecordIllegalModifierForInnerRecord", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("RecordIllegalComponentNameInRecord", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
@@ -1868,6 +1871,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("JavadocNonGenericConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
expectedProblemAttributes.put("JavadocNonGenericMethod", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
expectedProblemAttributes.put("JavadocNonStaticTypeFromStaticInvocation", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+ expectedProblemAttributes.put("JavadocNotAccessibleType", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
expectedProblemAttributes.put("JavadocNotVisibleConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
expectedProblemAttributes.put("JavadocNotVisibleField", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
expectedProblemAttributes.put("JavadocNotVisibleMethod", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
@@ -2208,6 +2212,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("UnqualifiedFieldAccess", new ProblemAttributes(JavaCore.COMPILER_PB_UNQUALIFIED_FIELD_ACCESS));
expectedProblemAttributes.put("UnreachableCatch", SKIP);
expectedProblemAttributes.put("UnresolvedVariable", SKIP);
+ expectedProblemAttributes.put("UnsafeCast", SKIP);
expectedProblemAttributes.put("UnsafeElementTypeConversion", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeGenericArrayForVarargs", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeGenericCast", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
@@ -2954,6 +2959,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("SwitchExpressionsNotSupported", SKIP);
expectedProblemAttributes.put("SwitchExpressionsBreakOutOfSwitchExpression", SKIP);
expectedProblemAttributes.put("SwitchExpressionsContinueOutOfSwitchExpression", SKIP);
+ expectedProblemAttributes.put("SwitchExpressionsReturnWithinSwitchExpression", SKIP);
expectedProblemAttributes.put("RecordIllegalModifierForRecord", SKIP);
expectedProblemAttributes.put("RecordIllegalModifierForInnerRecord", SKIP);
expectedProblemAttributes.put("RecordIllegalComponentNameInRecord", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index 03c803310..fceca1ee1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -5407,10 +5407,12 @@ public class GenericTypeTest extends AbstractComparableTest {
true,
customOptions);
}
- public void _test0178a() {
+ public void test0178a() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
this.runNegativeTest(
new String[] {
"X.java",
@@ -5426,7 +5428,7 @@ public class GenericTypeTest extends AbstractComparableTest {
" return t;\n" +
" } else if (t instanceof T) {\n" +
" return t;\n" +
- " } else if (t instanceof X) {\n" +
+ " } else if (t instanceof X) { // this is allowed since Java 14 as preview feature\n" +
" return t;\n" +
" }\n" +
" return null;\n" +
@@ -5436,13 +5438,33 @@ public class GenericTypeTest extends AbstractComparableTest {
"----------\n" +
"1. ERROR in X.java (at line 5)\n" +
" if (t instanceof X<T>) {\n" +
- " ^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from T to X<T>\n" +
+ " ^\n" +
+ "Type T cannot be safely cast to X<T>\n" +
"----------\n" +
- "2. ERROR in X.java (at line 7)\n" +
+ "2. WARNING in X.java (at line 5)\n" +
+ " if (t instanceof X<T>) {\n" +
+ " ^\n" +
+ "You are using a preview language feature that may or may not be supported in a future release\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
" } else if (t instanceof X<String>) {\n" +
- " ^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from T to X<String>\n" +
+ " ^\n" +
+ "Type T cannot be safely cast to X<String>\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 7)\n" +
+ " } else if (t instanceof X<String>) {\n" +
+ " ^\n" +
+ "You are using a preview language feature that may or may not be supported in a future release\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 11)\n" +
+ " } else if (t instanceof T) {\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "The expression of type T is already an instance of type T\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 11)\n" +
+ " } else if (t instanceof T) {\n" +
+ " ^\n" +
+ "You are using a preview language feature that may or may not be supported in a future release\n" +
"----------\n",
null,
true,
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java
index 20dffa7f3..66e672d6c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java
@@ -46,8 +46,6 @@ public abstract class JavadocTest extends AbstractRegressionTest {
ALL_CLASSES.add(JavadocTestForMethod.class);
ALL_CLASSES.add(JavadocTestMixed.class);
ALL_CLASSES.add(JavadocTestForClass.class);
- ALL_CLASSES.add(JavadocTestForRecord.class);
- ALL_CLASSES.add(JavadocTestForModule.class);
ALL_CLASSES.add(JavadocTestForConstructor.class);
ALL_CLASSES.add(JavadocTestForField.class);
ALL_CLASSES.add(JavadocTestForInterface.class);
@@ -85,6 +83,12 @@ public abstract class JavadocTest extends AbstractRegressionTest {
if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) {
testSuite.addTest(buildUniqueComplianceTestSuite(JavadocTest_1_5.class, ClassFileConstants.JDK1_5));
}
+ if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
+ testSuite.addTest(buildUniqueComplianceTestSuite(JavadocTestForModule.class, ClassFileConstants.JDK9));
+ }
+ if ((complianceLevels & AbstractCompilerTest.F_14) != 0) {
+ testSuite.addTest(buildUniqueComplianceTestSuite(JavadocTestForRecord.class, ClassFileConstants.JDK14));
+ }
return testSuite;
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java
index 466ac72d8..a95415607 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java
@@ -306,6 +306,10 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
skipNext = true;
continue;
}
+ if (tokens[i].trim().equals("-enableJavadoc")) {
+ buf.append(" -Xdoclint:all ");
+ continue;
+ }
buf.append(tokens[i]).append(' ');
}
if (versionOptions != null) {
@@ -418,7 +422,9 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"2 problems (2 errors)\n",
false,
- "missing tags");
+ "missing tags",
+ OUTPUT_DIR,
+ JavacTestOptions.JavacHasABug.NoWarningForMissingJavadocTag);
}
public void testBug549855b() {
@@ -491,7 +497,7 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"2 problems (2 errors)\n",
false,
- "missing and invalid tags");
+ "service-type not found");
}
public void testBug549855c() {
@@ -566,7 +572,9 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"2 problems (2 errors)\n",
false,
- "duplicate tags");
+ "duplicate tags",
+ OUTPUT_DIR,
+ JavacTestOptions.JavacHasABug.NoWarningForDuplicateJavadocTag);
}
public void testBug549855d() {
@@ -686,7 +694,9 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"1 problem (1 error)\n",
false,
- "missing tags");
+ "missing tags",
+ OUTPUT_DIR,
+ JavacTestOptions.JavacHasABug.NoWarningForMissingJavadocTag);
}
public void testBug549855f() {
@@ -753,7 +763,9 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"1 problem (1 error)\n",
false,
- "missing tags");
+ "missing tags",
+ OUTPUT_DIR,
+ JavacTestOptions.JavacHasABug.NoWarningForMissingJavadocTag);
}
public void testBug549855g() {
@@ -824,7 +836,9 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"2 problems (2 errors)\n",
false,
- "missing tags");
+ "missing tags",
+ OUTPUT_DIR,
+ JavacTestOptions.JavacHasABug.NoWarningForMissingJavadocTag);
}
public void testBug549855h() {
@@ -897,7 +911,7 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"2 problems (2 errors)\n",
false,
- "invalid tags");
+ "reference not found");
}
public void testBug549855i() {
@@ -935,7 +949,42 @@ public class JavadocTestForModule extends AbstractBatchCompilerTest {
"----------\n" +
"1 problem (1 error)\n",
false,
- "missing comment");
+ "no comment");
+ }
+
+ public void testBug562960() {
+ File outputDirectory = new File(OUTPUT_DIR);
+ Util.flushDirectoryContent(outputDirectory);
+ String out = "bin";
+ String directory = OUTPUT_DIR + File.separator + "src";
+
+ String options =
+ "-d " + OUTPUT_DIR + File.separator + out +
+ " -9 " +
+ " -enableJavadoc " +
+ " -err:allJavadoc " +
+ " -classpath \"" + Util.getJavaClassLibsAsString() + "\" " +
+ directory + File.separator + "Test.java";
+
+ runNegativeModuleTest(
+ new String[] {
+ "src/Test.java",
+ "/**\n" +
+ " * {@link sun.security.ssl.X509TrustManagerImpl}\n" +
+ " */\n" +
+ "public class Test {}\n"
+ },
+ options,
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/Test.java (at line 2)\n" +
+ " * {@link sun.security.ssl.X509TrustManagerImpl}\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Javadoc: The type sun.security.ssl.X509TrustManagerImpl is not accessible\n" +
+ "----------\n" +
+ "1 problem (1 error)\n",
+ false,
+ "reference not found");
}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaShapeTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaShapeTests.java
index c892bd5e2..97c50dfff 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaShapeTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaShapeTests.java
@@ -18,7 +18,7 @@ import junit.framework.Test;
@SuppressWarnings({ "rawtypes" })
public class LambdaShapeTests extends AbstractRegressionTest {
static {
-// TESTS_NAMES = new String[] { "testWhileThis"};
+// TESTS_NAMES = new String[] { "test016"};
// TESTS_NUMBERS = new int[] { 50 };
// TESTS_RANGE = new int[] { 11, -1 };
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
index dab2d3f34..016414f1d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
@@ -24,7 +24,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "test005" };
+// TESTS_NAMES = new String[] { "testBug562392" };
}
public static Class<?> testClass() {
@@ -2045,7 +2045,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
compilerOptions);
compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, old);
}
- public void _testBug562392a() {
+ public void testBug562392a() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runConformTest(
new String[] {
@@ -2067,11 +2067,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"true",
compilerOptions);
}
- public void _testBug562392b() {
+ public void testBug562392b() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runNegativeTest(
new String[] {
"X.java",
+ "@SuppressWarnings(\"preview\")\n" +
"public class X<T> {\n" +
" public boolean foo(Object obj) {\n" +
" if (obj instanceof T) {\n" +
@@ -2085,17 +2086,21 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X.java (at line 3)\n" +
+ "1. ERROR in X.java (at line 4)\n" +
" if (obj instanceof T) {\n" +
- " ^^^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from Object to T\n" +
+ " ^^^\n" +
+ "Type Object cannot be safely cast to T\n" +
"----------\n",
- "",
+ "X.java:4: error: Object cannot be safely cast to T\n" +
+ " if (obj instanceof T) {\n" +
+ " ^\n" +
+ " where T is a type-variable:\n" +
+ " T extends Object declared in class X",
null,
true,
compilerOptions);
}
- public void _testBug562392c() {
+ public void testBug562392c() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runNegativeTest(
new String[] {
@@ -2116,15 +2121,19 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"----------\n" +
"1. ERROR in X.java (at line 4)\n" +
" if (obj instanceof T t) {\n" +
- " ^^^^^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from Object to T\n" +
+ " ^^^\n" +
+ "Type Object cannot be safely cast to T\n" +
"----------\n",
- "",
+ "X.java:4: error: Object cannot be safely cast to T\n" +
+ " if (obj instanceof T t) {\n" +
+ " ^\n" +
+ " where T is a type-variable:\n" +
+ " T extends Object declared in class X",
null,
true,
compilerOptions);
}
- public void _testBug562392d() {
+ public void testBug562392d() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runConformTest(
new String[] {
@@ -2144,5 +2153,434 @@ public class PatternMatching14Test extends AbstractRegressionTest {
},
"",
compilerOptions);
+ }
+ public void testBug562392e() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X<T> {\n" +
+ " public boolean foo(X<?> obj) {\n" +
+ " if (obj instanceof X<String> p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " if (obj instanceof X<String> p) {\n" +
+ " ^^^\n" +
+ "Type X<capture#1-of ?> cannot be safely cast to X<String>\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void testBug562392f() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "class Outer<T> {\n" +
+ " static class Inner<T> {\n" +
+ " }\n" +
+ "}\n" +
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "class X<T> {\n" +
+ " public boolean foo(Outer.Inner obj) {\n" +
+ " if (obj instanceof Outer<?> p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " if (obj instanceof Outer<?> p) {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Incompatible conditional operand types Outer.Inner and Outer<?>\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void testBug562392g() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "class Outer<T> {\n" +
+ " static class Inner<T> {\n" +
+ " }\n" +
+ "}\n" +
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "class X<T> {\n" +
+ " public boolean foo(Object obj) {\n" +
+ " if (obj instanceof Outer.Inner<?> p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " Outer.Inner inn = new Outer.Inner();\n" +
+ " System.out.println(new X<String>().foo(inn));\n" +
+ " }\n" +
+ "}\n",
+ },
+ "true",
+ compilerOptions);
+ }
+ public void testBug562392h() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "public class X<T> {\n" +
+ " public boolean foo(X[] obj) {\n" +
+ " if (obj instanceof Object[] p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " Object[] param = {new X()};\n" +
+ " System.out.println(new X<String>().foo(param));\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " System.out.println(new X<String>().foo(param));\n" +
+ " ^^^\n" +
+ "The method foo(X[]) in the type X<String> is not applicable for the arguments (Object[])\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void testBug562392i() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ String backup = compilerOptions.get(CompilerOptions.OPTION_EnablePreviews);
+ compilerOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
+ try {
+ runNegativeTest(
+ new String[] {
+ "Test.java",
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import java.util.function.Function;\n" +
+ "import java.util.function.UnaryOperator;\n" +
+ "@SuppressWarnings({\"preview\"})\n" +
+ "public class Test<T> {\n" +
+ " public boolean foo(Function<ArrayList<T>, ArrayList<T>> obj) {\n" +
+ " if (obj instanceof UnaryOperator<? extends List<T>>) {\n" +
+ " return false;\n" +
+ " }\n" +
+ " return true;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in Test.java (at line 8)\n" +
+ " if (obj instanceof UnaryOperator<? extends List<T>>) {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Cannot perform instanceof check against parameterized type UnaryOperator<? extends List<T>>. Use the form UnaryOperator<?> instead since further generic type information will be erased at runtime\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ } finally {
+ compilerOptions.put(CompilerOptions.OPTION_EnablePreviews, backup);
+ }
+ }
+ public void testBug562392j() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "Test.java",
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import java.util.function.Function;\n" +
+ "import java.util.function.UnaryOperator;\n" +
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "public class Test<T> {\n" +
+ " public boolean foo(Function<ArrayList<T>, ArrayList<T>> obj) {\n" +
+ " if (obj instanceof UnaryOperator<? extends List<T>>) {\n" +
+ " return false;\n" +
+ " }\n" +
+ " return true;\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " System.out.println(\"\");\n" +
+ " }\n" +
+ "}\n",
+ },
+ "",
+ compilerOptions);
+ }
+ public void test053() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " @SuppressWarnings(\"preview\")\n" +
+ " public static void main(String argv[]) {\n" +
+ " Object obj = \"x\";\n" +
+ " if (obj instanceof String s) {\n" +
+ " System.out.println(s);\n" +
+ " }\n" +
+ " String s = \"y\";\n" +
+ " System.out.println(s);\n" +
+ " }\n" +
+ "}\n",
+ },
+ "x\n" +
+ "y",
+ compilerOptions);
+ }
+ public void test054() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " @SuppressWarnings(\"preview\")\n" +
+ " public static void main(String argv[]) {\n" +
+ " Object obj = \"x\";\n" +
+ " while (!(obj instanceof String s)) {\n" +
+ " String s = \"y\";\n" +
+ " System.out.println(s);\n" +
+ " }\n" +
+ " System.out.println(s);\n" +
+ " }\n" +
+ "}\n",
+ },
+ "x",
+ compilerOptions);
+ }
+ public void test055() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ "public static void main(String argv[]) {\n" +
+ " String result = \"\";\n" +
+ " Object obj = \"abc\";\n" +
+ " for (; !(obj instanceof String a);) {\n" +
+ " String a = \"\";\n" +
+ " result = a;\n" +
+ " obj = null;\n" +
+ " }\n" +
+ " if (!result.equals(\"abc\")) {\n" +
+ " System.out.println(\"PASS\");\n" +
+ " } else {\n" +
+ " System.out.println(\"FAIL\");\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "PASS",
+ compilerOptions);
+ }
+ // Positive - Test conflicting pattern variable and lambda argument in for loop
+ public void test056() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X {\n" +
+ " public static int impl(I a) {\n" +
+ " return a.foo(\"Default\");\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " String result = \"\";\n" +
+ " Object obj = \"a\";\n" +
+ " for (int i = 0; !(obj instanceof String a); i = impl(a -> a.length())) {\n" +
+ " obj = null;\n" +
+ " }\n" +
+ " if (!result.equals(\"\"))\n" +
+ " System.out.println(\"FAIL\");\n" +
+ " else\n" +
+ " System.out.println(\"PASS\");\n" +
+ " }\n" +
+ "}\n" +
+ "interface I {\n" +
+ " int foo(String s);\n" +
+ "}\n",
+ },
+ "PASS",
+ compilerOptions);
+ }
+ // Positive - Test conflicting pattern variable and lambda argument in for loop (block)
+ public void test056a() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X {\n" +
+ " public static int impl(I a) {\n" +
+ " return a.foo(\"Default\");\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " String result = \"\";\n" +
+ " Object obj = \"a\";\n" +
+ " for (int i = 0; !(obj instanceof String a); i = impl(x -> {\n" +
+ " String a = \"\";\n" +
+ " return a.length();\n" +
+ " })) {\n" +
+ " obj = null;\n" +
+ " }\n" +
+ " if (!result.equals(\"\"))\n" +
+ " System.out.println(\"FAIL\");\n" +
+ " else\n" +
+ " System.out.println(\"PASS\");\n" +
+ " }\n" +
+ "}\n" +
+ "interface I {\n" +
+ " int foo(String s);\n" +
+ "}\n",
+ },
+ "PASS",
+ compilerOptions);
+ }
+ // Positive - Test conflicting pattern variable and lambda argument in if
+ public void test056b() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X {\n" +
+ " public static int impl(I a) {\n" +
+ " return a.foo(\"Default\");\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " String result = \"\";\n" +
+ " Object obj = \"a\";\n" +
+ " if (!(obj instanceof String a)) {\n" +
+ " int i = impl(a -> a.length());\n" +
+ " }\n" +
+ " if (!result.equals(\"\"))\n" +
+ " System.out.println(\"FAIL\");\n" +
+ " else\n" +
+ " System.out.println(\"PASS\");\n" +
+ " }\n" +
+ "}\n" +
+ "interface I {\n" +
+ " int foo(String s);\n" +
+ "}\n",
+ },
+ "PASS",
+ compilerOptions);
+ }
+ // Positive - Test conflicting pattern variable and lambda argument in if
+ public void test056d() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X {\n" +
+ " public static int impl(I a) {\n" +
+ " return a.foo(\"Default\");\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " String result = \"\";\n" +
+ " Object obj = \"a\";\n" +
+ " for (int i = 0; (obj instanceof String a); i = impl(a -> a.length())) {\n" +
+ " obj = null;\n" +
+ " }\n" +
+ " if (!result.equals(\"\"))\n" +
+ " System.out.println(\"FAIL\");\n" +
+ " else\n" +
+ " System.out.println(\"PASS\");\n" +
+ " }\n" +
+ "}\n" +
+ "interface I {\n" +
+ " int foo(String s);\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " for (int i = 0; (obj instanceof String a); i = impl(a -> a.length())) {\n" +
+ " ^\n" +
+ "Lambda expression\'s parameter a cannot redeclare another local variable defined in an enclosing scope. \n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ /*
+ * Test we report only one duplicate variable, i.e., in THEN stmt
+ * where pattern variable is in scope.
+ */
+ public void test057() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " @SuppressWarnings(\"preview\")\n" +
+ " public static void main(String argv[]) {\n" +
+ " Object obj = \"x\";\n" +
+ " if (obj instanceof String s) {\n" +
+ " String s = \"\";\n" +
+ " System.out.println(s);\n" +
+ " }\n" +
+ " String s = \"y\";\n" +
+ " System.out.println(s);\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " String s = \"\";\n" +
+ " ^\n" +
+ "Duplicate local variable s\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
}
+ public void test058() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " @SuppressWarnings(\"preview\")\n" +
+ " public static void main(String[] s) {\n" +
+ " Object obj = \"x\";\n" +
+ " if (obj instanceof String[] s && s.length > 0) {\n" +
+ " System.out.println(s[0]);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " if (obj instanceof String[] s && s.length > 0) {\n" +
+ " ^\n" +
+ "Duplicate local variable s\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
}
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 e889e1574..c9e4c5bf7 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
@@ -29,7 +29,7 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest {
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "testBug560798_002" };
+// TESTS_NAMES = new String[] { "testBug562439"};
}
public static Class<?> testClass() {
@@ -567,6 +567,11 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest {
"----------\n" +
"1. ERROR in X.java (at line 6)\n" +
" record Point(int myInt, int myZ, int myZ) implements I {\n" +
+ " ^^^\n" +
+ "Duplicate component myZ in record\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " record Point(int myInt, int myZ, int myZ) implements I {\n" +
" ^^^\n" +
"Duplicate component myZ in record\n" +
"----------\n");
@@ -591,11 +596,16 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest {
"----------\n" +
"1. ERROR in X.java (at line 6)\n" +
" record Point(int myInt, int myInt, int myInt, int myZ) implements I {\n" +
- " ^^^^^\n" +
+ " ^^^^^\n" +
"Duplicate component myInt in record\n" +
"----------\n" +
"2. ERROR in X.java (at line 6)\n" +
" record Point(int myInt, int myInt, int myInt, int myZ) implements I {\n" +
+ " ^^^^^\n" +
+ "Duplicate component myInt in record\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 6)\n" +
+ " record Point(int myInt, int myInt, int myInt, int myZ) implements I {\n" +
" ^^^^^\n" +
"Duplicate component myInt in record\n" +
"----------\n");
@@ -1785,7 +1795,7 @@ public void testBug559281_001() {
"----------\n" +
"1. ERROR in X.java (at line 1)\n" +
" record X(void k) {}\n" +
- " ^\n" +
+ " ^\n" +
"void is an invalid type for the component k of a record\n" +
"----------\n");
}
@@ -2614,7 +2624,7 @@ public void testBug562219_002() {
* Test that annotation with implicit target as METHOD are included in the
* generated bytecode on the record component and its accessor method
*/
-public void _test562250a() throws IOException, ClassFormatException {
+public void test562250a() throws IOException, ClassFormatException {
runConformTest(
new String[] {
"X.java",
@@ -2653,9 +2663,9 @@ public void _test562250a() throws IOException, ClassFormatException {
}
/*
* Test that annotation with explicit target as METHOD are included in the
- * generated bytecode on the record component and its accessor method
+ * generated bytecode on its accessor method (and not on record component)
*/
-public void _test562250b() throws IOException, ClassFormatException {
+public void test562250b() throws IOException, ClassFormatException {
runConformTest(
new String[] {
"X.java",
@@ -2689,7 +2699,6 @@ public void _test562250b() throws IOException, ClassFormatException {
"}"
},
"RecordComponents:\n" +
- "@Annot()\n" +
"Accessors:\n" +
"@Annot()");
}
@@ -2698,7 +2707,7 @@ public void _test562250b() throws IOException, ClassFormatException {
* compiler on a record component, the generated bytecode doesn't contain these annotations
* on the record component.
*/
-public void _test562250c() throws IOException, ClassFormatException {
+public void test562250c() throws IOException, ClassFormatException {
runConformTest(
new String[] {
"X.java",
@@ -2734,4 +2743,1039 @@ public void _test562250c() throws IOException, ClassFormatException {
"RecordComponents:\n" +
"Accessors:");
}
+public void testBug562439_001() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RC int myInt, char myChar) { \n"+
+ "} \n"+
+ "\n"+
+ "@Target({ElementType.RECORD_COMPONENT})\n"+
+ "@interface RC {}\n"
+ },
+ "100");
+ String expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #61 @RC(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_002() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RC int myInt, char myChar) { \n"+
+ "} \n"+
+ "\n"+
+ "@Target({ElementType.RECORD_COMPONENT})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n"+
+ "@interface RC {}\n"
+ },
+ "100");
+ String expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #61 @RC(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_003() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCF int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.FIELD})\n"+
+ "@interface RCF {}\n"
+ },
+ "100");
+ String expectedOutput = " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RCF(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RCF(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_004() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCF int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.FIELD})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface RCF {}\n"
+ },
+ "100");
+ String expectedOutput = " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RCF(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RCF(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_005() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RF int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ElementType.FIELD})\n"+
+ "@interface RF {}\n"
+ },
+ "100");
+ String expectedOutput = " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RF(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ "// Component descriptor #10 C\n" +
+ "char myChar;\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_006() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RF int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ElementType.FIELD})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface RF {}\n"
+ },
+ "100");
+ String expectedOutput = " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RF(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ "// Component descriptor #10 C\n" +
+ "char myChar;\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_007() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCFU int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.FIELD, ElementType.TYPE_USE})\n"+
+ "@interface RCFU {}\n"
+ },
+ "100");
+ String expectedOutput = " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " )\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput = "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " )\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_008() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCFU int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.FIELD, ElementType.TYPE_USE})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface RCFU {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " )\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " )\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @RCFU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_009() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCM int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.METHOD})\n"+
+ "@interface RCM {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Method descriptor #23 ()I\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [15]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #25 @RCM(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #25 @RCM(\n" +
+ " )\n" +
+ "// Component descriptor #8 C\n" +
+ "char myChar;\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_010() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCM int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.METHOD})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface RCM {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [15]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #25 @RCM(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #25 @RCM(\n" +
+ " )\n" +
+ "// Component descriptor #8 C\n" +
+ "char myChar;\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_011() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@M int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ElementType.METHOD})\n"+
+ "@interface M {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Method descriptor #23 ()I\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [15]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #25 @M(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ "// Component descriptor #8 C\n" +
+ "char myChar;\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_012() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@M int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ElementType.METHOD})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface M {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [15]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #25 @M(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ "// Component descriptor #8 C\n" +
+ "char myChar;\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_013() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCMU int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.METHOD, ElementType.TYPE_USE})\n"+
+ "@interface RCMU {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " // Method descriptor #25 ()I\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [17]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " )\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_014() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCMU int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.METHOD, ElementType.TYPE_USE})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface RCMU {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " // Method descriptor #25 ()I\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [17]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " )\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @RCMU(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_015() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@T int myInt, char myChar) { \n"+
+ "} \n"+
+ "\n"+
+ "@Target({ElementType.TYPE_USE})\n"+
+ "@interface T {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @T(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " // Method descriptor #25 ()I\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [17]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @T(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @T(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " public Point(int myInt, char myChar);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Record() [14]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 iload_1 [myInt]\n" +
+ " 6 putfield Point.myInt : int [17]\n" +
+ " 9 aload_0 [this]\n" +
+ " 10 iload_2 [myChar]\n" +
+ " 11 putfield Point.myChar : char [19]\n" +
+ " 14 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 15] local: this index: 0 type: Point\n" +
+ " [pc: 0, pc: 15] local: myInt index: 1 type: int\n" +
+ " [pc: 0, pc: 15] local: myChar index: 2 type: char\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @T(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_016() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@T int myInt, char myChar) { \n"+
+ "} \n"+
+ "\n"+
+ "@Target({ElementType.TYPE_USE})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n"+
+ "@interface T {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @T(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [17]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #8 @T(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @T(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " public Point(int myInt, char myChar);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Record() [14]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 iload_1 [myInt]\n" +
+ " 6 putfield Point.myInt : int [17]\n" +
+ " 9 aload_0 [this]\n" +
+ " 10 iload_2 [myChar]\n" +
+ " 11 putfield Point.myChar : char [19]\n" +
+ " 14 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 15] local: this index: 0 type: Point\n" +
+ " [pc: 0, pc: 15] local: myInt index: 1 type: int\n" +
+ " [pc: 0, pc: 15] local: myChar index: 2 type: char\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @T(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_017() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCP int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.PARAMETER})\n"+
+ "@interface RCP {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " public Point(int myInt, char myChar);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Record() [14]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 iload_1 [myInt]\n" +
+ " 6 putfield Point.myInt : int [17]\n" +
+ " 9 aload_0 [this]\n" +
+ " 10 iload_2 [myChar]\n" +
+ " 11 putfield Point.myChar : char [19]\n" +
+ " 14 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 15] local: this index: 0 type: Point\n" +
+ " [pc: 0, pc: 15] local: myInt index: 1 type: int\n" +
+ " [pc: 0, pc: 15] local: myChar index: 2 type: char\n" +
+ " RuntimeInvisibleParameterAnnotations: \n" +
+ " Number of annotations for parameter 0: 1\n" +
+ " #12 @RCP(\n" +
+ " )\n" +
+ " Number of annotations for parameter 1: 0\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #12 @RCP(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_018() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@RCP int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.PARAMETER})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface RCP {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " public Point(int myInt, char myChar);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Record() [14]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 iload_1 [myInt]\n" +
+ " 6 putfield Point.myInt : int [17]\n" +
+ " 9 aload_0 [this]\n" +
+ " 10 iload_2 [myChar]\n" +
+ " 11 putfield Point.myChar : char [19]\n" +
+ " 14 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 15] local: this index: 0 type: Point\n" +
+ " [pc: 0, pc: 15] local: myInt index: 1 type: int\n" +
+ " [pc: 0, pc: 15] local: myChar index: 2 type: char\n" +
+ " RuntimeVisibleParameterAnnotations: \n" +
+ " Number of annotations for parameter 0: 1\n" +
+ " #12 @RCP(\n" +
+ " )\n" +
+ " Number of annotations for parameter 1: 0\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #12 @RCP(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_019() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@Annot int myInt, char myChar) { \n"+
+ "} \n"+
+ "@interface Annot {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " // Field descriptor #6 I\n" +
+ " private final int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @Annot(\n" +
+ " )\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @Annot(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " public Point(int myInt, char myChar);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Record() [16]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 iload_1 [myInt]\n" +
+ " 6 putfield Point.myInt : int [19]\n" +
+ " 9 aload_0 [this]\n" +
+ " 10 iload_2 [myChar]\n" +
+ " 11 putfield Point.myChar : char [21]\n" +
+ " 14 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 15] local: this index: 0 type: Point\n" +
+ " [pc: 0, pc: 15] local: myInt index: 1 type: int\n" +
+ " [pc: 0, pc: 15] local: myChar index: 2 type: char\n" +
+ " RuntimeInvisibleParameterAnnotations: \n" +
+ " Number of annotations for parameter 0: 1\n" +
+ " #8 @Annot(\n" +
+ " )\n" +
+ " Number of annotations for parameter 1: 0\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @Annot(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " // Method descriptor #27 ()I\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " public int myInt();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 getfield Point.myInt : int [19]\n" +
+ " 4 ireturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 11]\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @Annot(\n" +
+ " )\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeInvisibleAnnotations: \n" +
+ " #8 @Annot(\n" +
+ " )\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #8 @Annot(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562439_020() throws IOException, ClassFormatException {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n"+
+ "import java.lang.annotation.Retention;\n"+
+ "import java.lang.annotation.RetentionPolicy;\n"+
+ "import java.lang.annotation.Target;\n"+
+ " \n"+
+ "public class X { \n"+
+ " public static void main(String[] args){\n"+
+ " Point p = new Point(100, 'a');\n"+
+ " System.out.println(p.myInt());\n"+
+ " } \n"+
+ "}\n"+
+ "\n"+
+ "record Point(@Annot int myInt, char myChar) { \n"+
+ "} \n"+
+ "@Target({ ElementType.RECORD_COMPONENT, ElementType.PARAMETER})\n"+
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface Annot {}\n"
+ },
+ "100");
+ String expectedOutput =
+ " public Point(int myInt, char myChar);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Record() [14]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 iload_1 [myInt]\n" +
+ " 6 putfield Point.myInt : int [17]\n" +
+ " 9 aload_0 [this]\n" +
+ " 10 iload_2 [myChar]\n" +
+ " 11 putfield Point.myChar : char [19]\n" +
+ " 14 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 13]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 15] local: this index: 0 type: Point\n" +
+ " [pc: 0, pc: 15] local: myInt index: 1 type: int\n" +
+ " [pc: 0, pc: 15] local: myChar index: 2 type: char\n" +
+ " RuntimeVisibleParameterAnnotations: \n" +
+ " Number of annotations for parameter 0: 1\n" +
+ " #12 @Annot(\n" +
+ " )\n" +
+ " Number of annotations for parameter 1: 0\n" +
+ " \n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ "Record: #Record\n" +
+ "Components:\n" +
+ " \n" +
+ "// Component descriptor #6 I\n" +
+ "int myInt;\n" +
+ " RuntimeVisibleAnnotations: \n" +
+ " #12 @Annot(\n" +
+ " )\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM);
+}
+
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
index 858775a01..bdf7a3b87 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java
@@ -8861,4 +8861,68 @@ public class StackMapAttributeTest extends AbstractRegressionTest {
},
"1-1");
}
+ public void test562854() {
+ this.runConformTest(
+ new String[] {
+ "bug/Bug.java",
+ "package bug;\n" +
+ "public class Bug {\n" +
+ " public static void main(String[] args) {\n" +
+ " F(args.length > 1 ? pkg.Base.derived1() : pkg.Base.derived2());\n" + " }\n" + "\n" +
+ " static void F(pkg.Base base) {\n" +
+ " System.out.println(base.getClass().getCanonicalName());\n" +
+ " }\n" +
+ "}",
+ "pkg/Base.java",
+ "package pkg;\n" +
+ "public abstract class Base {\n" +
+ " public static Derived1 derived1() {\n" +
+ " return new Derived1();\n" +
+ " }\n" +
+ "\n" +
+ " public static Derived2 derived2() {\n" +
+ " return new Derived2();\n" +
+ " }\n" +
+ "}",
+ "pkg/Derived1.java",
+ "package pkg;\n" +
+ "class Derived1 extends Base {}",
+ "pkg/Derived2.java",
+ "package pkg;\n" +
+ "class Derived2 extends Derived1 {}",
+ },
+ "pkg.Derived2");
+ }
+ public void test562854_2() {
+ this.runConformTest(
+ new String[] {
+ "bug/Bug.java",
+ "package bug;\n" +
+ "public class Bug {\n" +
+ " public static void main(String[] args) {\n" +
+ " F(args.length > 1 ? pkg.Base.derived1() : pkg.Base.derived2());\n" + " }\n" + "\n" +
+ " static void F(pkg.Base base) {\n" +
+ " System.out.println(base.getClass().getCanonicalName());\n" +
+ " }\n" +
+ "}",
+ "pkg/Base.java",
+ "package pkg;\n" +
+ "public abstract class Base {\n" +
+ " public static Derived1 derived1() {\n" +
+ " return new Derived1();\n" +
+ " }\n" +
+ "\n" +
+ " public static Derived2 derived2() {\n" +
+ " return new Derived2();\n" +
+ " }\n" +
+ "}",
+ "pkg/Derived1.java",
+ "package pkg;\n" +
+ "public class Derived1 extends Base {}",
+ "pkg/Derived2.java",
+ "package pkg;\n" +
+ "public class Derived2 extends Derived1 {}",
+ },
+ "pkg.Derived2");
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
deleted file mode 100644
index 2e14732c1..000000000
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
+++ /dev/null
@@ -1,2985 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2018, 2019 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.core.tests.compiler.regression;
-
-import java.util.Map;
-
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-
-import junit.framework.Test;
-
-public class SwitchExpressionTest extends AbstractRegressionTest {
-
- static {
-// TESTS_NUMBERS = new int [] { 40 };
-// TESTS_NAMES = new String[] { "testBug548476" };
- }
-
- public static Class<?> testClass() {
- return SwitchExpressionTest.class;
- }
- public static Test suite() {
- return buildMinimalComplianceTestSuite(testClass(), F_12);
- }
- public SwitchExpressionTest(String testName){
- super(testName);
- }
-
- // Enables the tests to run individually
- @Override
- protected Map<String, String> getCompilerOptions() {
- Map<String, String> defaultOptions = super.getCompilerOptions();
- defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_12); // FIXME
- defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_12);
- defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_12);
- defaultOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- defaultOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- return defaultOptions;
- }
-
- @Override
- protected void runConformTest(String[] testFiles, Map<String, String> customOptions) {
- super.runConformTest(testFiles, "", null, true, new String[] {"--enable-preview"}, customOptions, null);
- }
-
- @Override
- protected void runConformTest(String[] testFiles, String expectedOutput, Map<String, String> customOptions) {
- super.runConformTest(testFiles, expectedOutput, null, true, new String[] {"--enable-preview"}, customOptions, null);
- }
- public void testSimpleExpressions() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " static int twice(int i) {\n" +
- " int tw = switch (i) {\n" +
- " case 0 -> i * 0;\n" +
- " case 1 -> 2;\n" +
- " default -> 3;\n" +
- " };\n" +
- " return tw;\n" +
- " }\n" +
- " public static void main(String... args) {\n" +
- " System.out.print(twice(3));\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 0)\n" +
- " public class X {\n" +
- " ^\n" +
- "Preview features enabled at an invalid source release level "+CompilerOptions.VERSION_12+", preview can be enabled only at source level "+AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL+"\n" +
- "----------\n");
- }
- public void testSwitchExpression_531714_002() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n"+
- " static int twice(int i) throws Exception {\n"+
- " int tw = switch (i) {\n"+
- " case 0 -> 0;\n"+
- " case 1 -> { \n"+
- " System.out.println(\"do_not_print\");\n"+
- " break 1;\n"+
- " } \n"+
- " case 3 -> throw new Exception();\n"+
- " default -> throw new Exception();\n"+
- " };\n"+
- " return tw;\n"+
- " }\n"+
- " public static void main(String[] args) {\n"+
- " try {\n"+
- " try {\n"+
- " System.out.print(twice(3));\n"+
- " } catch (Exception e) {\n"+
- " System.out.print(\"Got Exception - expected\");\n"+
- " }\n"+
- " } catch (Exception e) {\n"+
- " System.out.print(\"Got Exception\");\n"+
- " }\n"+
- " }\n"+
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 0)\n" +
- " public class X {\n" +
- " ^\n" +
- "Preview features enabled at an invalid source release level "+CompilerOptions.VERSION_12+", preview can be enabled only at source level "+AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL+"\n" +
- "----------\n");
- }
- public void _testBug531714_error_003() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " twice(1);\n" +
- " }\n" +
- " public static int twice(int i) {\n" +
- " int tw = switch (i) {\n" +
- " };\n" +
- " return tw;\n" +
- " }\n" +
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " int tw = switch (i) {\n" +
- " };\n" +
- " ^^^^^^^^^^^^^^^^\n" +
- "A switch expression should have a non-empty switch block\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " int tw = switch (i) {\n" +
- " ^\n" +
- "A switch expression should have a default case\n" +
- "----------\n");
- }
- public void _testBug531714_error_004() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " twice(1);\n" +
- " }\n" +
- " public static int twice(int i) {\n" +
- " int tw = switch (i) {\n" +
- " case 0 -> 0;\n" +
- " case 1 -> { \n" +
- " System.out.println(\"heel\");\n" +
- " break 1;\n" +
- " } \n" +
- " case \"hello\" -> throw new java.io.IOException(\"hello\");\n" +
- " default -> throw new java.io.IOException(\"world\");\n" +
- " };\n" +
- " return tw;\n" +
- " }\n" +
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " break 1;\n" +
- " ^\n" +
- "Syntax error on token \"1\", delete this token\n" +
- "----------\n");
- }
- public void _testBug531714_error_005() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " twice(1);\n" +
- " }\n" +
- " public static int twice(int i) {\n" +
- " int tw = switch (i) {\n" +
- " case 0 -> 0;\n" +
- " case 1 -> { \n" +
- " System.out.println(\"heel\");\n" +
- " break 1;\n" +
- " } \n" +
- " case 2 -> 2;\n" +
- " };\n" +
- " return tw;\n" +
- " }\n" +
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " break 1;\n" +
- " ^\n" +
- "Syntax error on token \"1\", delete this token\n" +
- "----------\n");
- }
- /**
- * Add a test case for enum
- * If the type of the selector expression is an enum type,
- * then the set of all the case constants associated with the switch block
- * must contain all the enum constants of that enum type
- * Add a missing enum test case
- */
- public void __testBug531714_error_006() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " int x, y;\n" +
- " I i = () -> {\n" +
- " int z = 10;\n" +
- " };\n" +
- " i++;\n" +
- " }\n" +
- " public static int twice(int i) {\n" +
- " int tw = switch (i) {\n" +
- " case 0 -> 0;\n" +
- " case 1 -> { \n" +
- " System.out.println(\"heel\");\n" +
- " break 1;\n" +
- " } \n" +
- " // case 2 -> 2;\n" +
- " case \"hello\" -> throw new IOException(\"hello\");\n" +
- " };\n" +
- " return tw;\n" +
- " }\n" +
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " int tw = switch (i) {\n" +
- " ^^^^^\n" +
- " The switch expression should have a default case\n" +
- "----------\n");
- }
- /*
- * should compile - test for adding additional nesting in variables
- * dev note: ref consumeToken().case Switch
- */
- public void _testBug531714_error_007() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n"+
- " static int foo(int i) {\n"+
- " int tw = \n"+
- " switch (i) {\n"+
- " case 1 -> \n"+
- " {\n"+
- " int z = 100;\n"+
- " break z;\n"+
- " }\n"+
- " default -> {\n"+
- " break 12;\n"+
- " }\n"+
- " };\n"+
- " return tw;\n"+
- " }\n"+
- " public static void main(String[] args) {\n"+
- " System.out.print(foo(1));\n"+
- " }\n"+
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " default -> {\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 11)\n" +
- " break 12;\n" +
- " ^^\n" +
- "Syntax error on token \"12\", delete this token\n" +
- "----------\n");
- }
- public void _testBug531714_008() {
- Map<String, String> disablePreviewOptions = getCompilerOptions();
- disablePreviewOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " static int twice(int i) {\n" +
- " int tw = switch (i) {\n" +
- " case 0 -> i * 0;\n" +
- " case 1 -> 2;\n" +
- " default -> 3;\n" +
- " };\n" +
- " return tw;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " System.out.print(twice(3));\n" +
- " }\n" +
- "}\n",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 3)\n" +
- " int tw = switch (i) {\n" +
- " case 0 -> i * 0;\n" +
- " case 1 -> 2;\n" +
- " default -> 3;\n" +
- " };\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Switch Expressions is a preview feature and disabled by default. Use --enable-preview to enable\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case 0 -> i * 0;\n" +
- " ^^^^^^\n" +
- "Case Labels with '->' is a preview feature and disabled by default. Use --enable-preview to enable\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 5)\n" +
- " case 1 -> 2;\n" +
- " ^^^^^^\n" +
- "Case Labels with '->' is a preview feature and disabled by default. Use --enable-preview to enable\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 6)\n" +
- " default -> 3;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
-
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- disablePreviewOptions);
- }
- public void _testBug543667_001() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- "\n" +
- " public static void bar(int i) {\n" +
- " switch (i) {\n" +
- " case 1 -> System.out.println(\"hello\");\n" +
- " default -> System.out.println(\"DEFAULT\");\n" +
- " }\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " bar(1);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " default -> System.out.println(\"DEFAULT\");\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug531714_009() {
- Map<String, String> disablePreviewOptions = getCompilerOptions();
- disablePreviewOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " static int twice(int i) {\n" +
- " switch (i) {\n" +
- " case 0 -> i * 0;\n" +
- " case 1 -> 2;\n" +
- " default -> 3;\n" +
- " }\n" +
- " return 0;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " System.out.print(twice(3));\n" +
- " }\n" +
- "}\n",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 0 -> i * 0;\n" +
- " ^^^^^^\n" +
- "Case Labels with \'->\' is a preview feature and disabled by default. Use --enable-preview to enable\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " case 1 -> 2;\n" +
- " ^^^^^^\n" +
- "Case Labels with \'->\' is a preview feature and disabled by default. Use --enable-preview to enable\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 6)\n" +
- " default -> 3;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- disablePreviewOptions);
- }
- public void _testBug531714_010() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.ERROR);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " static int twice(int i) {\n" +
- " switch (i) {\n" +
- " default -> 3;\n" +
- " }\n" +
- " return 0;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " System.out.print(twice(3));\n" +
- " }\n" +
- "}\n",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " default -> 3;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " default -> 3;\n" +
- " ^\n" +
- "Invalid expression as statement\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- public void _testBug531714_011() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " static int twice(int i) {\n" +
- " switch (i) {\n" +
- " default -> 3;\n" +
- " }\n" +
- " return 0;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " System.out.print(twice(3));\n" +
- " }\n" +
- "}\n",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> 3;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default -> 3;\n" +
- " ^\n" +
- "Invalid expression as statement\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- getCompilerOptions());
- }
- public void testBug531714_012() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
- String release = options.get(CompilerOptions.OPTION_Release);
- options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_11);
- try {
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " static int twice(int i) {\n" +
- " switch (i) {\n" +
- " default -> 3;\n" +
- " }\n" +
- " return 0;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " System.out.print(twice(3));\n" +
- " }\n" +
- "}\n",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 0)\n" +
- " public class X {\n" +
- " ^\n" +
- "Preview features enabled at an invalid source release level "+CompilerOptions.VERSION_11+", preview can be enabled only at source level "+AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL+"\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- } finally {
- options.put(CompilerOptions.OPTION_Source, release);
- }
- }
- public void _testBug531714_013() {
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(int i) {\n" +
- " int v;\n" +
- " int t = switch (i) {\n" +
- " case 0 : {\n" +
- " break 0;\n" +
- " }\n" +
- " default :v = 2;\n" +
- " };\n" +
- " return t;\n" +
- " }\n" +
- " \n" +
- " public boolean bar() {\n" +
- " return true;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " System.out.println(foo(3));\n" +
- " }\n" +
- "}\n",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " break 0;\n" +
- " ^\n" +
- "Syntax error on token \"0\", delete this token\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- getCompilerOptions());
- }
- public void _testBug531714_014() {
- // switch expression is not a Primary
- Runner runner = new Runner();
- runner.customOptions = getCompilerOptions();
- runner.testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " void test(int i) {\n" +
- " System.out.println(switch (i) {\n" +
- " case 1 -> \"one\";\n" +
- " default -> null;\n" +
- " }.toLowerCase());\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " new X().test(1);\n" +
- " }\n" +
- "}\n"
- };
- runner.expectedCompilerLog =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> null;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " }.toLowerCase());\n" +
- " ^\n" +
- "Syntax error on token \".\", , expected\n" +
- "----------\n";
- runner.runNegativeTest();
- }
- public void _testBug543673_001() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(Day day) {\n" +
- "\n" +
- " var len= switch (day) {\n" +
- " case SUNDAY-> 6;\n" +
- " default -> 10;\n" +
- " };\n" +
- "\n" +
- " return len;\n" +
- " }\n" +
- "\n" +
- " public static void main(String[] args) {\n" +
- " System.out.println(foo(Day.SUNDAY));\n" +
- " }\n" +
- "}\n" +
- "enum Day {\n" +
- " MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " default -> 10;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- /*
- * A simple multi constant case statement, compiled and run as expected
- */
- public void _testBug543240_1() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- "public static void bar(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY: \n" +
- " System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " case MONDAY : System.out.println(Day.MONDAY);\n" +
- " break;\n" +
- " }\n" +
- " }" +
- " public static void main(String[] args) {\n" +
- " bar(Day.SATURDAY);\n" +
- " }\n" +
- "}\n" +
- "enum Day { SATURDAY, SUNDAY, MONDAY;}",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * A simple multi constant case statement, compiler reports missing enum constants
- */
- public void _testBug543240_1a() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- "public static void bar(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY: \n" +
- " System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " case MONDAY : System.out.println(Day.MONDAY);\n" +
- " break;\n" +
- " }\n" +
- " }" +
- "}\n" +
- "enum Day { SATURDAY, SUNDAY, MONDAY, TUESDAY;}",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. WARNING in X.java (at line 5)\n" +
- " switch (day) {\n" +
- " ^^^\n" +
- "The enum constant TUESDAY needs a corresponding case label in this enum switch on Day\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- /*
- * A simple multi constant case statement with duplicate enums
- */
- public void _testBug543240_2() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- "public static void bar(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY: \n" +
- " System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " case SUNDAY : System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " }\n" +
- " }" +
- " public static void main(String[] args) {\n" +
- " bar(Day.SATURDAY);\n" +
- " }\n" +
- "}\n" +
- "enum Day { SATURDAY, SUNDAY, MONDAY;}",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 7)\n" +
- " case SUNDAY : System.out.println(Day.SUNDAY);\n" +
- " ^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * A simple multi constant case statement with duplicate enums
- */
- public void _testBug543240_2a() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- "public static void bar(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY: \n" +
- " System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " case SUNDAY, SATURDAY : \n" +
- " System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " }\n" +
- " }" +
- "}\n" +
- "enum Day { SATURDAY, SUNDAY, MONDAY;}",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. WARNING in X.java (at line 3)\n" +
- " switch (day) {\n" +
- " ^^^\n" +
- "The enum constant MONDAY needs a corresponding case label in this enum switch on Day\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 7)\n" +
- " case SUNDAY, SATURDAY : \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "5. ERROR in X.java (at line 7)\n" +
- " case SUNDAY, SATURDAY : \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "6. ERROR in X.java (at line 7)\n" +
- " case SUNDAY, SATURDAY : \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- *
- */
- public void _testBug543240_3() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- "public static void bar(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY: \n" +
- " System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " case TUESDAY : System.out.println(Day.SUNDAY);\n" +
- " break;\n" +
- " }\n" +
- " }" +
- " public static void main(String[] args) {\n" +
- " bar(Day.SATURDAY);\n" +
- " }\n" +
- "}\n" +
- "enum Day { SATURDAY, SUNDAY, MONDAY, TUESDAY;}",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. WARNING in X.java (at line 3)\n" +
- " switch (day) {\n" +
- " ^^^\n" +
- "The enum constant MONDAY needs a corresponding case label in this enum switch on Day\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- new String[] {"--enable-preview"},
- options);
- }
- public void _testBug543240_4() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- "public static void bar(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY: \n" +
- " System.out.println(day);\n" +
- " break;\n" +
- " case MONDAY : System.out.println(0);\n" +
- " break;\n" +
- " }\n" +
- " }" +
- " public static void main(String[] args) {\n" +
- " bar(Day.SATURDAY);\n" +
- " bar(Day.MONDAY);\n" +
- " bar(Day.SUNDAY);\n" +
- " }\n" +
- "}\n" +
- "enum Day { SATURDAY, SUNDAY, MONDAY;}",
- };
-
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY: \n" +
- " ^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Simple switch case with string literals
- */
- public void _testBug543240_5() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " bar(\"a\");\n" +
- " bar(\"b\");\n" +
- " bar(\"c\");\n" +
- " bar(\"d\");\n" +
- " }\n" +
- " public static void bar(String s) {\n" +
- " switch(s) {\n" +
- " case \"a\":\n" +
- " case \"b\":\n" +
- " System.out.println(\"A/B\");\n" +
- " break;\n" +
- " case \"c\":\n" +
- " System.out.println(\"C\");\n" +
- " break;\n" +
- " default:\n" +
- " System.out.println(\"NA\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "A/B\n" +
- "A/B\n" +
- "C\n" +
- "NA";
- this.runConformTest(
- testFiles,
- expectedProblemLog,
- options,
- new String[] {"--enable-preview"});
- }
- public void _testBug543240_6() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " bar(\"a\");\n" +
- " bar(\"b\");\n" +
- " bar(\"c\");\n" +
- " bar(\"d\");\n" +
- " }\n" +
- " public static void bar(String s) {\n" +
- " switch(s) {\n" +
- " case \"a\", \"b\":\n" +
- " System.out.println(\"A/B\");\n" +
- " break;\n" +
- " case \"c\":\n" +
- " System.out.println(\"C\");\n" +
- " break;\n" +
- " default:\n" +
- " System.out.println(\"NA\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " case \"a\", \"b\":\n" +
- " ^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch with multi constant case statements with string literals
- * two string literals with same hashcode
- */
- public void _testBug543240_7() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " bar(\"FB\");\n" +
- " bar(\"Ea\");\n" +
- " bar(\"c\");\n" +
- " bar(\"D\");\n" +
- " }\n" +
- " public static void bar(String s) {\n" +
- " switch(s) {\n" +
- " case \"FB\", \"c\":\n" +
- " System.out.println(\"A\");\n" +
- " break;\n" +
- " case \"Ea\":\n" +
- " System.out.println(\"B\");\n" +
- " break;\n" +
- " default:\n" +
- " System.out.println(\"NA\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " case \"FB\", \"c\":\n" +
- " ^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch with multi constant case statements with integer constants
- */
- public void _testBug543240_8() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " bar(1);\n" +
- " bar(2);\n" +
- " bar(3);\n" +
- " bar(4);\n" +
- " bar(5);\n" +
- " }\n" +
- " public static void bar(int i) {\n" +
- " switch (i) {\n" +
- " case 1, 3: \n" +
- " System.out.println(\"Odd\");\n" +
- " break;\n" +
- " case 2, 4: \n" +
- " System.out.println(\"Even\");\n" +
- " break;\n" +
- " default:\n" +
- " System.out.println(\"Out of range\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 11)\n" +
- " case 1, 3: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 14)\n" +
- " case 2, 4: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch multi-constant with mixed constant types, reported
- */
- public void _testBug543240_9() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public static void bar(int i) {\n" +
- " switch (i) {\n" +
- " case 1, 3: \n" +
- " System.out.println(\"Odd\");\n" +
- " break;\n" +
- " case \"2\": \n" +
- " System.out.println(\"Even\");\n" +
- " break;\n" +
- " default:\n" +
- " System.out.println(\"Out of range\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case 1, 3: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 9)\n" +
- " case \"2\": \n" +
- " ^^^\n" +
- "Type mismatch: cannot convert from String to int\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch multi-constant without break statement, reported
- */
- public void _testBug543240_10() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- options.put(CompilerOptions.OPTION_ReportFallthroughCase, CompilerOptions.WARNING);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public static void bar(int i) {\n" +
- " switch (i) {\n" +
- " case 1, 3: \n" +
- " System.out.println(\"Odd\");\n" +
- " case 2, 4: \n" +
- " System.out.println(\"Even\");\n" +
- " break;\n" +
- " default:\n" +
- " System.out.println(\"Out of range\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case 1, 3: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 8)\n" +
- " case 2, 4: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch multi-constant without break statement, reported
- */
- public void _testBug543240_11() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- options.put(CompilerOptions.OPTION_ReportMissingDefaultCase, CompilerOptions.WARNING);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public static void bar(int i) {\n" +
- " switch (i) {\n" +
- " case 1, 3: \n" +
- " System.out.println(\"Odd\");\n" +
- " case 2, 4: \n" +
- " System.out.println(\"Even\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. WARNING in X.java (at line 5)\n" +
- " switch (i) {\n" +
- " ^\n" +
- "The switch statement should have a default case\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " case 1, 3: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 8)\n" +
- " case 2, 4: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch multi-constant with duplicate int constants
- */
- public void _testBug543240_12() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public static void bar(int i) {\n" +
- " switch (i) {\n" +
- " case 1, 3: \n" +
- " System.out.println(\"Odd\");\n" +
- " case 3, 4: \n" +
- " System.out.println(\"Odd\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case 1, 3: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " case 1, 3: \n" +
- " ^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 8)\n" +
- " case 3, 4: \n" +
- " ^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 8)\n" +
- " case 3, 4: \n" +
- " ^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch multi-constant with duplicate String literals
- */
- public void _testBug543240_13() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public static void bar(String s) {\n" +
- " switch (s) {\n" +
- " case \"a\", \"b\": \n" +
- " System.out.println(\"Odd\");\n" +
- " case \"b\", \"c\": \n" +
- " System.out.println(\"Odd\");\n" +
- " }\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case \"a\", \"b\": \n" +
- " ^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " case \"a\", \"b\": \n" +
- " ^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 8)\n" +
- " case \"b\", \"c\": \n" +
- " ^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 8)\n" +
- " case \"b\", \"c\": \n" +
- " ^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- /*
- * Switch multi-constant with illegal qualified enum constant
- */
- public void _testBug543240_14() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public static void bar(Num s) {\n" +
- " switch (s) {\n" +
- " case ONE, Num.TWO: \n" +
- " System.out.println(\"Odd\");\n" +
- " }\n" +
- " }\n" +
- "}\n" +
- "enum Num { ONE, TWO}\n",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case ONE, Num.TWO: \n" +
- " ^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 6)\n" +
- " case ONE, Num.TWO: \n" +
- " ^^^^^^^\n" +
- "The qualified case label Num.TWO must be replaced with the unqualified enum constant TWO\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- public void _testBug543240_15() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public void bar(int s) {\n" +
- " int j = switch (s) {\n" +
- " case 1, 2, 3 -> (s+1);\n" +
- " default -> j;\n" +
- " };\n" +
- " }\n" +
- "}\n",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1, 2, 3 -> (s+1);\n" +
- " ^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default -> j;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- public void _testBug543240_16() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " }\n" +
- " public void bar(int s) {\n" +
- " int j = 0;" +
- " j = switch (s) {\n" +
- " case 1, 2, 3 -> (s+1);\n" +
- " default -> j;\n" +
- " };\n" +
- " }\n" +
- "}\n",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case 1, 2, 3 -> (s+1);\n" +
- " ^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 7)\n" +
- " default -> j;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- public void _testBug543795_01() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "import java.io.IOException;\n" +
- "\n" +
- "public class X {\n" +
- " public static int foo(int i) throws IOException {\n" +
- " int t = switch (i) {\n" +
- " case 0 : {\n" +
- " break 0;\n" +
- " }\n" +
- " case 2 : {\n" +
- " break;\n" +
- " }\n" +
- " default : break 10;\n" +
- " };\n" +
- " return t;\n" +
- " }\n" +
- " \n" +
- " public boolean bar() {\n" +
- " return true;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " System.out.println(foo(3));\n" +
- " } catch (IOException e) {\n" +
- " // TODO Auto-generated catch block\n" +
- " e.printStackTrace();\n" +
- " }\n" +
- " }\n" +
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " break 0;\n" +
- " ^\n" +
- "Syntax error on token \"0\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 12)\n" +
- " default : break 10;\n" +
- " ^^\n" +
- "Syntax error on token \"10\", delete this token\n" +
- "----------\n");
- }
- public void _testBug543691() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " public static void bar(int i) {\n" +
- " i = switch (i+0) {\n" +
- " default: System.out.println(0);\n" +
- " }; " +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " i = switch (i+0) {\n" +
- " default: System.out.println(0);\n" +
- " }; }\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "A switch expression should have at least one result expression\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- options);
- }
- public void _testBug543799_1() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " void test(int i) {\n" +
- " need(switch (i) {\n" +
- " case 1 -> \"\";\n" +
- " default -> i == 3 ? null : \"\";\n" +
- " }); \n" +
- " }\n" +
- " void need(String s) {\n" +
- " System.out.println(s.toLowerCase());\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " new X().need(\"Hello World\");\n" +
- " }\n" +
- "}\n"
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> i == 3 ? null : \"\";\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- runNegativeTest(testFiles, expectedProblemLog, null, true, options);
- }
- public void _testBug543799_2() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " void test(int i) {\n" +
- " need(switch (i) {\n" +
- " case 1: break \"\";\n" +
- " default: break i == 3 ? null : \"\";\n" +
- " }); \n" +
- " }\n" +
- " void need(String s) {\n" +
- " System.out.println(s.toLowerCase());\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " new X().need(\"Hello World\");\n" +
- " }\n" +
- "}\n"
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1: break \"\";\n" +
- " ^^\n" +
- "Syntax error on token \"\"\"\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default: break i == 3 ? null : \"\";\n" +
- " ^^^^^\n" +
- "Syntax error on token \"break\", yield expected\n" +
- "----------\n";
- runNegativeTest(testFiles, expectedProblemLog, null, true, options);
- }
- public void _testBug543799_3() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "interface I0 { void i(); }\n" +
- "interface I1 extends I0 {}\n" +
- "interface I2 extends I0 {}\n" +
- "public class X {\n" +
- " I1 n1() { return null; }\n" +
- " <I extends I2> I n2() { return null; }\n" +
- " <M> M m(M m) { return m; }\n" +
- " void test(int i, boolean b) {\n" +
- " m(switch (i) {\n" +
- " case 1 -> n1();\n" +
- " default -> b ? n1() : n2();\n" +
- " }).i(); \n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " new X().test(1, true);\n" +
- " } catch (NullPointerException e) {\n" +
- " System.out.println(\"NPE as expected\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 11)\n" +
- " default -> b ? n1() : n2();\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- runNegativeTest(testFiles, expectedProblemLog, null, true, options);
- }
- public void _testBug543799_4() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "import java.util.function.Supplier;\n" +
- "interface I0 { void i(); }\n" +
- "interface I1 extends I0 {}\n" +
- "interface I2 extends I0 {}\n" +
- "public class X {\n" +
- " I1 n1() { return null; }\n" +
- " <I extends I2> I n2() { return null; }\n" +
- " <M> M m(Supplier<M> m) { return m.get(); }\n" +
- " void test(int i, boolean b) {\n" +
- " m(switch (i) {\n" +
- " case 1 -> this::n1;\n" +
- " default -> this::n2;\n" +
- " }).i(); \n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " new X().test(1, true);\n" +
- " } catch (NullPointerException e) {\n" +
- " System.out.println(\"NPE as expected\");\n" +
- " }\n" +
- " }\n" +
- "}\n"
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 12)\n" +
- " default -> this::n2;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- runNegativeTest(testFiles, expectedProblemLog, null, true, options);
- }
- public void _testBug543799_5() {
- // require resolving/inferring of poly-switch-expression during ASTNode.resolvePolyExpressionArguments()
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " void test(int i) {\n" +
- " need(switch (i) {\n" +
- " case 1 -> 1.0f;\n" +
- " default -> i == 3 ? 3 : 5.0d;\n" +
- " }); \n" +
- " }\n" +
- " <N extends Number> void need(N s) {\n" +
- " System.out.println(s.toString());\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " new X().need(3);\n" +
- " }\n" +
- "}\n"
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> i == 3 ? 3 : 5.0d;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- runNegativeTest(testFiles, expectedProblemLog, null, true, options);
- }
- public void _testSwitchStatementWithBreakExpression() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " static int twice(int i) throws Exception {\n" +
- " switch (i) {\n" +
- " case 0 -> System.out.println(\"hellow\");\n" +
- " case 1 -> foo();\n" +
- " default -> throw new Exception();\n" +
- " };\n" +
- " return 0;\n" +
- " }\n" +
- "\n" +
- " static int foo() {\n" +
- " System.out.println(\"inside foo\");\n" +
- " return 1;\n" +
- " }\n" +
- "\n" +
- " public static void main(String[] args) {\n" +
- " try {\n" +
- " System.out.print(twice(1));\n" +
- " } catch (Exception e) {\n" +
- " System.out.print(\"Got Exception\");\n" +
- " }\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " default -> throw new Exception();\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testSwitchStatementWithEnumValues() {
- runConformTest(
- new String[] {
- "X.java",
- "enum SomeDays {\n" +
- " Mon, Wed, Fri\n" +
- "}\n" +
- "\n" +
- "public class X {\n" +
- " int testEnum(boolean b) {\n" +
- " SomeDays day = b ? SomeDays.Mon : null;\n" +
- " return switch(day) {\n" +
- " case Mon -> 1;\n" +
- " case Wed -> 2;\n" +
- " case Fri -> 3;\n" +
- " };\n" +
- " }\n" +
- "\n" +
- " public static void main(String[] args) {\n" +
- " System.out.println(new X().testEnum(true));\n" +
- " }\n" +
- "}\n" +
- ""
- },
- "1",
- null,
- new String[] {"--enable-preview"});
- }
- public void _testBug543967_01() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " static int foo(int i) {\n" +
- " switch (i) {\n" +
- " default -> 3; // should flag an error\n" +
- " \n" +
- " };\n" +
- " return 0;\n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " foo(1);\n" +
- " }\n" +
- "}\n",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " default -> 3; // should flag an error\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " default -> 3; // should flag an error\n" +
- " ^\n" +
- "Invalid expression as statement\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- public void _testBug544204() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(int i) {\n" +
- " int j = switch (i) {\n" +
- " case 1 -> i;\n" +
- " default -> i;\n" +
- " };\n" +
- " System.out.println(j);\n" +
- " }\n" +
- " \n" +
- " public static void main(String[] args) {\n" +
- " new X().foo(1);\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> i;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544204_2() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(int i) {\n" +
- " long j = switch (i) {\n" +
- " case 1 -> 10L;\n" +
- " default -> 20L;\n" +
- " };\n" +
- " System.out.println(j);\n" +
- " }\n" +
- " \n" +
- " public static void main(String[] args) {\n" +
- " new X().foo(1);\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> 20L;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544223() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public int foo(String s) throws Exception {\n" +
- " int i = switch (s) {\n" +
- " case \"hello\" -> 1;\n" +
- " default -> throw new Exception();\n" +
- " };\n" +
- " return i;\n" +
- " }\n" +
- "\n" +
- " public static void main(String[] argv) {\n" +
- " try {\n" +
- " System.out.print(new X().foo(\"hello\"));\n" +
- " } catch (Exception e) {\n" +
- " //\n" +
- " }\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> throw new Exception();\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544258_01() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(Day day) {\n" +
- " var today = 1;\n" +
- " today = switch (day) {\n" +
- " case SATURDAY,SUNDAY :\n" +
- " today=1;\n" +
- " break today;\n" +
- " case MONDAY,TUESDAY,WEDNESDAY,THURSDAY :\n" +
- " today=2;\n" +
- " break today;\n" +
- " };\n" +
- " }\n" +
- " public static void main(String argv[]) {\n" +
- " new X().foo(Day.FRIDAY);\n" +
- " }\n" +
- "}\n" +
- "\n" +
- "enum Day {\n" +
- " SUNDAY,\n" +
- " MONDAY,\n" +
- " TUESDAY,\n" +
- " WEDNESDAY,\n" +
- " THURSDAY,\n" +
- " FRIDAY,\n" +
- " SATURDAY\n" +
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " today = switch (day) {\n" +
- " case SATURDAY,SUNDAY :\n" +
- " today=1;\n" +
- " break today;\n" +
- " case MONDAY,TUESDAY,WEDNESDAY,THURSDAY :\n" +
- " today=2;\n" +
- " break today;\n" +
- " };\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "A switch expression should have at least one result expression\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " today = switch (day) {\n" +
- " ^^^\n" +
- "A Switch expression should cover all possible values\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 5)\n" +
- " case SATURDAY,SUNDAY :\n" +
- " ^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 8)\n" +
- " case MONDAY,TUESDAY,WEDNESDAY,THURSDAY :\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544253() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(int i ) {\n" +
- " boolean b = switch (i) {\n" +
- " case 0 -> i == 1;\n" +
- " default -> true;\n" +
- " };\n" +
- " System.out.println( b ? \" true\" : \"false\");\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " new X().foo(0);\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> true;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544254() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(String s) {\n" +
- " try {\n" +
- " int i = switch (s) {\n" +
- " case \"hello\" -> 0;\n" +
- " default -> 2;\n" +
- " };\n" +
- " } finally {\n" +
- " System.out.println(s);\n" +
- " }\n" +
- " }\n" +
- " public static void main(String argv[]) {\n" +
- " new X().foo(\"hello\");\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " default -> 2;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544254_2() {
- Map<String, String> customOptions = getCompilerOptions();
- customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(String s) {\n" +
- " try {\n" +
- " int i = switch (s) {\n" +
- " case \"hello\" -> 0;\n" +
- " default -> 2;\n" +
- " };\n" +
- " } finally {\n" +
- " System.out.println(s);\n" +
- " }\n" +
- " }\n" +
- " public static void main(String argv[]) {\n" +
- " new X().foo(\"hello\");\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " default -> 2;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544254_3() {
- Map<String, String> customOptions = getCompilerOptions();
- customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public void foo(String s) {\n" +
- " try {\n" +
- " long l = switch (s) {\n" +
- " case \"hello\" -> 0;\n" +
- " default -> 2;\n" +
- " };\n" +
- " } finally {\n" +
- " System.out.println(s);\n" +
- " }\n" +
- " }\n" +
- " public static void main(String argv[]) {\n" +
- " new X().foo(\"hello\");\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " default -> 2;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544224_1() {
- Map<String, String> customOptions = getCompilerOptions();
- customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public int foo(int i) {\n" +
- " int j = (switch (i) {\n" +
- " case 1 -> 1;\n" +
- " default -> 2;\n" +
- " });\n" +
- " return j;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " new X().foo(1);\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> 2;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544298() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " enum MyEnum {\n" +
- " FIRST;\n" +
- " }\n" +
- "\n" +
- " public void foo(MyEnum myEnum) {\n" +
- " int i = switch (myEnum) {\n" +
- " case FIRST -> 1;\n" +
- " };\n" +
- " System.out.println( \"i:\" + i);\n" +
- " }\n" +
- "\n" +
- " public static void main(String argv[]) {\n" +
- " new X().foo(MyEnum.FIRST);\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- "----------\n");
- }
- public void _testBug544298_2() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " enum MyEnum {\n" +
- " FIRST;\n" +
- " }\n" +
- "\n" +
- " public void foo(MyEnum myEnum) {\n" +
- " int i = switch (myEnum) {\n" +
- " case FIRST -> 1;\n" +
- " default -> 0;\n" +
- " };\n" +
- " System.out.println( \"i:\" + i);\n" +
- " }\n" +
- "\n" +
- " public static void main(String argv[]) {\n" +
- " new X().foo(MyEnum.FIRST);\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 9)\n" +
- " default -> 0;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544428_01() {
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String[] testFiles = new String[] {
- "X.java",
- "public class X {\n" +
- " public int foo(int i) {\n" +
- " var v = switch(i) {\n" +
- " case 0 -> x;\n" +
- " default -> 1;\n" +
- " };\n" +
- " return v;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(new X().foo(0));\n" +
- " }\n" +
- "}",
- };
- String expectedProblemLog =
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 0 -> x;\n" +
- " ^\n" +
- "x cannot be resolved to a variable\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default -> 1;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n";
- this.runNegativeTest(
- testFiles,
- expectedProblemLog,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- public void _testBug544523_01() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " public int foo(int i) {\n" +
- " int v = switch(i) {\n" +
- " case 0 -> switch(i) {\n" +
- " case 0 -> 0;\n" +
- " default -> 1;\n" +
- " };\n" +
- " default -> 1;\n" +
- " };\n" +
- " return v;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(new X().foo(0));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " default -> 1;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 9)\n" +
- " default -> 1;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544560_01() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public int foo(int i) {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " int v = switch(switch(i) {\n" +
- " default -> 1;\n" +
- " }) {\n" +
- " default -> 1;\n" +
- " };\n" +
- " return v;\n" +
- " }\n" +
- "\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(new X().foo(0));\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " default -> 1;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 7)\n" +
- " default -> 1;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug544458() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(int i) {\n" +
- " boolean v = switch (i) {\n" +
- " case 1: i = 10; break true;\n" +
- " default: break false;\n" +
- " };\n" +
- " return v ? 0 : 1;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(X.foo(0));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1: i = 10; break true;\n" +
- " ^^^^\n" +
- "Syntax error on token \"true\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default: break false;\n" +
- " ^^^^^\n" +
- "Syntax error on token \"false\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544458_2() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(int i) {\n" +
- " boolean v = switch (i) {\n" +
- " case 1: i++; break true;\n" +
- " default: break false;\n" +
- " };\n" +
- " return v ? 0 : 1;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(X.foo(1));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1: i++; break true;\n" +
- " ^^^^\n" +
- "Syntax error on token \"true\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default: break false;\n" +
- " ^^^^^\n" +
- "Syntax error on token \"false\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544458_3() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(int i) {\n" +
- " boolean v = switch (i) {\n" +
- " case 1: i+= 10; break true;\n" +
- " default: break false;\n" +
- " };\n" +
- " return v ? 0 : 1;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(X.foo(1));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1: i+= 10; break true;\n" +
- " ^^^^\n" +
- "Syntax error on token \"true\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default: break false;\n" +
- " ^^^^^\n" +
- "Syntax error on token \"false\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544458_4() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(int i) {\n" +
- " boolean v = switch (i) {\n" +
- " case 1: switch(i) {case 4: break;}; break true;\n" +
- " default: break false;\n" +
- " };\n" +
- " return v ? 0 : 1;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(X.foo(1));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1: switch(i) {case 4: break;}; break true;\n" +
- " ^^^^\n" +
- "Syntax error on token \"true\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default: break false;\n" +
- " ^^^^^\n" +
- "Syntax error on token \"false\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544458_5() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public static int foo(int i) {\n" +
- " boolean v = switch (i) {\n" +
- " case 1: foo(5); break true;\n" +
- " default: break false;\n" +
- " };\n" +
- " return v ? 0 : 1;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(X.foo(1));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 1: foo(5); break true;\n" +
- " ^^^^\n" +
- "Syntax error on token \"true\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default: break false;\n" +
- " ^^^^^\n" +
- "Syntax error on token \"false\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544601_1() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public int foo(int i) {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " boolean v = switch (i) {\n" +
- " case 1:\n" +
- " switch (i) {\n" +
- " case 1 : i = 10;\n" +
- " break;\n" +
- " default :\n" +
- " i = 2;\n" +
- " break;\n" +
- " }\n" +
- " break true;\n" +
- " default: break false;\n" +
- " };\n" +
- " return v ? 0 : 1;\n" +
- " }\n" +
- "\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(new X().foo(0));\n" +
- " }\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 13)\n" +
- " break true;\n" +
- " ^^^^\n" +
- "Syntax error on token \"true\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 14)\n" +
- " default: break false;\n" +
- " ^^^^^\n" +
- "Syntax error on token \"false\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544556() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " public int foo(int i) {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " int v =\n" +
- " switch(switch(i) {\n" +
- " case 0 -> { break 2; }\n" +
- " default -> { break 3; }\n" +
- " }) {\n" +
- " case 0 -> { break 0; }\n" +
- " default -> { break 1; }\n" +
- " };\n" +
- " return v == 1 ? v : 0;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(new X().foo(0));\n" +
- " }\n" +
- "}"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 6)\n" +
- " case 0 -> { break 2; }\n" +
- " ^\n" +
- "Syntax error on token \"2\", delete this token\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 7)\n" +
- " default -> { break 3; }\n" +
- " ^\n" +
- "Syntax error on token \"3\", delete this token\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 9)\n" +
- " case 0 -> { break 0; }\n" +
- " ^\n" +
- "Syntax error on token \"0\", delete this token\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 10)\n" +
- " default -> { break 1; }\n" +
- " ^\n" +
- "Syntax error on token \"1\", delete this token\n" +
- "----------\n");
- }
- public void _testBug544702_01() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " public int foo(int i) {\n" +
- " int k = 10;\n" +
- " switch (i) {\n" +
- " case 0 -> { k = 0;}\n" +
- " default -> k = -1;\n" +
- " }\n" +
- " return k;\n" +
- " }\n" +
- " public static void main(String[] argv) {\n" +
- " System.out.println(new X().foo(0) == 0 ? \"Success\" : \"Failure\");\n" +
- " }\n" +
- "\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " default -> k = -1;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug545168_01() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " public static void foo(Day day) {\n" +
- " switch (day) {\n" +
- " case MONDAY, FRIDAY -> System.out.println(Day.SUNDAY);\n" +
- " case TUESDAY -> System.out.println(7);\n" +
- " case THURSDAY, SATURDAY -> System.out.println(8);\n" +
- " case WEDNESDAY -> System.out.println(9);\n" +
- " default -> {}\n" +
- " } \n" +
- " }\n" +
- " public static void main(String[] args) {\n" +
- " X.foo(Day.WEDNESDAY);\n" +
- " }\n" +
- "}\n" +
- "\n" +
- "enum Day {\n" +
- " MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " case MONDAY, FRIDAY -> System.out.println(Day.SUNDAY);\n" +
- " ^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 7)\n" +
- " case THURSDAY, SATURDAY -> System.out.println(8);\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 9)\n" +
- " default -> {}\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug545255_01() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n"+
- " public static void foo (int i) {\n"+
- " int v = switch (i) {\n"+
- " case 60, 600: break 6;\n"+
- " case 70: break 7;\n"+
- " case 80: break 8;\n"+
- " case 90, 900: break 9;\n"+
- " default: break 0;\n"+
- " };\n"+
- " System.out.println(v);\n"+
- " }\n"+
- " public static void main(String[] args) {\n"+
- " X.foo(10);\n"+
- " }\n"+
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case 60, 600: break 6;\n" +
- " ^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case 60, 600: break 6;\n" +
- " ^\n" +
- "Syntax error on token \"6\", delete this token\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 5)\n" +
- " case 70: break 7;\n" +
- " ^\n" +
- "Syntax error on token \"7\", delete this token\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 6)\n" +
- " case 80: break 8;\n" +
- " ^\n" +
- "Syntax error on token \"8\", delete this token\n" +
- "----------\n" +
- "5. ERROR in X.java (at line 7)\n" +
- " case 90, 900: break 9;\n" +
- " ^\n" +
- "Syntax error on token \"9\", delete this token\n" +
- "----------\n" +
- "6. ERROR in X.java (at line 8)\n" +
- " default: break 0;\n" +
- " ^\n" +
- "Syntax error on token \"0\", delete this token\n" +
- "----------\n");
- }
- // see comment 12 in the bug
- public void _testBug513766_01() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n"+
- " @SuppressWarnings(\"preview\")\n"+
- " public void foo(int i) {\n"+
- " if (switch(i) { default -> magic(); })\n"+
- " System.out.println(\"true\");\n"+
- " if (magic())\n"+
- " System.out.println(\"true, too\");\n"+
- " }\n"+
- " <T> T magic() { return null; }\n"+
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " if (switch(i) { default -> magic(); })\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from Object to boolean\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " if (switch(i) { default -> magic(); })\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 6)\n" +
- " if (magic())\n" +
- " ^^^^^^^\n" +
- "Type mismatch: cannot convert from Object to boolean\n" +
- "----------\n");
- }
- public void _testBug545333() {
- runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n"+
- " @SuppressWarnings(\"preview\")\n"+
- " public static int foo(int i) throws MyException {\n"+
- " int v = switch (i) {\n"+
- " default -> throw new MyException();\n"+
- " };\n"+
- " return v;\n"+
- " }\n"+
- " public static void main(String argv[]) {\n"+
- " try {\n"+
- " System.out.println(X.foo(1));\n"+
- " } catch (MyException e) {\n"+
- " System.out.println(\"Exception thrown as expected\");\n"+
- " }\n"+
- " }\n"+
- "}\n"+
- "class MyException extends Exception {\n"+
- " private static final long serialVersionUID = 3461899582505930473L; \n"+
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " int v = switch (i) {\n" +
- " default -> throw new MyException();\n" +
- " };\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "A switch expression should have at least one result expression\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 5)\n" +
- " default -> throw new MyException();\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug545518() {
- if (this.complianceLevel < ClassFileConstants.JDK12)
- return;
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
- String message =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " case \"ABC\", (false ? (String) \"c\" : (String) \"d\") : break;\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
-
- this.runNegativeTest(new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String [] args) {\n" +
- " String arg = \"ABD\";\n" +
- " switch(arg) {\n" +
- " case \"ABC\", (false ? (String) \"c\" : (String) \"d\") : break;\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- message,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- public void _testBug545518a() {
- if (this.complianceLevel < ClassFileConstants.JDK12)
- return;
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
- String message =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " case \"ABC\", (false ? (String) \"c\" : (String) \"d\") : break;\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
-
- this.runNegativeTest(new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String [] args) {\n" +
- " String arg = \"ABD\";\n" +
- " switch(arg) {\n" +
- " case \"ABC\", (false ? (String) \"c\" : (String) \"d\") : break;\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- message,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- public void _testBug545518b() {
- if (this.complianceLevel < ClassFileConstants.JDK1_8)
- return;
- Map<String, String> options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
- options.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
- String message =
- "----------\n" +
- "1. ERROR in X.java (at line 5)\n" +
- " case \"ABC\", (false ? (String) \"c\" : (String) \"d\") : break;\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n";
-
- this.runNegativeTest(new String[] {
- "X.java",
- "public class X {\n" +
- " public static void main(String [] args) {\n" +
- " String arg = \"ABD\";\n" +
- " switch(arg) {\n" +
- " case \"ABC\", (false ? (String) \"c\" : (String) \"d\") : break;\n" +
- " }\n" +
- " }\n" +
- "}\n"
- },
- message,
- null,
- true,
- new String[] { "--enable-preview"},
- options);
- }
- public void _testBug545715_01() {
- runNegativeTest(
- new String[] {
- "X.java",
- "enum X {\n"+
- " A, B; \n"+
- " @SuppressWarnings(\"preview\")\n"+
- " public static void main(String[] args) {\n"+
- " X myEnum = X.A;\n"+
- " int o;\n"+
- " switch(myEnum) {\n"+
- " case A -> o = 5;\n"+
- " case B -> o = 10;\n"+
- " default -> o = 0;\n"+
- " }\n"+
- " System.out.println(o);\n"+
- " }\n"+
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " default -> o = 0;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug545916_01() {
- runConformTest(
- new String[] {
- "X.java",
- "enum X {\n"+
- " A, B;\n"+
- " \n"+
- " @SuppressWarnings(\"preview\")\n"+
- " public static void main(String[] args) {\n"+
- " X myEnum = X.A;\n"+
- " int o;\n"+
- " var f = switch(myEnum) {\n"+
- " case A -> o = 5;\n"+
- " case B -> o = 10;\n"+
- " };\n"+
- " System.out.println(o);\n"+
- " }\n"+
- "} \n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 10)\n" +
- " default -> o = 0;\n" +
- " ^^^^^^^\n" +
- "The preview feature Case Labels with \'->\' is only available with source level 13 and above\n" +
- "----------\n");
- }
- public void _testBug545983_01() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "\n"+
- "public class X {\n"+
- "\n"+
- " @SuppressWarnings(\"preview\")\n"+
- " public static int foo() {\n"+
- " for (int i = 0; i < 1; ++i) {\n"+
- " int k = switch (i) {\n"+
- " case 0:\n"+
- " break 1;\n"+
- " default:\n"+
- " continue;\n"+
- " };\n"+
- " System.out.println(k);\n"+
- " }\n"+
- " return 1;\n"+
- " }\n"+
- " public static void main(String[] args) {\n"+
- " X.foo();\n"+
- " }\n"+
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 9)\n" +
- " break 1;\n" +
- " ^\n" +
- "Syntax error on token \"1\", delete this token\n" +
- "----------\n");
- }
- public void _testBug545983_02() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "\n"+
- "public class X {\n"+
- "\n"+
- " @SuppressWarnings(\"preview\")\n"+
- " public static int foo() {\n"+
- " for (int i = 0; i < 1; ++i) {\n"+
- " int k = switch (i) {\n"+
- " case 0:\n"+
- " break 1;\n"+
- " default:\n"+
- " return 2;\n"+
- " };\n"+
- " System.out.println(k);\n"+
- " }\n"+
- " return 1;\n"+
- " }\n"+
- " public static void main(String[] args) {\n"+
- " X.foo();\n"+
- " }\n"+
- "}\n",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 9)\n" +
- " break 1;\n" +
- " ^\n" +
- "Syntax error on token \"1\", delete this token\n" +
- "----------\n");
- }
- public void _testBug547125_01() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " void foo(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY, SUNDAY:\n" +
- " System.out.println(\"Weekend\");\n" +
- " case MONDAY:\n" +
- " System.out.println(\"Weekday\");\n" +
- " default: \n" +
- " }\n" +
- " }\n" +
- "}\n" +
- "\n" +
- "enum Day {\n" +
- " MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" +
- "}",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY, SUNDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY, SUNDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- " ^^^^^^^\n" +
- "----------\n");
- }
- public void _testBug547125_02() {
- this.runNegativeTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " void foo(Day day) {\n" +
- " switch (day) {\n" +
- " case SATURDAY, SUNDAY, MONDAY:\n" +
- " System.out.println(\"Weekend\");\n" +
- " case MONDAY, SUNDAY:\n" +
- " System.out.println(\"Weekday\");\n" +
- " default: \n" +
- " }\n" +
- " }\n" +
- "}\n" +
- "\n" +
- "enum Day {\n" +
- " MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" +
- "}",
- },
- "----------\n" +
- "1. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY, MONDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " case SATURDAY, SUNDAY, MONDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "3. ERROR in X.java (at line 6)\n" +
- " case MONDAY, SUNDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^\n" +
- "The preview feature Multi constant case is only available with source level 13 and above\n" +
- "----------\n" +
- "4. ERROR in X.java (at line 6)\n" +
- " case MONDAY, SUNDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n" +
- "5. ERROR in X.java (at line 6)\n" +
- " case MONDAY, SUNDAY:\n" +
- " ^^^^^^^^^^^^^^^^^^^\n" +
- "Duplicate case\n" +
- "----------\n");
- }
- public void _testBug544943() {
- runConformTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings(\"preview\")\n" +
- " public static int foo(int i) throws MyException {\n" +
- " int v = -1;\n" +
- " try {\n" +
- " v = switch (i) {\n" +
- " case 0 -> switch(i) {\n" +
- " case 0 -> 1;\n" +
- " default -> throw new MyException();\n" +
- " };\n" +
- " default -> 1;\n" +
- " };\n" +
- " } finally {\n" +
- " // do nothing\n" +
- " }\n" +
- " return v;\n" +
- " } \n" +
- " public static void main(String argv[]) {\n" +
- " try {\n" +
- " System.out.println(X.foo(0));\n" +
- " } catch (MyException e) {\n" +
- " e.printStackTrace();\n" +
- " }\n" +
- " }\n" +
- "}\n" +
- "class MyException extends Exception {\n" +
- " private static final long serialVersionUID = 3461899582505930473L; \n" +
- "}"
- },
- "1");
- }
- public void _testBug544943_2() {
- runConformTest(
- new String[] {
- "X.java",
- "public class X {\n" +
- " @SuppressWarnings({ \"preview\" })\n" +
- " public static int foo(int i) throws Exception {\n" +
- " int v = switch (i) {\n" +
- " case 0 -> switch (i) {\n" +
- " case 0 -> 0;\n" +
- " default-> throw new Exception();\n" +
- " case 3 -> 3;\n" +
- " case 2 -> throw new Exception();\n" +
- " };\n" +
- " default -> 0;\n" +
- " };\n" +
- " return v;\n" +
- " }\n" +
- " public static void main(String argv[]) throws Exception {\n" +
- " System.out.println(X.foo(1));\n" +
- " }\n" +
- "}"
- },
- "0");
- }
-}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
index 6c8ae9eac..0cb6f7e8f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
@@ -486,7 +486,7 @@ public class SwitchExpressionsYieldTest extends AbstractRegressionTest {
"----------\n" +
"1. ERROR in X.java (at line 8)\n" +
" default :v = 2;\n" +
- " ^^^^^\n" +
+ " ^^\n" +
"A switch labeled block in a switch expression should not complete normally\n" +
"----------\n";
this.runNegativeTest(
@@ -2166,7 +2166,7 @@ public class SwitchExpressionsYieldTest extends AbstractRegressionTest {
" };\n"+
" System.out.println(k);\n"+
" }\n"+
- " return 1;\n"+
+ " return 100;\n"+
" }\n"+
" public static void main(String[] args) {\n"+
" X.foo();\n"+
@@ -2177,7 +2177,7 @@ public class SwitchExpressionsYieldTest extends AbstractRegressionTest {
"1. ERROR in X.java (at line 11)\n" +
" return 2;\n" +
" ^^^^^^^^^\n" +
- "'continue' or 'return' cannot be the last statement in a Switch expression case body\n" +
+ "Return within switch expressions not permitted\n" +
"----------\n");
}
public void testBug544073_078() {
@@ -4669,5 +4669,527 @@ public class SwitchExpressionsYieldTest extends AbstractRegressionTest {
},
"1");
}
+ public void testBug562728_001() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " static public void main (String[] args) {\n"+
+ " int a = 0x21;\n"+
+ " int b = 0xff;\n"+
+ " switch (a) {\n"+
+ " case 0x21 -> {\n"+
+ " switch (b) {\n"+
+ " default -> System.out.println(\"default\");\n"+
+ " }\n"+
+ " }\n"+
+ " case 0x3b -> System.out.println(\"3b <- WTH?\");\n"+
+ " }\n"+
+ " }\n"+
+ "}\n"
+ },
+ "default");
+ }
+ public void testBug562728_002() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " static public void main (String[] args) {\n"+
+ " int a = 0x21;\n"+
+ " int b = 0xff;\n"+
+ " switch (a) {\n"+
+ " case 0x21 -> {\n"+
+ " switch (b) {\n"+
+ " default -> System.out.println(\"default\");\n"+
+ " }\n"+
+ " return;\n"+
+ " }\n"+
+ " case 0x3b -> System.out.println(\"3b <- WTH?\");\n"+
+ " }\n"+
+ " }\n"+
+ "}\n"
+ },
+ "default");
+ }
+ public void testBug562728_003() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " static public void main (String[] args) throws Exception {\n"+
+ " int a = 0x21;\n"+
+ " int b = 0xff;\n"+
+ " switch (a) {\n"+
+ " case 0x21 -> {\n"+
+ " switch (b) {\n"+
+ " default -> throw new Exception();\n"+
+ " }\n"+
+ " return; \n"+
+ " }\n"+
+ " case 0x3b -> System.out.println(\"3b <- WTH?\");\n"+
+ " }\n"+
+ " }\n"+
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " return; \n" +
+ " ^^^^^^^\n" +
+ "Unreachable code\n" +
+ "----------\n");
+ }
+ public void testBug562728_004() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " static public void main (String[] args) throws Exception {\n"+
+ " int a = 0x21;\n"+
+ " int b = 0xff;\n"+
+ " Zork();\n"+
+ " switch (a) {\n"+
+ " case 0x21 -> {\n"+
+ " switch (b) {\n"+
+ " default -> {\n"+
+ " for (;;) {\n"+
+ " if (b > 1)\n"+
+ " throw new Exception();\n"+
+ " }\n"+
+ " }\n"+
+ " }\n"+
+ " }\n"+
+ " case 0x3b -> System.out.println(\"3b <- WTH?\");\n"+
+ " }\n"+
+ " }\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " Zork();\n" +
+ " ^^^^\n" +
+ "The method Zork() is undefined for the type X\n" +
+ "----------\n");
+ }
+ public void testBug562728_005() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " public static int foo(int i) { \n"+
+ " int v; \n"+
+ " int t = switch (i) { \n"+
+ " case 0 : { \n"+
+ " yield 0; \n"+
+ " } \n"+
+ " case 2 :v = 2;\n"+
+ " default :v = 2;\n"+
+ " }; \n"+
+ " return t; \n"+
+ " } \n"+
+ " \n"+
+ " public boolean bar() { \n"+
+ " return true; \n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(foo(3));\n"+
+ " } \n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " default :v = 2;\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n");
+ }
+ public void testBug562728_006() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " public static int foo(int i) { \n"+
+ " int v; \n"+
+ " int t = switch (i) { \n"+
+ " case 0 -> { \n"+
+ " yield 0; \n"+
+ " } \n"+
+ " case 2 ->{v = 2;}\n"+
+ " default ->{v = 2;}\n"+
+ " }; \n"+
+ " return t; \n"+
+ " } \n"+
+ " \n"+
+ " public boolean bar() { \n"+
+ " return true; \n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(foo(3));\n"+
+ " } \n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " case 2 ->{v = 2;}\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " default ->{v = 2;}\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n");
+ }
+ public void testBug562728_007() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " public static int foo(int i) { \n"+
+ " int v; \n"+
+ " int t = switch (i) { \n"+
+ " case 0 -> { \n"+
+ " return 1;\n"+
+ " } \n"+
+ " default ->100;\n"+
+ " }; \n"+
+ " return t; \n"+
+ " } \n"+
+ " \n"+
+ " public boolean bar() { \n"+
+ " return true; \n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(foo(3));\n"+
+ " } \n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " return 1;\n" +
+ " ^^^^^^^^^\n" +
+ "Return within switch expressions not permitted\n" +
+ "----------\n");
+}
+ public void testBug563023_001() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(int a, int b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " default -> {\n"+
+ " yield 0;\n"+
+ " }\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(0, 0));\n"+
+ " }\n"+
+ "}\n"
+ },
+ "0");
+ }
+ public void testBug563023_002() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(int a, int b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " case 0 -> {\n"+
+ " break;\n"+
+ " }\n"+
+ " default -> {\n"+
+ " yield 0;\n"+
+ " }\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(0, 0));\n"+
+ " }\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " }\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n");
+}
+ public void testBug563023_003() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(int a, int b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " case 0 -> {\n"+
+ " yield 0;\n"+
+ " }\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(0, 0));\n"+
+ " }\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " }\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n");
+}
+ public void testBug563023_004() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(int a, int b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " case 0 -> {\n"+
+ " break;\n"+
+ " }\n"+
+ " default -> yield 0;\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(0, 0));\n"+
+ " }\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " default -> yield 0;\n" +
+ " ^\n" +
+ "Syntax error on token \"0\", delete this token\n" +
+ "----------\n");
+}
+ public void testBug563023_005() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(int a, int b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " case 0 -> {\n"+
+ " break;\n"+
+ " }\n"+
+ " default ->{ yield 0;}\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(0, 0));\n"+
+ " }\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " }\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n");
+}
+ public void testBug563023_006() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(MyEnum a, MyEnum b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " case ONE -> { \n"+
+ " yield 0;\n"+
+ " }\n"+
+ " default -> {yield 1;}\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(MyEnum.ONE, MyEnum.TWO));\n"+
+ " }\n"+
+ "} \n"+
+ "enum MyEnum {\n"+
+ " ONE,\n"+
+ " TWO\n"+
+ "}\n"
+ },
+ "1");
+ }
+ public void testBug563023_007() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X { \n"+
+ " static public int foo(MyEnum a, MyEnum b){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " switch (b) {\n"+
+ " case ONE -> { \n"+
+ " yield 0;\n"+
+ " }\n"+
+ " } \n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(MyEnum.ONE, MyEnum.TWO));\n"+
+ " }\n"+
+ "} \n"+
+ "enum MyEnum {\n"+
+ " ONE,\n"+
+ " TWO\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 5)\n" +
+ " switch (b) {\n" +
+ " ^\n" +
+ "The enum constant TWO needs a corresponding case label in this enum switch on MyEnum\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " }\n" +
+ " ^^\n" +
+ "A switch labeled block in a switch expression should not complete normally\n" +
+ "----------\n");
+}
+ public void testBug563147_001() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "interface I {\n"+
+ " public int apply();\n"+
+ "}\n"+
+ "public class X { \n"+
+ " static public int foo(int a){\n"+
+ " int t = switch (a) {\n"+
+ " default -> {\n"+
+ " I lambda = () -> { return 0;};\n"+
+ " yield lambda.apply();\n"+
+ " }\n"+
+ " };\n"+
+ " return t;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " System.out.println(X.foo(1));\n"+
+ " }\n"+
+ "} \n"
+ },
+ "0");
+ }
+ public void testBug563147_002() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "interface FI {\n"+
+ " public int foo();\n"+
+ "}\n"+
+ "public class X {\n"+
+ " public int field = 0;\n"+
+ " public int test() {\n"+
+ " var v = switch (field) {\n"+
+ " case 0 -> {\n"+
+ " yield ((FI ) () -> {\n"+
+ " int i = 0;\n"+
+ " while (true) {\n"+
+ " i++;\n"+
+ " if (i == 7) {\n"+
+ " break;\n"+
+ " }\n"+
+ " }\n"+
+ " return i;\n"+
+ " }); \n"+
+ " }\n"+
+ " default -> {\n"+
+ " yield null;\n"+
+ " }\n"+
+ " }; \n"+
+ " return 0;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " int t = new X().test();\n"+
+ " System.out.println(t);\n"+
+ "}\n"+
+ "}\n"
+ },
+ "0");
+ }
+ public void testBug563147_003() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "interface FI {\n"+
+ " public int foo();\n"+
+ "}\n"+
+ "public class X {\n"+
+ " public int field = 0;\n"+
+ " public int test() {\n"+
+ " var v = switch (field) {\n"+
+ " case 0 -> {\n"+
+ " yield ((F ) () -> {\n"+
+ " int i = 0;\n"+
+ " while (true) {\n"+
+ " i++;\n"+
+ " if (i == 7) {\n"+
+ " break;\n"+
+ " }\n"+
+ " }\n"+
+ " return i;\n"+
+ " }); \n"+
+ " }\n"+
+ " default -> {\n"+
+ " yield null;\n"+
+ " }\n"+
+ " }; \n"+
+ " return 0;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " int t = new X().test();\n"+
+ " System.out.println(t);\n"+
+ "}\n"+
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " yield ((F ) () -> {\n" +
+ " ^\n" +
+ "F cannot be resolved to a type\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " yield ((F ) () -> {\n" +
+ " ^^^^^\n" +
+ "The target type of this expression must be a functional interface\n" +
+ "----------\n");
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index 0be1c91dc..379bbb121 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -173,6 +173,7 @@ public static Test suite() {
since_9.add(UnnamedModuleTest.class);
since_9.add(NullAnnotationTests9.class);
since_9.add(AnnotationTest_9.class);
+ since_9.add(JavadocTestForModule.class);
// add 10 specific test here (check duplicates)
ArrayList since_10 = new ArrayList();
@@ -187,7 +188,6 @@ public static Test suite() {
// add 12 specific test here (check duplicates)
ArrayList since_12 = new ArrayList();
- since_12.add(SwitchExpressionTest.class);
since_12.add(Unicode11Test.class);
// add 13 specific test here (check duplicates)
@@ -199,6 +199,7 @@ public static Test suite() {
since_14.add(SwitchExpressionsYieldTest.class);
since_14.add(RecordsRestrictedClassTest.class);
since_14.add(PatternMatching14Test.class);
+ since_14.add(JavadocTestForRecord.class);
// Build final test suite
TestSuite all = new TestSuite(TestAll.class.getName());
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java
index 79f463143..99244e58a 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java
@@ -15,7 +15,6 @@ package org.eclipse.jdt.core.tests.compiler.regression;
import java.util.HashMap;
import java.util.Map;
-import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import junit.framework.Test;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest2.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest2.java
index 53c49bf32..49a9c058d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest2.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/XLargeTest2.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018 Andrey Loskutov and others.
+ * Copyright (c) 2018, 2020 Andrey Loskutov and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -404,4 +404,22 @@ public class XLargeTest2 extends AbstractRegressionTest {
"interface gwz {}\n" +
"interface gxc {}\n";
}
+ public void testBug550480() {
+ StringBuilder source = new StringBuilder();
+ source.append("package p;\n");
+ String[] names = new String[571];
+ for (int i = 0; i < 571; i++) {
+ names[i] = "I"+i;
+ source.append("interface ").append(names[i]).append(" {}\n");
+ }
+ source.append("public abstract class hft implements ");
+ source.append(String.join(", ", names));
+ source.append("\n{\n}\n");
+ runConformTest(
+ new String[] {
+ "p/hft.java",
+ source.toString()
+ });
+ }
+
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
index e664e6268..25f31d698 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
@@ -168,12 +168,6 @@ public class AbstractCompilerTest extends TestCase {
public static void setpossibleComplianceLevels(int complianceLevel) {
possibleComplianceLevels = complianceLevel;
- int lessthan9 = F_1_3 | F_1_4 | F_1_5 | F_1_6 | F_1_7 | F_1_8;
- isJRE9Plus = !isJRELevel(lessthan9);
- isJRE14Plus = isJRELevel(F_14);
- isJRE13Plus = isJRELevel(F_13) || isJRE14Plus;
- isJRE12Plus = isJRE13Plus || isJRELevel(F_12);
- isJRE11Plus = isJRE12Plus || isJRELevel(F_11);
}
/**
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java
index 375361265..2d3db19d7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java
@@ -11,7 +11,9 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - contribution for bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
- * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for bug 559618 - No compiler warning for import from same package
+ * Pierre-Yves B. <pyvesdev@gmail.com> - Contributions for
+ * Bug 559618 - No compiler warning for import from same package
+ * Bug 560630 - No warning on unused import on class from same package
*******************************************************************************/
package org.eclipse.jdt.core.tests.model;
@@ -2791,4 +2793,29 @@ public void testBug559618_3() throws CoreException { // Nested class imports mus
deleteFile("/P/src/p/D.java");
}
}
+public void testBug560630() throws CoreException {
+ try {
+ createFile("/P/src/p/C.java",
+ "package p;\n" +
+ "public class C{};\n");
+
+ createFile("/P/src/p/D.java",
+ "package p;\n" +
+ "import p.C;\n" +
+ "public class D extends C {}\n");
+ ICompilationUnit cuD = getCompilationUnit("/P/src/p/D.java");
+
+ ASTParser parser = ASTParser.newParser(AST_INTERNAL_LATEST);
+ parser.setProject(this.testProject);
+ parser.setSource(cuD);
+ parser.setResolveBindings(true);
+ org.eclipse.jdt.core.dom.CompilationUnit cuAST = (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(null);
+ IProblem[] problems = cuAST.getProblems();
+ assertEquals("Should have 1 problem", 1, problems.length);
+ assertEquals("Should have only an unused warning", "The import p.C is never used", problems[0].getMessage());
+ } finally {
+ deleteFile("/P/src/p/C.java");
+ deleteFile("/P/src/p/D.java");
+ }
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionWithMissingTypesTests_1_8.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionWithMissingTypesTests_1_8.java
new file mode 100644
index 000000000..1c9b27aba
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionWithMissingTypesTests_1_8.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Julian Honnen.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Julian Honnen - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import java.util.Hashtable;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+import junit.framework.Test;
+
+public class CompletionWithMissingTypesTests_1_8 extends AbstractJavaModelCompletionTests {
+
+public CompletionWithMissingTypesTests_1_8(String name) {
+ super(name);
+}
+@Override
+public void setUpSuite() throws Exception {
+ if (COMPLETION_PROJECT == null) {
+ COMPLETION_PROJECT = setUpJavaProject("Completion", "1.8");
+ } else {
+ setUpProjectCompliance(COMPLETION_PROJECT, "1.8");
+ }
+ super.setUpSuite();
+}
+static {
+// TESTS_NAMES = new String[] { "testZZZ"};
+}
+public static Test suite() {
+ return buildModelTestSuite(CompletionWithMissingTypesTests_1_8.class);
+}
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=563010
+public void testStaticInterfaceMethod() throws JavaModelException {
+ this.oldOptions = JavaCore.getOptions();
+
+ try {
+ Hashtable<String, String> options = new Hashtable<>(this.oldOptions);
+ options.put(JavaCore.CODEASSIST_VISIBILITY_CHECK, JavaCore.ENABLED);
+ JavaCore.setOptions(options);
+
+ this.workingCopies = new ICompilationUnit[3];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/test/Test.java",
+ "package test;"+
+ "public class Test {\n" +
+ " void foo() {\n" +
+ " MissingType.foo\n" +
+ " }\n" +
+ "}\n");
+
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/missing/MissingType.java",
+ "package missing;"+
+ "public interface MissingType {\n" +
+ " void foo1()\n" +
+ " static void foo2() {}\n" +
+ "}\n");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, false, true, false, true);
+ requestor.allowAllRequiredProposals();
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "MissingType.foo";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+
+ int relevance1 = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_NON_INHERITED + R_NON_RESTRICTED
+ + R_NO_PROBLEMS;
+ int start1 = str.lastIndexOf("MissingType.") + "MissingType.".length();
+ int end1 = start1 + "foo".length();
+ int start2 = str.indexOf("MissingType");
+ int end2 = start2 + "MissingType".length();
+ assertResults(
+ "foo2[METHOD_REF]{foo2(), Lmissing.MissingType;, ()V, foo2, null, ["+start1+", "+end1+"], " + (relevance1) + "}\n" +
+ " MissingType[TYPE_REF]{missing.MissingType, missing, Lmissing.MissingType;, null, null, ["+start2+", "+end2+"], " + (relevance1) + "}",
+ requestor.getResults());
+ } finally {
+ JavaCore.setOptions(this.oldOptions);
+ }
+}
+
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CopyMoveTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CopyMoveTests.java
index dd024f0e4..b7df04cad 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CopyMoveTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CopyMoveTests.java
@@ -19,6 +19,8 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
+import junit.framework.AssertionFailedError;
+
abstract public class CopyMoveTests extends ModifyingResourceTests {
public CopyMoveTests(String name) {
super(name);
@@ -110,9 +112,13 @@ public IJavaElement copyPositive(IJavaElement element, IJavaElement container, I
if (copy.getElementType() == IJavaElement.IMPORT_DECLARATION)
container = ((ICompilationUnit) container).getImportContainer();
IJavaElementDelta destDelta = listener.getDeltaFor(container, true);
- assertTrue("Destination container not changed", destDelta != null && destDelta.getKind() == IJavaElementDelta.CHANGED);
+ assertTrue("No delta", destDelta != null);
+ assertTrue("Destination container not changed", destDelta.getKind() == IJavaElementDelta.CHANGED);
IJavaElementDelta[] deltas = destDelta.getAddedChildren();
assertTrue("Added children not correct for element copy", deltas[0].getElement().equals(copy));
+ } catch (AssertionFailedError afe) {
+ System.err.println(listener.stackTraces());
+ throw afe;
} finally {
stopDeltas(listener);
}
@@ -351,7 +357,8 @@ public void movePositive(IJavaElement[] elements, IJavaElement[] destinations, I
IJavaElementDelta destDelta = null;
if (isMainType(element, destinations[i]) && names != null && names[i] != null) { //moved/renamed main type to same cu
destDelta = listener.getDeltaFor(moved.getParent());
- assertTrue("Renamed compilation unit as result of main type not added", destDelta != null && destDelta.getKind() == IJavaElementDelta.ADDED);
+ assertTrue("No delta", destDelta != null);
+ assertTrue("Renamed compilation unit as result of main type not added", destDelta.getKind() == IJavaElementDelta.ADDED);
assertTrue("flag should be F_MOVED_FROM", (destDelta.getFlags() & IJavaElementDelta.F_MOVED_FROM) > 0);
assertTrue("moved from handle should be original", destDelta.getMovedFromElement().equals(element.getParent()));
} else {
@@ -365,6 +372,9 @@ public void movePositive(IJavaElement[] elements, IJavaElement[] destinations, I
}
}
}
+ } catch (AssertionFailedError afe) {
+ System.err.println(listener.stackTraces());
+ throw afe;
} finally {
if(checkDelta) stopDeltas(listener);
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java
index e9703b9db..8ece18a0d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java
@@ -127,7 +127,7 @@ public class JavaConventionTests extends AbstractJavaModelTests {
case IMPORT_DECLARATION:
return JavaConventions.validateImportDeclaration(string, sourceLevel, complianceLevel).getSeverity();
case JAVA_TYPE_NAME:
- return JavaConventions.validateJavaTypeName(string, sourceLevel, complianceLevel).getSeverity();
+ return JavaConventions.validateJavaTypeName(string, sourceLevel, complianceLevel, null).getSeverity();
case METHOD_NAME:
return JavaConventions.validateMethodName(string, sourceLevel, complianceLevel).getSeverity();
case PACKAGE_NAME:
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs14Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs14Tests.java
index f52e17e89..34fe476f6 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs14Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs14Tests.java
@@ -17,6 +17,7 @@ import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -522,7 +523,35 @@ public class JavaSearchBugs14Tests extends AbstractJavaSearchTests {
search(elements[0], REFERENCES, EXACT_RULE);
assertSearchResults(
"src/X.java Point(int) [comp_] EXACT_MATCH\n" +
- "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH");
+ }
+ public void testBug558812_016a() throws CoreException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+ "public record Point(int comp_) { \n" +
+ " public Point {\n" +
+ " comp_=11;\n" +
+ " }\n" +
+ "public void method ( ) { \n"+
+ " int compp_=comp_;\n" +
+ " int compp2_=comp_;\n" +
+ "} \n"+
+ "}\n"
+ );
+
+ String str = this.workingCopies[0].getSource();
+ String selection = "comp_";
+ int start = str.lastIndexOf(selection);
+ int length = selection.length();
+
+ IJavaElement[] elements = this.workingCopies[0].codeSelect(start, length);
+ assertTrue(elements.length ==1);
+ assertTrue(elements[0] instanceof IField);
+ search(elements[0], REFERENCES, EXACT_RULE);
+ assertSearchResults(
+ "src/X.java Point(int) [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
"src/X.java void Point.method() [comp_] EXACT_MATCH");
}
@@ -552,8 +581,38 @@ public class JavaSearchBugs14Tests extends AbstractJavaSearchTests {
search(elements[0], REFERENCES, EXACT_RULE);
assertSearchResults(
"src/X.java Point(int) [comp_] EXACT_MATCH\n" +
- "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
- "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH");
+ }
+ public void testBug558812_017a() throws CoreException {
+ this.workingCopies = new ICompilationUnit[1];
+ this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+ "public record Point(int comp_) { \n" +
+ " public Point {\n" +
+ " comp_=11;\n" +
+ " }\n" +
+ "public void method ( ) { \n"+
+ " int compp_=comp_;\n" +
+ " int compp2_=comp_;\n" +
+ " int compp3_=this.comp_;\n" +
+ "} \n"+
+ "}\n"
+ );
+
+ String str = this.workingCopies[0].getSource();
+ String selection = "comp_";
+ int start = str.lastIndexOf(selection);
+ int length = selection.length();
+
+ IJavaElement[] elements = this.workingCopies[0].codeSelect(start, length);
+ assertTrue(elements.length ==1);
+ assertTrue(elements[0] instanceof IField);
+ search(elements[0], REFERENCES, EXACT_RULE);
+ assertSearchResults(
+ "src/X.java Point(int) [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n" +
"src/X.java void Point.method() [comp_] EXACT_MATCH");
}
@@ -794,7 +853,7 @@ public class JavaSearchBugs14Tests extends AbstractJavaSearchTests {
search(elements[0], REFERENCES, EXACT_RULE);
assertSearchResults(
"src/X.java Point(int) [comp_] EXACT_MATCH\n" +
- "src/X.java void Point.method() [comp_] EXACT_MATCH\n"+
+ "src/X.java void Point.method() [comp_] EXACT_MATCH\n"+
"src/X.java void Point.method() [comp_] EXACT_MATCH");
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index 4be741f62..5f31b7e92 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -8877,6 +8877,59 @@ public class ModuleBuilderTests extends ModifyingResourceTests {
deleteProject(prjB);
}
}
+ public void testBug538512_comment9() throws CoreException, IOException {
+ try {
+ IJavaProject project = createJava9Project("ztest", new String[] { "src" });
+ createFolder("/ztest/lib");
+ Util.createJar(new String[] {
+ "org/xml/sax/Parser.java",
+ "package org.xml.sax;\n" +
+ "public class Parser {}\n"
+ },
+ project.getProject().getLocation().toString() + "/lib/xml-apis.jar", // conflicts with module 'java.xml'
+ "1.8");
+ IClasspathEntry libraryEntry = JavaCore.newLibraryEntry(new Path("/ztest/lib/xml-apis.jar"), null, null);
+ addClasspathEntry(project, libraryEntry, 1); // right after src and before jrt-fs.jar
+ Util.createJar(new String[] {
+ "org/apache/xerces/parsers/SAXParser.java",
+ "package org.apache.xerces.parsers;\n" +
+ "public abstract class SAXParser implements org.xml.sax.Parser, java.io.Serializable {}\n"
+ },
+ project.getProject().getLocation().toString() + "/lib/xercesImpl.jar",
+ "1.8");
+ project.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
+ libraryEntry = JavaCore.newLibraryEntry(new Path("/ztest/lib/xercesImpl.jar"), null, null);
+ addClasspathEntry(project, libraryEntry, 1); // right after src and before jrt-fs.jar
+
+ String testSource =
+ "package com.ztest;\n" +
+ "import org.apache.xerces.parsers.SAXParser;\n" +
+ "\n" +
+ "public class MySAXParser extends SAXParser {\n" +
+ " static final long serialVersionUID = 0;\n" +
+ "}\n";
+ createFolder("/ztest/src/com/ztest");
+ createFile("/ztest/src/com/ztest/MySAXParser.java", testSource);
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ sortMarkers(markers);
+ assertMarkers("Unexpected Markers",
+ "",
+ markers);
+
+ char[] sourceChars = testSource.toCharArray();
+ this.problemRequestor.initialize(sourceChars);
+ getCompilationUnit("/ztest/src/com/ztest/MySAXParser.java").getWorkingCopy(this.wcOwner, null);
+ assertProblems(
+ "Unexpected problems",
+ "----------\n" +
+ "----------\n",
+ this.problemRequestor);
+
+ } finally {
+ deleteProject("ztest");
+ }
+ }
protected void assertNoErrors() throws CoreException {
for (IProject p : getWorkspace().getRoot().getProjects()) {
int maxSeverity = p.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
index 6b2c1939c..a1aea2b36 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
@@ -6006,7 +6006,7 @@ public void testBug534865() throws CoreException, IOException {
deleteProject(project18);
}
}
-public void testBug559774() throws CoreException, IOException, InterruptedException {
+public void testBug562637() throws CoreException, IOException, InterruptedException {
if (!isJRE14) return;
IJavaProject project14 = null;
try {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RecordsElementTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RecordsElementTests.java
new file mode 100644
index 000000000..e8619bbe1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RecordsElementTests.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2020 IBM Corporation.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
+
+import junit.framework.Test;
+
+public class RecordsElementTests extends AbstractJavaModelTests {
+
+ static {
+// TESTS_NAMES = new String[] {"test001"};
+ }
+
+ public RecordsElementTests(String name) {
+ super(name);
+ }
+ public static Test suite() {
+ return buildModelTestSuite(AbstractCompilerTest.F_14, RecordsElementTests.class);
+ }
+ protected IJavaProject createJavaProject(String projectName) throws CoreException {
+ IJavaProject createJavaProject = super.createJavaProject(projectName, new String[] {"src"}, new String[] {"JCL14_LIB"}, "bin", "14");
+ createJavaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
+ return createJavaProject;
+ }
+ // Test a simple class for record oriented attributes
+ public void test001() throws Exception {
+ try {
+ IJavaProject project = createJavaProject("RecordsElement");
+ project.open(null);
+ String fileContent = "@SuppressWarnings(\"preview\")\n" +
+ "public class Point {\n" +
+ " public Point(int x1, int x2) {\n" +
+ " x1 = 10;\n" +
+ " x2 = 11;\n" +
+ " }\n" +
+ "}\n";
+ createFile( "/RecordsElement/src/X.java", fileContent);
+ ICompilationUnit unit = getCompilationUnit("/RecordsElement/src/X.java");
+ IType[] types = unit.getTypes();
+ assertEquals("Incorret no of types", 1, types.length);
+ assertEquals("type should be a record", IJavaElement.TYPE, types[0].getElementType());
+ assertFalse("type should be a record", types[0].isRecord());
+ IField[] recordComponents = types[0].getRecordComponents();
+ assertNotNull("should not be null", recordComponents);
+ assertEquals("Incorret no of components", 0, recordComponents.length);
+ }
+ finally {
+ deleteProject("RecordsElement");
+ }
+ }
+ // Test that with preview disabled, model doesn't see/create record elements
+ public void test002() throws Exception {
+ try {
+ IJavaProject project = createJavaProject("RecordsElement");
+ project.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.DISABLED);
+ project.open(null);
+ String fileContent = "@SuppressWarnings(\"preview\")\n" +
+ "public class Point {\n" +
+ " public Point(int x1, int x2) {\n" +
+ " x1 = 10;\n" +
+ " x2 = 11;\n" +
+ " }\n" +
+ "}\n";
+ createFile( "/RecordsElement/src/X.java", fileContent);
+ ICompilationUnit unit = getCompilationUnit("/RecordsElement/src/X.java");
+ IType[] types = unit.getTypes();
+ assertEquals("Incorret no of types", 1, types.length);
+ }
+ finally {
+ deleteProject("RecordsElement");
+ }
+ }
+ // Test a simple record and record components
+ public void test003() throws Exception {
+ try {
+ IJavaProject project = createJavaProject("RecordsElement");
+ project.open(null);
+ String fileContent = "@SuppressWarnings(\"preview\")\n" +
+ "public record Point(int x1, int x2) {\n" +
+ " public Point {\n" +
+ " this.x1 = 10;\n" +
+ " this.x2 = 11;\n" +
+ " }\n" +
+ "}\n";
+ createFile( "/RecordsElement/src/X.java", fileContent);
+ ICompilationUnit unit = getCompilationUnit("/RecordsElement/src/X.java");
+ IType[] types = unit.getTypes();
+ assertEquals("Incorret no of types", 1, types.length);
+ assertTrue("type should be a record", types[0].isRecord());
+ assertEquals("type should be a record", IJavaElement.TYPE, types[0].getElementType());
+ IField[] recordComponents = types[0].getRecordComponents();
+ assertNotNull("should be null", recordComponents);
+ assertEquals("Incorret no of components", 2, recordComponents.length);
+ IField comp = recordComponents[0];
+ assertEquals("type should be a record component", IJavaElement.FIELD, comp.getElementType());
+ assertEquals("incorrect element name", "x1", comp.getElementName());
+ comp = recordComponents[1];
+ assertEquals("type should be a record component", IJavaElement.FIELD, comp.getElementType());
+ assertEquals("incorrect element name", "x2", comp.getElementName());
+ }
+ finally {
+ deleteProject("RecordsElement");
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java
index ceb49bcfa..2f2141557 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java
@@ -47,6 +47,7 @@ public class RunCompletionModelTests extends junit.framework.TestCase {
COMPLETION_SUITES.add(CompletionWithMissingTypesTests.class);
COMPLETION_SUITES.add(CompletionWithMissingTypesTests2.class);
COMPLETION_SUITES.add(CompletionWithMissingTypesTests_1_5.class);
+ COMPLETION_SUITES.add(CompletionWithMissingTypesTests_1_8.class);
COMPLETION_SUITES.add(SnippetCompletionContextTests.class);
COMPLETION_SUITES.add(SubstringCompletionTests.class);
COMPLETION_SUITES.add(SubwordCompletionTests.class);
diff --git a/org.eclipse.jdt.core/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jdt.core/.settings/org.eclipse.jdt.ui.prefs
index 0221545ad..1f524a0e2 100644
--- a/org.eclipse.jdt.core/.settings/org.eclipse.jdt.ui.prefs
+++ b/org.eclipse.jdt.core/.settings/org.eclipse.jdt.ui.prefs
@@ -59,8 +59,8 @@ sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=false
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
-sp_cleanup.add_missing_override_annotations=true
-sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_missing_override_annotations=false
+sp_cleanup.add_missing_override_annotations_interface_methods=false
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java
index 8fd914a76..13f9cdccc 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2013 IBM Corporation and others.
+ * Copyright (c) 2008, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -18,6 +18,7 @@ import java.util.Map;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IMemberValuePair;
+import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMarkerAnnotationName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMemberValueName;
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnParameterizedQualifiedTypeReference;
@@ -36,9 +37,11 @@ import org.eclipse.jdt.internal.codeassist.impl.AssistSourceType;
import org.eclipse.jdt.internal.codeassist.impl.AssistTypeParameter;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.core.AnnotatableInfo;
@@ -91,14 +94,33 @@ public class CompletionUnitStructureRequestor extends CompilationUnitStructureRe
protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) {
String fieldName = JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name));
AssistSourceField field = new AssistSourceField(parent, fieldName, this.bindingCache, this.newElements);
- if (fieldInfo.node.binding != null) {
- this.bindingCache.put(field, fieldInfo.node.binding);
- this.elementCache.put(fieldInfo.node.binding, field);
+ FieldDeclaration decl = (fieldInfo.node);
+ if (decl.binding != null) {
+ this.bindingCache.put(field, decl.binding);
+ this.elementCache.put(decl.binding, field);
} else {
this.elementWithProblemCache.put(fieldInfo.node, field);
}
return field;
}
+ @Override
+ protected SourceField createRecordComponent(JavaElement parent, RecordComponentInfo compInfo) {
+ String compName = JavaModelManager.getJavaModelManager().intern(new String(compInfo.name));
+ SourceField comp = new AssistSourceField(parent, compName, this.bindingCache, this.newElements) {
+ @Override
+ public boolean isRecordComponent() throws JavaModelException {
+ return true;
+ }
+ };
+ RecordComponent decl = (compInfo.node);
+ if (decl.binding != null) {
+ this.bindingCache.put(compName, decl.binding);
+ this.elementCache.put(decl.binding, compName);
+ } else {
+ this.elementWithProblemCache.put(compInfo.node, compName);
+ }
+ return comp;
+ }
@Override
protected ImportContainer createImportContainer(ICompilationUnit parent) {
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 c1739db81..3bf82ba8a 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
@@ -706,6 +706,10 @@ void setSourceStart(int sourceStart);
/** @since 3.5 */
int ComparingIdentical = Internal + 211;
+ /** @since 3.22
+ * @noreference preview feature error */
+ int UnsafeCast = TypeRelated + 212;
+
int UnmatchedBracket = Syntax + Internal + 220;
int NoFieldOnBaseType = FieldRelated + 221;
int InvalidExpressionAsStatement = Syntax + Internal + 222;
@@ -1197,6 +1201,9 @@ void setSourceStart(int sourceStart);
int JavadocUnexpectedText = Javadoc + Internal + 518;
/** @since 3.1 */
int JavadocInvalidParamTagName = Javadoc + Internal + 519;
+
+ // see also JavadocNotAccessibleType below
+
/*
* IDs for module errors in Javadoc
*/
@@ -2090,6 +2097,10 @@ void setSourceStart(int sourceStart);
/** @since 3.14 */
int UnstableAutoModuleName = ModuleRelated + 1461;
+ // doc variant of an above constant:
+ /** @since 3.22 */
+ int JavadocNotAccessibleType = Javadoc + NotAccessibleType;
+
/** @since 3.13 */
int RedundantNullDefaultAnnotationLocal = Internal + 1062;
@@ -2699,6 +2710,8 @@ void setSourceStart(int sourceStart);
int SwitchExpressionsBreakOutOfSwitchExpression = Syntax + 1722;
/** @since 3.22 */
int SwitchExpressionsContinueOutOfSwitchExpression = Syntax + 1723;
+ /** @since 3.22 */
+ int SwitchExpressionsReturnWithinSwitchExpression = Syntax + 1724;
/* records - begin */
/** @since 3.22
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
index f2deed497..0c4a68951 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
@@ -534,6 +534,9 @@ public abstract class ASTVisitor {
public void endVisit(SwitchExpression switchExpression, BlockScope scope) {
// do nothing by default
}
+ public void endVisit(RecordComponent recordComponent, BlockScope scope) {
+ // do nothing by default, keep traversing
+ }
//{ObjectTeams: visit new ast nodes:
public void endVisit(LiftingTypeReference liftingTypeReference, BlockScope scope) {
@@ -1076,6 +1079,9 @@ public abstract class ASTVisitor {
public boolean visit(SwitchExpression switchExpression, BlockScope blockScope) {
return true; // do nothing by default, keep traversing
}
+ public boolean visit(RecordComponent recordComponent, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
//{ObjectTeams: visit new ast nodes:
public boolean visit(LiftingTypeReference liftingTypeReference, BlockScope scope) {
return true; // do nothing by default, keep traversing
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 178472e9f..329c8015f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -68,6 +68,7 @@ import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.Receiver;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
@@ -104,6 +105,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.RecordComponentBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
@@ -610,26 +612,18 @@ public class ClassFile implements TypeConstants, TypeIds {
}
}
- private int addComponentAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
- // almost mirrors with field_info
- // TODO: watch out for spec changes once preview to standard of records
- return addFieldAttributes(fieldBinding, fieldAttributeOffset, true);
- }
private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
- return addFieldAttributes(fieldBinding, fieldAttributeOffset, false);
- }
- private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset, boolean isComponent) {
int attributesNumber = 0;
// 4.7.2 only static constant fields get a ConstantAttribute
// Generate the constantValueAttribute
Constant fieldConstant = fieldBinding.constant();
- if (fieldConstant != Constant.NotAConstant && !isComponent){
+ if (fieldConstant != Constant.NotAConstant){
attributesNumber += generateConstantValueAttribute(fieldConstant, fieldBinding, fieldAttributeOffset);
}
- if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic() && !isComponent) {
+ if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
attributesNumber += generateSyntheticAttribute();
}
- if (fieldBinding.isDeprecated() && !isComponent) {
+ if (fieldBinding.isDeprecated()) {
attributesNumber += generateDeprecatedAttribute();
}
// add signature attribute
@@ -640,42 +634,50 @@ public class ClassFile implements TypeConstants, TypeIds {
if (this.targetJDK >= ClassFileConstants.JDK1_4) {
FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
if (fieldDeclaration != null) {
- Annotation[] annotations = fieldDeclaration.annotations;
- if (annotations != null) {
- long allowedTargets = TagBits.AnnotationForField | (fieldDeclaration.isARecordComponent ?
- TagBits.AnnotationForRecordComponent : 0);
- attributesNumber += generateRuntimeAnnotations(annotations, allowedTargets);
- }
-
- if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
- List allTypeAnnotationContexts = new ArrayList();
- if (annotations != null && (fieldDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) {
- fieldDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+ try {
+ if (fieldDeclaration.isARecordComponent) {
+ long rcMask = TagBits.AnnotationForField | TagBits.AnnotationForTypeUse;
+ fieldDeclaration.annotations = getAnnotationsFromAssociatedRecordComponent(fieldBinding.declaringClass, fieldBinding.name, rcMask);
}
- int invisibleTypeAnnotationsCounter = 0;
- int visibleTypeAnnotationsCounter = 0;
- TypeReference fieldType = fieldDeclaration.type;
- if (fieldType != null && ((fieldType.bits & ASTNode.HasTypeAnnotations) != 0)) {
- fieldType.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+ Annotation[] annotations = fieldDeclaration.annotations;
+ if (annotations != null) {
+ attributesNumber += generateRuntimeAnnotations(annotations, TagBits.AnnotationForField);
}
- int size = allTypeAnnotationContexts.size();
- if (size != 0) {
- AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
- allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
- for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) {
- AnnotationContext annotationContext = allTypeAnnotationContextsArray[i];
- if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
- invisibleTypeAnnotationsCounter++;
- allTypeAnnotationContexts.add(annotationContext);
- } else {
- visibleTypeAnnotationsCounter++;
- allTypeAnnotationContexts.add(annotationContext);
+
+ if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+ List allTypeAnnotationContexts = new ArrayList();
+ if (annotations != null && (fieldDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) {
+ fieldDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+ }
+ int invisibleTypeAnnotationsCounter = 0;
+ int visibleTypeAnnotationsCounter = 0;
+ TypeReference fieldType = fieldDeclaration.type;
+ if (fieldType != null && ((fieldType.bits & ASTNode.HasTypeAnnotations) != 0)) {
+ fieldType.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+ }
+ int size = allTypeAnnotationContexts.size();
+ if (size != 0) {
+ AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
+ allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
+ for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) {
+ AnnotationContext annotationContext = allTypeAnnotationContextsArray[i];
+ if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+ invisibleTypeAnnotationsCounter++;
+ allTypeAnnotationContexts.add(annotationContext);
+ } else {
+ visibleTypeAnnotationsCounter++;
+ allTypeAnnotationContexts.add(annotationContext);
+ }
}
+ attributesNumber += generateRuntimeTypeAnnotations(
+ allTypeAnnotationContextsArray,
+ visibleTypeAnnotationsCounter,
+ invisibleTypeAnnotationsCounter);
}
- attributesNumber += generateRuntimeTypeAnnotations(
- allTypeAnnotationContextsArray,
- visibleTypeAnnotationsCounter,
- invisibleTypeAnnotationsCounter);
+ }
+ } finally {
+ if (fieldDeclaration.isARecordComponent) {
+ fieldDeclaration.annotations = null;
}
}
}
@@ -685,16 +687,76 @@ public class ClassFile implements TypeConstants, TypeIds {
}
return attributesNumber;
}
+ private Annotation[] getAnnotationsFromAssociatedRecordComponent(ReferenceBinding declaringClass,
+ char[] name, long rcMask) {
+ if (declaringClass instanceof SourceTypeBinding) {
+ SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) declaringClass;
+ RecordComponentBinding rcb = sourceTypeBinding.getRecordComponent(name);
+ if (rcb != null) {
+ RecordComponent recordComponent = rcb.sourceRecordComponent();
+ assert recordComponent != null;
+ return ASTNode.getRelevantAnnotations(recordComponent.annotations, rcMask, null);
+ }
+ }
+ return null;
+ }
+ private int addComponentAttributes(RecordComponentBinding recordComponentBinding, int componetAttributeOffset) {
+ // See JVMS 14 Table 4.7-C - Record Preview for allowed attributes
+ int attributesNumber = 0;
+ // add signature attribute
+ char[] genericSignature = recordComponentBinding.genericSignature();
+ if (genericSignature != null) {
+ attributesNumber += generateSignatureAttribute(genericSignature);
+ }
+ RecordComponent recordComponent = recordComponentBinding.sourceRecordComponent();
+ if (recordComponent != null) {
+ Annotation[] annotations = recordComponent.annotations;
+ if (annotations != null) {
+ attributesNumber += generateRuntimeAnnotations(annotations, TagBits.AnnotationForRecordComponent);
+ }
- /**
- * INTERNAL USE-ONLY
- * This methods generates the bytes for the given record component given by field binding
- * @param fieldBinding the given field binding of the record component
- */
- private void addComponentInfo(FieldBinding fieldBinding) {
+ if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+ List allTypeAnnotationContexts = new ArrayList();
+ if (annotations != null && (recordComponent.bits & ASTNode.HasTypeAnnotations) != 0) {
+ recordComponent.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts);
+ }
+ int invisibleTypeAnnotationsCounter = 0;
+ int visibleTypeAnnotationsCounter = 0;
+ TypeReference recordComponentType = recordComponent.type;
+ if (recordComponentType != null && ((recordComponentType.bits & ASTNode.HasTypeAnnotations) != 0)) {
+ recordComponentType.getAllAnnotationContexts(AnnotationTargetTypeConstants.RECORD_COMPONENT, allTypeAnnotationContexts);
+ }
+ int size = allTypeAnnotationContexts.size();
+ if (size != 0) {
+ AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size];
+ allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray);
+ for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) {
+ AnnotationContext annotationContext = allTypeAnnotationContextsArray[i];
+ if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) {
+ invisibleTypeAnnotationsCounter++;
+ allTypeAnnotationContexts.add(annotationContext);
+ } else {
+ visibleTypeAnnotationsCounter++;
+ allTypeAnnotationContexts.add(annotationContext);
+ }
+ }
+ attributesNumber += generateRuntimeTypeAnnotations(
+ allTypeAnnotationContextsArray,
+ visibleTypeAnnotationsCounter,
+ invisibleTypeAnnotationsCounter);
+ }
+ }
+ }
+ if ((recordComponentBinding.tagBits & TagBits.HasMissingType) != 0) {
+ this.missingTypes = recordComponentBinding.type.collectMissingTypes(this.missingTypes);
+ }
+ return attributesNumber;
+ }
+
+ private void addComponentInfo(RecordComponentBinding recordComponentBinding) {
// check that there is enough space to write all the bytes for the field info corresponding
// to the @fieldBinding sans accessflags for component
- /* component_info {
+ /* record_component_info {
* u2 name_index;
* u2 descriptor_index;
* u2 attributes_count;
@@ -704,24 +766,25 @@ public class ClassFile implements TypeConstants, TypeIds {
resizeContents(6);
}
// Now we can generate all entries into the byte array
- int nameIndex = this.constantPool.literalIndex(fieldBinding.name);
+ int nameIndex = this.constantPool.literalIndex(recordComponentBinding.name);
this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8);
this.contents[this.contentsOffset++] = (byte) nameIndex;
// Then the descriptorIndex
- int descriptorIndex = this.constantPool.literalIndex(fieldBinding.type);
+ int descriptorIndex = this.constantPool.literalIndex(recordComponentBinding.type);
this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[this.contentsOffset++] = (byte) descriptorIndex;
int componentAttributeOffset = this.contentsOffset;
int attributeNumber = 0;
// leave some space for the number of attributes
this.contentsOffset += 2;
- attributeNumber += addComponentAttributes(fieldBinding, componentAttributeOffset);
+ attributeNumber += addComponentAttributes(recordComponentBinding, componentAttributeOffset);
if (this.contentsOffset + 2 >= this.contents.length) {
resizeContents(2);
}
this.contents[componentAttributeOffset++] = (byte) (attributeNumber >> 8);
this.contents[componentAttributeOffset] = (byte) attributeNumber;
}
+
/**
* INTERNAL USE-ONLY
* This methods generates the bytes for the given field binding
@@ -2955,7 +3018,7 @@ public class ClassFile implements TypeConstants, TypeIds {
if (record == null || !record.isRecord())
return 0;
int localContentsOffset = this.contentsOffset;
- FieldBinding[] recordComponents = this.referenceBinding.getRecordComponents();
+ RecordComponentBinding[] recordComponents = this.referenceBinding.components();
if (recordComponents == null)
return 0;
// could be an empty record also, account for zero components as well.
@@ -3834,7 +3897,7 @@ public class ClassFile implements TypeConstants, TypeIds {
assert type instanceof SourceTypeBinding;
SourceTypeBinding sourceType = (SourceTypeBinding) type;
- FieldBinding[] recordComponents = sourceType.getRecordComponents();
+ FieldBinding[] recordComponents = sourceType.getImplicitComponentFields();
int numArgs = 2 + recordComponents.length;
this.contents[numArgsLocation++] = (byte) (numArgs >> 8);
@@ -4171,6 +4234,17 @@ public class ClassFile implements TypeConstants, TypeIds {
SyntheticMethodBinding syntheticMethod = (SyntheticMethodBinding) methodBinding;
if (syntheticMethod.purpose == SyntheticMethodBinding.SuperMethodAccess && CharOperation.equals(syntheticMethod.selector, syntheticMethod.targetMethod.selector))
methodDeclaration = ((SyntheticMethodBinding)methodBinding).targetMethod.sourceMethod();
+ if (syntheticMethod.recordComponentBinding != null) {
+ assert methodDeclaration == null;
+ long rcMask = TagBits.AnnotationForMethod | TagBits.AnnotationForTypeUse;
+ // record component (field) accessor method
+ Annotation[] annotations = getAnnotationsFromAssociatedRecordComponent(methodBinding.declaringClass,
+ methodBinding.selector, rcMask);
+ if (annotations != null) {
+ assert !methodBinding.isConstructor();
+ attributesNumber += generateRuntimeAnnotations(annotations, rcMask);
+ }
+ }
}
if (methodDeclaration != null) {
Annotation[] annotations = methodDeclaration.annotations;
@@ -4180,6 +4254,7 @@ public class ClassFile implements TypeConstants, TypeIds {
if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
Argument[] arguments = methodDeclaration.arguments;
if (arguments != null) {
+ propagateRecordComponentArguments(methodDeclaration);
attributesNumber += generateRuntimeAnnotationsForParameters(arguments);
}
}
@@ -4208,6 +4283,27 @@ public class ClassFile implements TypeConstants, TypeIds {
}
return attributesNumber;
}
+ private void propagateRecordComponentArguments(AbstractMethodDeclaration methodDeclaration) {
+ if ((methodDeclaration.bits & (ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit)) == 0)
+ return;
+ ReferenceBinding declaringClass = methodDeclaration.binding.declaringClass;
+ if (declaringClass instanceof SourceTypeBinding) {
+ assert declaringClass.isRecord();
+ RecordComponentBinding[] rcbs = ((SourceTypeBinding) declaringClass).components();
+ Argument[] arguments = methodDeclaration.arguments;
+ for (int i = 0, length = rcbs.length; i < length; i++) {
+ RecordComponentBinding rcb = rcbs[i];
+ RecordComponent recordComponent = rcb.sourceRecordComponent();
+ if ((recordComponent.bits & ASTNode.HasTypeAnnotations) != 0) {
+ methodDeclaration.bits |= ASTNode.HasTypeAnnotations;
+ arguments[i].bits |= ASTNode.HasTypeAnnotations;
+ }
+ long rcMask = TagBits.AnnotationForParameter | TagBits.AnnotationForTypeUse;
+ arguments[i].annotations = ASTNode.getRelevantAnnotations(recordComponent.annotations, rcMask, null);
+ }
+ }
+ }
+
public int generateMethodInfoAttributes(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
int attributesNumber = generateMethodInfoAttributes(methodBinding);
int attributeOffset = this.contentsOffset;
@@ -5811,6 +5907,9 @@ public class ClassFile implements TypeConstants, TypeIds {
if ((binding.tagBits & TagBits.HasMissingType) != 0) {
continue;
}
+ if (this.contentsOffset + 4 >= this.contents.length) {
+ resizeContents(4); // 2 bytes this iteration plus 2 bytes after the loop
+ }
interfaceCounter++;
int interfaceIndex = this.constantPool.literalIndexForType(binding);
this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8);
@@ -6291,7 +6390,8 @@ public class ClassFile implements TypeConstants, TypeIds {
TypeBinding type = (TypeBinding) scope.getTypeOrPackage(CharOperation.splitOn('/', typeName));
if (!type.isValidBinding()) {
ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) type;
- if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0) {
+ if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0
+ || (problemReferenceBinding.problemId() & ProblemReasons.NotVisible) != 0) {
type = problemReferenceBinding.closestMatch();
} else if ((problemReferenceBinding.problemId() & ProblemReasons.NotFound) != 0 && this.innerClassesBindings != null) {
// check local inner types to see if this is a anonymous type
@@ -6311,7 +6411,8 @@ public class ClassFile implements TypeConstants, TypeIds {
TypeBinding type = (TypeBinding) scope.getTypeOrPackage(CharOperation.splitOn('/', typeName));
if (!type.isValidBinding()) {
ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) type;
- if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0) {
+ if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0
+ || (problemReferenceBinding.problemId() & ProblemReasons.NotVisible) != 0) {
type = problemReferenceBinding.closestMatch();
} else if ((problemReferenceBinding.problemId() & ProblemReasons.NotFound) != 0 && this.innerClassesBindings != null) {
// check local inner types to see if this is a anonymous type
@@ -6341,7 +6442,8 @@ public class ClassFile implements TypeConstants, TypeIds {
TypeBinding type = (TypeBinding) scope.getTypeOrPackage(CharOperation.splitOn('/', typeName));
if (!type.isValidBinding()) {
ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) type;
- if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0) {
+ if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0
+ || (problemReferenceBinding.problemId() & ProblemReasons.NotVisible) != 0) {
type = problemReferenceBinding.closestMatch();
}
}
@@ -6400,7 +6502,8 @@ public class ClassFile implements TypeConstants, TypeIds {
CharOperation.splitOn('/', elementTypeClassName));
if (!type.isValidBinding()) {
ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) type;
- if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0) {
+ if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0
+ || (problemReferenceBinding.problemId() & ProblemReasons.NotVisible) != 0) {
type = problemReferenceBinding.closestMatch();
} else if ((problemReferenceBinding.problemId() & ProblemReasons.NotFound) != 0 && this.innerClassesBindings != null) {
// check local inner types to see if this is a anonymous type
@@ -6420,7 +6523,8 @@ public class ClassFile implements TypeConstants, TypeIds {
CharOperation.splitOn('/', typeConstantPoolName));
if (!type.isValidBinding()) {
ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) type;
- if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0) {
+ if ((problemReferenceBinding.problemId() & ProblemReasons.InternalNameProvided) != 0
+ || (problemReferenceBinding.problemId() & ProblemReasons.NotVisible) != 0) {
type = problemReferenceBinding.closestMatch();
} else if ((problemReferenceBinding.problemId() & ProblemReasons.NotFound) != 0 && this.innerClassesBindings != null) {
// check local inner types to see if this is a anonymous type
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 695ef2fe0..4a51f56b2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -716,6 +716,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
reset();
this.annotationProcessorStartIndex = 0;
this.stats.endTime = System.currentTimeMillis();
+ this.stats.overallTime += this.stats.endTime - this.stats.startTime;
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 526491404..77c1f91ff 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -50,8 +50,10 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
@@ -81,14 +83,14 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)| name ref (yield result value)
public final static int Bit6 = 0x20; // depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference)
- public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
- public final static int Bit8 = 0x80; // depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
+ public final static int Bit7 = 0x40; // depth (name ref, msg) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
+ public final static int Bit8 = 0x80; // depth (name ref, msg) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
public final static int Bit9 = 0x100; // depth (name ref, msg) | operator (operator) | is local type (type decl) | isThenStatementUnreachable (if statement) | can be static
public final static int Bit10= 0x200; // depth (name ref, msg) | operator (operator) | is anonymous type (type decl) | is implicit constructor (constructor)
public final static int Bit11 = 0x400; // depth (name ref, msg) | operator (operator) | is member type (type decl)
public final static int Bit12 = 0x800; // depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
- public final static int Bit13 = 0x1000; // depth (name ref, msg) | is secondary type (type decl)
- public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
+ public final static int Bit13 = 0x1000; // depth (name ref, msg) | operator (operator) | is secondary type (type decl)
+ public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | operator (operator) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
public final static int Bit15 = 0x4000; // is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement) | superAccess (javadoc allocation expression/javadoc message send/javadoc return statement)
public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg)
public final static int Bit17 = 0x10000; // compound assigned (reference lhs) | unchecked (msg, alloc, explicit constr call)
@@ -146,8 +148,8 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
// for operators
public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4;
- public static final int OperatorSHIFT = 6; // Bit7 -> Bit12
- public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID
+ public static final int OperatorSHIFT = 8; // Bit9 -> Bit14
+ public static final int OperatorMASK = Bit9|Bit10|Bit11|Bit12|Bit13|Bit14; // 6 bits for operator ID
// for binary expressions
public static final int IsReturnedValue = Bit5;
@@ -158,8 +160,8 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public static final int GenerateCheckcast = Bit7;
public static final int UnsafeCast = Bit8;
- // for name references
- public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3;
+ // for name references (Java 14 addition - Records preview - Bit18)
+ public static final int RestrictiveFlagMASK = Bit1 | Bit2 | Bit3 | Bit18 ;
// for local decls
public static final int IsTypeElided = Bit2; // type elided lambda argument.
@@ -168,7 +170,6 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public static final int IsForeachElementVariable = Bit5;
public static final int ShadowsOuterLocal = Bit22;
public static final int IsAdditionalDeclarator = Bit23;
- public static final int IsRecordComponent = Bit30;
// for name refs or local decls
public static final int FirstAssignmentToLocal = Bit4;
@@ -343,6 +344,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public static final int HasFunctionalInterfaceTypes = ASTNode.Bit22;
public static final Argument [] NO_ARGUMENTS = new Argument [0];
+ public static final RecordComponent [] NO_RECORD_COMPONENTS = new RecordComponent [0];
public ASTNode() {
@@ -862,6 +864,15 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
field.setAnnotations(annotations, false);
}
break;
+ case Binding.RECORD_COMPONENT :
+ RecordComponentBinding rcb = (RecordComponentBinding) recipient;
+ if ((rcb.tagBits & TagBits.AnnotationResolved) != 0) return annotations;
+ rcb.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
+ if (length > 0) {
+ annotations = new AnnotationBinding[length];
+ rcb.setAnnotations(annotations, false);
+ }
+ break;
case Binding.LOCAL :
LocalVariableBinding local = (LocalVariableBinding) recipient;
if ((local.tagBits & TagBits.AnnotationResolved) != 0) return annotations;
@@ -916,9 +927,21 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
}
break;
+ case Binding.RECORD_COMPONENT :
+ RecordComponentBinding recordComponentBinding = (RecordComponentBinding) recipient;
+ recordComponentBinding.tagBits = ((RecordComponentBinding) annotationRecipient).tagBits;
+ if (annotations != null) {
+ // need to fill the instances array
+ for (int j = 0; j < length; j++) {
+ Annotation annot = sourceAnnotations[j];
+ annotations[j] = annot.getCompilerAnnotation();
+ }
+ }
+ break;
case Binding.LOCAL :
LocalVariableBinding local = (LocalVariableBinding) recipient;
- long otherLocalTagBits = ((LocalVariableBinding) annotationRecipient).tagBits;
+ // Note for JDK>=14, this could be LVB or RCB, hence typecasting to VB
+ long otherLocalTagBits = ((VariableBinding) annotationRecipient).tagBits;
local.tagBits = otherLocalTagBits;
if ((otherLocalTagBits & TagBits.AnnotationSuppressWarnings) == 0) {
// None of the annotations is a SuppressWarnings annotation
@@ -950,6 +973,10 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
}
}
+ // Note: This is the argument of an implicit canonical constructor of a record declaration
+ // copy the se8 annotations.
+ if (annotationRecipient instanceof RecordComponentBinding && copySE8AnnotationsToType)
+ copySE8AnnotationsToType(scope, recipient, sourceAnnotations, false);
break;
}
return annotations;
@@ -1112,6 +1139,9 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
MethodBinding method = (MethodBinding) recipient;
recipientTargetMask = method.isConstructor() ? TagBits.AnnotationForConstructor : TagBits.AnnotationForMethod;
break;
+ case Binding.RECORD_COMPONENT:
+ recipientTargetMask = TagBits.AnnotationForRecordComponent;
+ break;
default:
return;
}
@@ -1177,6 +1207,18 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
}
break;
+ case Binding.RECORD_COMPONENT:
+ RecordComponentBinding recordComponentBinding = (RecordComponentBinding) recipient;
+ RecordComponent recordComponent = recordComponentBinding.sourceRecordComponent();
+ if (Annotation.isTypeUseCompatible(recordComponent.type, scope)) { // discard hybrid annotations on name qualified types.
+ recordComponent.bits |= HasTypeAnnotations;
+ recordComponent.type.bits |= HasTypeAnnotations;
+ recordComponentBinding.type = mergeAnnotationsIntoType(scope, se8Annotations, se8nullBits, se8NullAnnotation, recordComponent.type, recordComponentBinding.type);
+ if(scope.environment().usesNullTypeAnnotations()) { //TODO Bug 562478
+ recordComponentBinding.tagBits &= ~(se8nullBits);
+ }
+ }
+ break;
case Binding.METHOD:
MethodBinding method = (MethodBinding) recipient;
if (!method.isConstructor()) {
@@ -1213,6 +1255,60 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
}
+ public static Annotation[] getRelevantAnnotations(Annotation[] annotations, long rcMask,
+ List<AnnotationBinding> relevantAnnotations) {
+
+ if (annotations == null || annotations.length == 0)
+ return null;
+
+ List<Annotation> filteredAnnotations = new ArrayList<>();
+ for (Annotation annot : annotations) {
+ AnnotationBinding annotationBinding = annot.getCompilerAnnotation();
+ if (annotationBinding == null) continue;
+ final ReferenceBinding annotationType = annotationBinding.getAnnotationType();
+ long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
+ if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0 || (metaTagBits & rcMask) != 0) {
+ filteredAnnotations.add(annot);
+ if (relevantAnnotations != null)
+ relevantAnnotations.add(annotationBinding);
+ }
+ }
+ return filteredAnnotations.toArray(new Annotation[0]);
+ }
+ public static Annotation[] copyRecordComponentAnnotations(Scope scope, Binding recipient, Annotation[] annotations) {
+ if (annotations == null || annotations.length == 0 || recipient == null)
+ return null;
+
+ long recipientTargetMask = 0;
+ switch (recipient.kind()) {
+ case Binding.LOCAL:
+ assert recipient.isParameter(); // only for implicit canonical constructor arguments
+ recipientTargetMask = recipient.isParameter() ? TagBits.AnnotationForParameter : TagBits.AnnotationForLocalVariable;
+ break;
+ case Binding.FIELD:
+ recipientTargetMask = TagBits.AnnotationForField;
+ break;
+ case Binding.METHOD:
+ MethodBinding method = (MethodBinding) recipient;
+ recipientTargetMask = method.isConstructor() ? TagBits.AnnotationForConstructor : TagBits.AnnotationForMethod;
+ break;
+ case Binding.RECORD_COMPONENT:
+ // Use it on record component itself to filter out non-record component annotations.
+ recipientTargetMask = TagBits.AnnotationForRecordComponent;
+ break;
+ default:
+ return null;
+ }
+ // TODO: Null Analysis Address via bug 562478?
+
+ recipientTargetMask |= TagBits.AnnotationForTypeUse;
+ List<AnnotationBinding> relevantAnnotations = new ArrayList<>();
+ Annotation[] filteredAnnotations = ASTNode.getRelevantAnnotations(annotations, recipientTargetMask, relevantAnnotations);
+ AnnotationBinding [] recipientAnnotations = relevantAnnotations.toArray(new AnnotationBinding[relevantAnnotations.size()]);
+ recipient.setAnnotations(recipientAnnotations, scope, true /* forceStore*/);// forceStore since we require at codegen
+ return filteredAnnotations;
+ }
+
private static TypeBinding mergeAnnotationsIntoType(BlockScope scope, AnnotationBinding[] se8Annotations, long se8nullBits, Annotation se8NullAnnotation,
TypeReference typeRef, TypeBinding existingType)
{
@@ -1290,6 +1386,10 @@ public static void resolveDeprecatedAnnotations(BlockScope scope, Annotation[] a
LocalVariableBinding local = (LocalVariableBinding) recipient;
if ((local.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
break;
+ case Binding.RECORD_COMPONENT :
+ RecordComponentBinding recordComponentBinding = (RecordComponentBinding) recipient;
+ if ((recordComponentBinding.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
+ break;
default :
return;
}
@@ -1332,6 +1432,10 @@ public static void resolveDeprecatedAnnotations(BlockScope scope, Annotation[] a
LocalVariableBinding local = (LocalVariableBinding) recipient;
local.tagBits |= deprecationTagBits;
return;
+ case Binding.RECORD_COMPONENT :
+ RecordComponentBinding recordComponentBinding = (RecordComponentBinding) recipient;
+ recordComponentBinding.tagBits |= deprecationTagBits;
+ return;
default:
return;
}
@@ -1362,6 +1466,10 @@ public static void resolveDeprecatedAnnotations(BlockScope scope, Annotation[] a
LocalVariableBinding local = (LocalVariableBinding) recipient;
local.tagBits |= TagBits.DeprecatedAnnotationResolved;
return;
+ case Binding.RECORD_COMPONENT :
+ RecordComponentBinding recordComponentBinding = (RecordComponentBinding) recipient;
+ recordComponentBinding.tagBits |= TagBits.DeprecatedAnnotationResolved;
+ return;
default:
return;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 415c8f0f6..5244d63b0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -303,6 +303,10 @@ public abstract class AbstractMethodDeclaration
paramAnnotations[i] = Binding.NO_ANNOTATIONS;
}
}
+ if (paramAnnotations == null) {
+ paramAnnotations = getPropagatedRecordComponentAnnotations();
+ }
+
if (paramAnnotations != null)
this.binding.setParameterAnnotations(paramAnnotations);
}
@@ -315,6 +319,10 @@ public abstract class AbstractMethodDeclaration
}
}
+ protected AnnotationBinding[][] getPropagatedRecordComponentAnnotations() {
+ return null;
+ }
+
/**
* Record the thrown exception type bindings in the corresponding type references.
*/
@@ -386,6 +394,9 @@ public abstract class AbstractMethodDeclaration
}
}
}
+ if (methodArguments[i].duplicateCheckObligation != null) {
+ methodArguments[i].duplicateCheckObligation.accept(flowInfo);
+ }
// tag parameters as being set:
flowInfo.markAsDefinitelyAssigned(methodArguments[i].binding);
}
@@ -729,7 +740,7 @@ public abstract class AbstractMethodDeclaration
return (this.modifiers & ClassFileConstants.AccNative) != 0;
}
- public Argument getRecordComponent() {
+ public RecordComponent getRecordComponent() {
return null;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
index 0f92005e1..d5749212f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -57,8 +57,9 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
public static final int LOCAL_VARIABLE = 4;
public static final int PARAMETER = 5;
public static final int TYPE_PARAMETER = 6;
+ public static final int RECORD_COMPONENT = 7; // record
//{ObjectTeams: new kind:
- public static final int TYPE_VALUE_PARAMETER = 7;
+ public static final int TYPE_VALUE_PARAMETER = 8;
// SH}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index 70ae15ff7..7fceaa96e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -1051,6 +1051,33 @@ public abstract class Annotation extends Expression {
}
break;
// SH}
+ case Binding.RECORD_COMPONENT :
+ RecordComponentBinding sourceRecordComponent = (RecordComponentBinding) this.recipient;
+ sourceRecordComponent.tagBits |= tagBits;
+ if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) {
+ RecordComponent recordComponent = sourceRecordComponent.sourceRecordComponent();
+ recordSuppressWarnings(scope, recordComponent.declarationSourceStart, recordComponent.declarationSourceEnd, compilerOptions.suppressWarnings);
+ }
+// TODO: BUG 562478 Consideration - to uncomment/modify the following:
+// if (defaultNullness != 0) {
+// RecordComponent recordComponent = sourceRecordComponent.sourceRecordComponent();
+// // test merged value of defaultNullness contributed by this annotation and previous annotations on same target is redundant w.r.t. containing value
+// // (for targets other than fields the resulting value is tested only once after processing all annotations, but this is hard to do for fields)
+// Binding target = scope.parent.checkRedundantDefaultNullness(
+// defaultNullness | scope.localNonNullByDefaultValue(recordComponent.sourceStart),
+// recordComponent.sourceStart);
+// scope.recordNonNullByDefault(recordComponent.binding, defaultNullness, this, recordComponent.declarationSourceStart, recordComponent.declarationSourceEnd);
+// if (target != null) {
+// scope.problemReporter().nullDefaultAnnotationIsRedundant(recordComponent, new Annotation[]{this}, target);
+// }
+// }
+// // fields don't yet have their type resolved, in 1.8 null annotations
+// // will be transfered from the field to its type during STB.resolveTypeFor().
+// if ((sourceRecordComponent.tagBits & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) {
+// scope.problemReporter().contradictoryNullAnnotations(this);
+// sourceRecordComponent.tagBits &= ~TagBits.AnnotationNullMASK; // avoid secondary problems
+// }
+ break;
case Binding.FIELD :
FieldBinding sourceField = (FieldBinding) this.recipient;
sourceField.tagBits |= tagBits;
@@ -1236,6 +1263,20 @@ public abstract class Annotation extends Expression {
}
}
break;
+ case Binding.RECORD_COMPONENT :
+ /* JLS 14 9.7.4 Record Preview
+ * It is a compile-time error if an annotation of type T is syntactically a modifier for:
+ * ...
+ * a record component but T is not applicable to record component declarations, field declarations,
+ * method declarations, or type contexts.
+ */
+ long recordComponentMask = TagBits.AnnotationForRecordComponent |
+ TagBits.AnnotationForField |
+ TagBits.AnnotationForMethod |
+ TagBits.AnnotationForParameter | // See JLS 14 8.10.4 Records Preview - TODO revisit in J15
+ TagBits.AnnotationForTypeUse;
+ return (metaTagBits & recordComponentMask) != 0 ? AnnotationTargetAllowed.YES :
+ AnnotationTargetAllowed.NO;
case Binding.LOCAL :
LocalVariableBinding localVariableBinding = (LocalVariableBinding) recipient;
if ((localVariableBinding.tagBits & TagBits.IsArgument) != 0) {
@@ -1302,6 +1343,7 @@ public abstract class Annotation extends Expression {
case Binding.METHOD :
case Binding.FIELD :
case Binding.LOCAL :
+ case Binding.RECORD_COMPONENT :
scope.problemReporter().invalidUsageOfTypeAnnotations(annotation);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index 634931b4f..e89679e43 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -105,10 +105,14 @@ public class Argument extends LocalDeclaration {
}
}
if ((this.binding.tagBits & TagBits.AnnotationResolved) == 0) {
- resolveAnnotations(scope, this.annotations, this.binding, true);
- if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8) {
- Annotation.isTypeUseCompatible(this.type, scope, this.annotations);
- scope.validateNullAnnotation(this.binding.tagBits, this.type, this.annotations);
+ Annotation[] annots = this.annotations;
+ long sourceLevel = scope.compilerOptions().sourceLevel;
+ if (sourceLevel >= ClassFileConstants.JDK14 && annots == null)
+ annots = getCorrespondingRecordComponentAnnotationsIfApplicable(scope.referenceMethod());
+ resolveAnnotations(scope, annots, this.binding, true);
+ if (sourceLevel >= ClassFileConstants.JDK1_8) {
+ Annotation.isTypeUseCompatible(this.type, scope, annots);
+ scope.validateNullAnnotation(this.binding.tagBits, this.type, annots);
}
//{ObjectTeams: LTR needs to do more work:
if (this.type instanceof LiftingTypeReference)
@@ -119,6 +123,23 @@ public class Argument extends LocalDeclaration {
return this.binding.type; // might have been updated during resolveAnnotations (for typeAnnotations)
}
+ private Annotation[] getCorrespondingRecordComponentAnnotationsIfApplicable(AbstractMethodDeclaration methodDecl) {
+ if (methodDecl != null && methodDecl.isConstructor() &&
+ ((methodDecl.bits & (ASTNode.IsCanonicalConstructor )) != 0 &&
+ ((methodDecl.bits & (ASTNode.IsImplicit)) != 0))) {
+ MethodBinding methodBinding = methodDecl.binding;
+ ReferenceBinding referenceBinding = methodBinding== null ? null : methodBinding.declaringClass;
+ if (referenceBinding instanceof SourceTypeBinding) {
+ SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) referenceBinding;
+ assert (sourceTypeBinding.isRecord());
+ sourceTypeBinding.components();
+ RecordComponentBinding recordComponentBinding = sourceTypeBinding.getRecordComponent(this.name);
+ RecordComponent recordComponent = recordComponentBinding.sourceRecordComponent();
+ return recordComponent.annotations;
+ }
+ }
+ return null;
+ }
public TypeBinding bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
TypeBinding newTypeBinding = createBinding(scope, typeBinding); // basically a no-op if createBinding() was called before
@@ -142,9 +163,17 @@ public class Argument extends LocalDeclaration {
final boolean localExists = existingVariable instanceof LocalVariableBinding;
if (localExists && this.hiddenVariableDepth == 0) {
if ((this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope()) {
- scope.problemReporter().lambdaRedeclaresArgument(this);
- } else if ((this.bits & ASTNode.IsRecordComponent) != 0) {
- scope.problemReporter().recordDuplicateComponent(this);
+ if ((((LocalVariableBinding) existingVariable).modifiers & ExtraCompilerModifiers.AccPatternVariable) != 0) {
+ this.duplicateCheckObligation = (flowInfo) -> {
+ if (flowInfo.isDefinitelyAssigned((LocalVariableBinding) existingVariable)) {
+ scope.problemReporter().lambdaRedeclaresArgument(this);
+ }
+ };
+ } else {
+ scope.problemReporter().lambdaRedeclaresArgument(this);
+ }
+ } else if (scope.referenceContext instanceof CompactConstructorDeclaration) {
+ // skip error reporting - hidden params - already reported in record components
} else {
scope.problemReporter().redefineArgument(this);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index 0b12e08a6..73b346126 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -226,4 +226,17 @@ public boolean completesByContinue() {
int length = this.statements == null ? 0 : this.statements.length;
return length > 0 && this.statements[length - 1].completesByContinue();
}
+
+@Override
+public boolean canCompleteNormally() {
+ int length = this.statements == null ? 0 : this.statements.length;
+ return length == 0 || this.statements[length - 1].canCompleteNormally();
+}
+
+@Override
+public boolean continueCompletes() {
+ int length = this.statements == null ? 0 : this.statements.length;
+ return length > 0 && this.statements[length - 1].continueCompletes();
+}
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
index e12cfc4d6..84467d87f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
@@ -21,6 +21,7 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
public class BreakStatement extends BranchStatement {
+ public boolean isSynthetic;
public BreakStatement(char[] label, int sourceStart, int e) {
super(label, sourceStart, e);
}
@@ -110,4 +111,15 @@ public void traverse(ASTVisitor visitor, BlockScope blockscope) {
public boolean doesNotCompleteNormally() {
return true;
}
+
+@Override
+public boolean canCompleteNormally() {
+ return false;
+}
+
+
+@Override
+protected boolean doNotReportUnreachable() {
+ return this.isSynthetic;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 8d620e00a..3e6c349e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -489,6 +489,12 @@ private static boolean preventsUnlikelyTypeWarning(TypeBinding castedType, TypeB
@Override
public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ return CastExpression.checkUnsafeCast(this, scope, castType, expressionType, match, isNarrowing);
+}
+public static boolean checkUnsafeCast(Expression expression, Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ // In case of expression being a InstanceOfExpression, this.resolvedType is null
+ // hence use the type of RHS of the instanceof operator
+ TypeBinding resolvedType = expression.resolvedType != null ? expression.resolvedType : castType;
//{ObjectTeams: for weakened types use all available source level information:
if (match instanceof WeakenedTypeBinding)
match = ((WeakenedTypeBinding)match).getStrongType();
@@ -496,9 +502,9 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
castType = ((WeakenedTypeBinding)castType).getStrongType();
// SH}
if (TypeBinding.equalsEquals(match, castType)) {
- if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType()) // do not tag as unnecessary when recursing through upper bounds
+ if (!isNarrowing && TypeBinding.equalsEquals(match, resolvedType.leafComponentType()) // do not tag as unnecessary when recursing through upper bounds
&& !(expressionType.isParameterizedType() && expressionType.isProvablyDistinct(castType))) {
- tagAsUnnecessaryCast(scope, castType);
+ expression.tagAsUnnecessaryCast(scope, castType);
}
return true;
}
@@ -513,7 +519,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
case Binding.PARAMETERIZED_TYPE :
if (!castType.isReifiable()) {
if (match == null) { // unrelated types
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
switch (match.kind()) {
@@ -521,7 +527,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
if (isNarrowing) {
// [JLS 5.5] T <: S
if (expressionType.isRawType() || !expressionType.isEquivalentTo(match)) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
// [JLS 5.5] S has no subtype X != T, such that |X| == |T|
@@ -532,7 +538,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
TypeBinding[] castArguments = paramCastType.arguments;
int length = castArguments == null ? 0 : castArguments.length;
if (paramMatch.arguments == null || length > paramMatch.arguments.length) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
} else if ((paramCastType.tagBits & (TagBits.HasDirectWildcard|TagBits.HasTypeVariable)) != 0) {
// verify alternate cast type, substituting different type arguments
nextAlternateArgument: for (int i = 0; i < length; i++) {
@@ -550,7 +556,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
LookupEnvironment environment = scope.environment();
ParameterizedTypeBinding alternateCastType = environment.createParameterizedType((ReferenceBinding)castType.erasure(), alternateArguments, castType.enclosingType());
if (TypeBinding.equalsEquals(alternateCastType.findSuperTypeOriginatingFrom(expressionType), match)) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
break;
}
}
@@ -559,18 +565,18 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
} else {
// [JLS 5.5] T >: S
if (!match.isEquivalentTo(castType)) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
}
break;
case Binding.RAW_TYPE :
- this.bits |= ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType
+ expression.bits |= ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType
return true;
default :
if (isNarrowing){
// match is not parameterized or raw, then any other subtype of match will erase to |T|
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
break;
@@ -580,12 +586,12 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
case Binding.ARRAY_TYPE :
TypeBinding leafType = castType.leafComponentType();
if (isNarrowing && (!leafType.isReifiable() || leafType.isTypeVariable())) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
break;
case Binding.TYPE_PARAMETER :
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
// (disabled) https://bugs.eclipse.org/bugs/show_bug.cgi?id=240807
// case Binding.TYPE :
@@ -595,8 +601,8 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
// }
// break;
}
- if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType())) { // do not tag as unnecessary when recursing through upper bounds
- tagAsUnnecessaryCast(scope, castType);
+ if (!isNarrowing && TypeBinding.equalsEquals(match, resolvedType.leafComponentType())) { // do not tag as unnecessary when recursing through upper bounds
+ expression.tagAsUnnecessaryCast(scope, castType);
}
return true;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index b1cbc4c63..56950343a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -693,6 +693,41 @@ private void internalGenerateCode(ClassScope classScope, ClassFile classFile) {
classFile.completeMethodInfo(this.binding, methodAttributeOffset, attributeNumber);
}
+@Override
+protected AnnotationBinding[][] getPropagatedRecordComponentAnnotations() {
+
+ if ((this.bits & (ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit)) == 0)
+ return null;
+ if (this.binding == null)
+ return null;
+ AnnotationBinding[][] paramAnnotations = null;
+ ReferenceBinding declaringClass = this.binding.declaringClass;
+ if (declaringClass instanceof SourceTypeBinding) {
+ assert declaringClass.isRecord();
+ RecordComponentBinding[] rcbs = ((SourceTypeBinding) declaringClass).components();
+ for (int i = 0, length = rcbs.length; i < length; i++) {
+ RecordComponentBinding rcb = rcbs[i];
+ RecordComponent recordComponent = rcb.sourceRecordComponent();
+ long rcMask = TagBits.AnnotationForParameter | TagBits.AnnotationForTypeUse;
+ List<AnnotationBinding> relevantAnnotationBindings = new ArrayList<>();
+ Annotation[] relevantAnnotations = ASTNode.getRelevantAnnotations(recordComponent.annotations, rcMask, relevantAnnotationBindings);
+ if (relevantAnnotations != null) {
+ if (paramAnnotations == null) {
+ paramAnnotations = new AnnotationBinding[length][];
+ for (int j=0; j<i; j++) {
+ paramAnnotations[j] = Binding.NO_ANNOTATIONS;
+ }
+ }
+ this.binding.tagBits |= TagBits.HasParameterAnnotations;
+ paramAnnotations[i] = relevantAnnotationBindings.toArray(new AnnotationBinding[0]);
+ } else if (paramAnnotations != null) {
+ paramAnnotations[i] = Binding.NO_ANNOTATIONS;
+ }
+ }
+ }
+ return paramAnnotations;
+}
+
//{ObjectTeams: ctors are copied for roles and teams:
@Override
public void maybeRecordByteCode(ClassFile classFile, int methodAttributeOffset) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
index 7161c6e91..b1237e8b4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
@@ -109,8 +109,19 @@ public void traverse(ASTVisitor visitor, BlockScope blockScope) {
public boolean doesNotCompleteNormally() {
return true;
}
+
@Override
public boolean completesByContinue() {
return true;
}
+
+@Override
+public boolean canCompleteNormally() {
+ return false;
+}
+
+@Override
+public boolean continueCompletes() {
+ return true;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index 548bedd3c..3c13922f0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -262,4 +262,28 @@ public boolean doesNotCompleteNormally() {
public boolean completesByContinue() {
return this.action.continuesAtOuterLabel();
}
+
+@Override
+public boolean canCompleteNormally() {
+ Constant cst = this.condition.constant;
+ boolean isConditionTrue = cst == null || cst != Constant.NotAConstant && cst.booleanValue() == true;
+ cst = this.condition.optimizedBooleanConstant();
+ boolean isConditionOptimizedTrue = cst == null ? true : cst != Constant.NotAConstant && cst.booleanValue() == true;
+
+ if (!(isConditionTrue || isConditionOptimizedTrue)) {
+ if (this.action == null || this.action.canCompleteNormally())
+ return true;
+ if (this.action != null && this.action.continueCompletes())
+ return true;
+ }
+ if (this.action != null && this.action.breaksOut(null))
+ return true;
+
+ return false;
+}
+@Override
+public boolean continueCompletes() {
+ return this.action.continuesAtOuterLabel();
+}
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index cfaacd7c0..8c99c38f2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -475,4 +475,23 @@ public class ForStatement extends Statement {
public boolean completesByContinue() {
return this.action.continuesAtOuterLabel();
}
+ @Override
+ public boolean canCompleteNormally() {
+ Constant cst = this.condition == null ? null : this.condition.constant;
+ boolean isConditionTrue = cst == null || cst != Constant.NotAConstant && cst.booleanValue() == true;
+ cst = this.condition == null ? null : this.condition.optimizedBooleanConstant();
+ boolean isConditionOptimizedTrue = cst == null ? true : cst != Constant.NotAConstant && cst.booleanValue() == true;
+
+ if (!(isConditionTrue || isConditionOptimizedTrue))
+ return true;
+ if (this.action != null && this.action.breaksOut(null))
+ return true;
+ return false;
+ }
+
+ @Override
+ public boolean continueCompletes() {
+ return this.action.continuesAtOuterLabel();
+ }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index 8e9dd654d..12a3932e3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -732,4 +732,10 @@ public class ForeachStatement extends Statement {
public boolean doesNotCompleteNormally() {
return false; // may not be entered at all.
}
+
+ @Override
+ public boolean canCompleteNormally() {
+ return true;
+ }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index 47b7c8864..44b5dac4a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -309,4 +309,14 @@ public boolean doesNotCompleteNormally() {
public boolean completesByContinue() {
return this.thenStatement != null && this.thenStatement.completesByContinue() || this.elseStatement != null && this.elseStatement.completesByContinue();
}
+@Override
+public boolean canCompleteNormally() {
+ return ((this.thenStatement == null || this.thenStatement.canCompleteNormally()) ||
+ (this.elseStatement == null || this.elseStatement.canCompleteNormally()));
+}
+@Override
+public boolean continueCompletes() {
+ return this.thenStatement != null && this.thenStatement.continueCompletes() ||
+ this.elseStatement != null && this.elseStatement.continueCompletes();
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 414386eae..3b6f10a06 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -28,9 +28,12 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.IrritantSet;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
@@ -239,7 +242,21 @@ public TypeBinding resolveType(BlockScope scope) {
return null;
if (!checkedType.isReifiable()) {
- scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+ CompilerOptions options = scope.compilerOptions();
+ // If preview is disabled, report same as before, even at Java 14
+ if (options.complianceLevel < ClassFileConstants.JDK14 || !options.enablePreviewFeatures) {
+ scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+ } else {
+ if (options.isAnyEnabled(IrritantSet.PREVIEW)) {
+ scope.problemReporter().previewFeatureUsed(this.type.sourceStart, this.type.sourceEnd);
+ }
+ if (expressionType != TypeBinding.NULL) {
+ boolean isLegal = checkCastTypesCompatibility(scope, checkedType, expressionType, this.expression, true);
+ if (!isLegal || (this.bits & ASTNode.UnsafeCast) != 0) {
+ scope.problemReporter().unsafeCastInInstanceof(this.expression, checkedType, expressionType);
+ }
+ }
+ }
} else if (checkedType.isValidBinding()) {
// if not a valid binding, an error has already been reported for unresolved type
if ((expressionType != TypeBinding.NULL && expressionType.isBaseType()) // disallow autoboxing
@@ -250,10 +267,17 @@ public TypeBinding resolveType(BlockScope scope) {
}
return this.resolvedType = TypeBinding.BOOLEAN;
}
-
+@Override
+public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ if (!castType.isReifiable())
+ return CastExpression.checkUnsafeCast(this, scope, castType, expressionType, match, isNarrowing);
+ else
+ return super.checkUnsafeCast(scope, castType, expressionType, match, isNarrowing);
+}
/**
* @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
*/
+
@Override
public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
// null is not instanceof Type, recognize direct scenario
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index 0b5b785a3..0aaa80b02 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -794,7 +794,7 @@ public class Javadoc extends ASTNode {
// Get declaration infos
TypeParameter[] parameters = null;
TypeVariableBinding[] typeVariables = null;
- Argument[] recordParameters = null;
+ RecordComponent[] recordParameters = null;
int modifiers = -1;
switch (scope.kind) {
case Scope.METHOD_SCOPE:
@@ -816,7 +816,7 @@ public class Javadoc extends ASTNode {
parameters = typeDeclaration.typeParameters;
typeVariables = typeDeclaration.binding.typeVariables;
modifiers = typeDeclaration.binding.modifiers;
- recordParameters = typeDeclaration.args;
+ recordParameters = typeDeclaration.recordComponents;
break;
}
@@ -862,17 +862,17 @@ public class Javadoc extends ASTNode {
// Look for undocumented arguments
if (reportMissing) {
for (int i = 0; i < recordParameters.length; i++) {
- Argument arg = recordParameters[i];
+ RecordComponent component = recordParameters[i];
boolean found = false;
for (int j = 0; j < paramReferencesLength && !found; j++) {
JavadocSingleNameReference param = this.paramReferences[j];
String paramName = new String(param.getName()[0]);
- if (paramName.equals(new String(arg.name))) {
+ if (paramName.equals(new String(component.name))) {
found = true;
}
}
if (!found) {
- scope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, modifiers);
+ scope.problemReporter().javadocMissingParamTag(component.name, component.sourceStart, component.sourceEnd, modifiers);
}
}
}
@@ -882,8 +882,8 @@ public class Javadoc extends ASTNode {
String paramName = new String(param.getName()[0]);
boolean found = false;
for (int j = 0; j < recordParameters.length; j++) {
- Argument arg = recordParameters[j];
- if (paramName.equals(new String(arg.name))) {
+ RecordComponent component = recordParameters[j];
+ if (paramName.equals(new String(component.name))) {
found = true;
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
index b252fc8af..fa0b95186 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
@@ -161,4 +161,17 @@ public class LabeledStatement extends Statement {
public boolean completesByContinue() {
return this.statement instanceof ContinueStatement; // NOT this.statement.continuesAtOuterLabel
}
+
+ @Override
+ public boolean canCompleteNormally() {
+ if (this.statement.canCompleteNormally())
+ return true;
+ return this.statement.breaksOut(this.label);
+ }
+
+ @Override
+ public boolean continueCompletes() {
+ return this.statement instanceof ContinueStatement; // NOT this.statement.continuesAtOuterLabel
+ }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index 7ce3c26b3..1dadf1528 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -170,6 +170,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// no need to inform enclosing try block since its locals won't get
// known by the finally block
}
+ if (this.duplicateCheckObligation != null) {
+ this.duplicateCheckObligation.accept(flowInfo);
+ }
return flowInfo;
}
@@ -374,9 +377,10 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
boolean localExists = existingVariable instanceof LocalVariableBinding;
- if (localExists && isPatternVariable
- && (((LocalVariableBinding) existingVariable).modifiers & ExtraCompilerModifiers.AccPatternVariable) != 0)
+ if (localExists && (isPatternVariable
+ || (((LocalVariableBinding) existingVariable).modifiers & ExtraCompilerModifiers.AccPatternVariable) != 0))
{
+ // Do this only if either one of them is a pattern variable.
this.duplicateCheckObligation = (flowInfo) -> {
if (flowInfo.isDefinitelyAssigned((LocalVariableBinding) existingVariable)) {
scope.problemReporter().redefineLocal(this);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index 00b90db15..8ce9f54f2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -268,7 +268,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
}
@Override
- public Argument getRecordComponent() {
+ public RecordComponent getRecordComponent() {
if (this.arguments != null && this.arguments.length != 0)
return null;
ClassScope skope = this.scope.classScope();
@@ -277,14 +277,14 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
return null;
if (!(skope.referenceContext.isRecord()))
return null;
- Argument[] args = typeDecl.args;
- if (args == null || args.length == 0)
+ RecordComponent[] recComps = typeDecl.recordComponents;
+ if (recComps == null || recComps.length == 0)
return null;
- for (Argument arg : args) {
- if (arg == null || arg.name == null)
+ for (RecordComponent recComp : recComps) {
+ if (recComp == null || recComp.name == null)
continue;
- if (CharOperation.equals(this.selector, arg.name)) {
- return arg;
+ if (CharOperation.equals(this.selector, recComp.name)) {
+ return recComp;
}
}
return null;
@@ -311,7 +311,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
this.returnType.resolvedType = this.binding.returnType;
// record the return type binding
}
- Argument recordComponent = getRecordComponent();
+ RecordComponent recordComponent = getRecordComponent();
if (recordComponent != null) {
/* JLS 14 Records Sec 8.10.3 */
if (this.returnType != null && TypeBinding.notEquals(this.returnType.resolvedType, recordComponent.type.resolvedType))
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
index a750efc9b..9c795e546 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -116,7 +116,7 @@ public boolean isSuperAccess() {
@Override
public boolean isTypeAccess() {
// null is acceptable when we are resolving the first part of a reference
- return this.binding == null || this.binding instanceof ReferenceBinding;
+ return this.binding == null || (this.binding.kind() & Binding.TYPE) != 0;
}
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordComponent.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordComponent.java
new file mode 100644
index 000000000..e9853b841
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordComponent.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2020 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import java.util.List;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationCollector;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+@SuppressWarnings("rawtypes")
+public class RecordComponent extends AbstractVariableDeclaration {
+
+ public RecordComponentBinding binding;
+
+ public RecordComponent(
+ char[] name,
+ int sourceStart,
+ int sourceEnd) {
+
+ this.name = name;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ this.declarationEnd = sourceEnd;
+ }
+ public RecordComponent(char[] name, long posNom, TypeReference tr, int modifiers) {
+ this(name, (int) (posNom >>> 32), (int) posNom);
+ this.declarationSourceEnd = (int) posNom;
+ this.modifiers = modifiers;
+ this.type = tr;
+ if (tr != null) {
+ this.bits |= (tr.bits & ASTNode.HasTypeAnnotations);
+ }
+ }
+
+ @Override
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ //TODO: Add error checking if relevant.
+ return flowInfo;
+ }
+
+ public void checkModifiers() {
+
+ //only potential valid modifier is <<final>>
+ if (((this.modifiers & ExtraCompilerModifiers.AccJustFlag) & ~ClassFileConstants.AccFinal) != 0)
+ //AccModifierProblem -> other (non-visibility problem)
+ //AccAlternateModifierProblem -> duplicate modifier
+ //AccModifierProblem | AccAlternateModifierProblem -> visibility problem"
+
+ this.modifiers = (this.modifiers & ~ExtraCompilerModifiers.AccAlternateModifierProblem) | ExtraCompilerModifiers.AccModifierProblem;
+ }
+
+ @Override
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+ if ((this.bits & IsReachable) == 0) {
+ return; // TODO: can this ever happen?
+ }
+ codeStream.recordPositionsFrom(codeStream.position, this.sourceStart);
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+ */
+ @Override
+ public int getKind() {
+ return RECORD_COMPONENT;
+ }
+
+ public void getAllAnnotationContexts(int targetType, List allAnnotationContexts) {
+ AnnotationCollector collector = new AnnotationCollector(this, targetType, allAnnotationContexts);
+ this.traverse(collector, (BlockScope) null);
+ }
+
+ public boolean isVarArgs() {
+ return this.type != null && (this.type.bits & IsVarArgs) != 0;
+ }
+
+ @Override
+ public void resolve(BlockScope scope) {
+ resolveAnnotations(scope, this.annotations, this.binding);
+ // Check if this declaration should now have the type annotations bit set
+ if (this.annotations != null) {
+ for (int i = 0, max = this.annotations.length; i < max; i++) {
+ TypeBinding resolvedAnnotationType = this.annotations[i].resolvedType;
+ if (resolvedAnnotationType != null && (resolvedAnnotationType.getAnnotationTagBits() & TagBits.AnnotationForTypeUse) != 0) {
+ this.bits |= ASTNode.HasTypeAnnotations;
+ break;
+ }
+ }
+ }
+ // check @Deprecated annotation presence - Mostly in the future :)
+// if ((this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
+// && (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
+// && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK14) {
+// scope.problemReporter().missingDeprecatedAnnotationForRecordComponent(this);
+// }
+ }
+ // TODO: check when to call/relevance?
+ void validateNullAnnotations(BlockScope scope) {
+ if (!scope.validateNullAnnotation(this.binding.tagBits, this.type, this.annotations))
+ this.binding.tagBits &= ~TagBits.AnnotationNullMASK;
+ }
+
+ @Override
+ public StringBuffer print(int indent, StringBuffer output) {
+
+ printIndent(indent, output);
+ printModifiers(this.modifiers, output);
+ if (this.annotations != null) {
+ printAnnotations(this.annotations, output);
+ output.append(' ');
+ }
+
+ if (this.type == null) {
+ output.append("<no type> "); //$NON-NLS-1$
+ } else {
+ this.type.print(0, output).append(' ');
+ }
+ return output.append(this.name);
+ }
+
+ @Override
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+
+ return print(indent, output).append(';');
+ }
+
+ @Override
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
+ this.type.traverse(visitor, scope);
+ if (this.initialization != null)
+ this.initialization.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index 21f6132c8..54b2c9ee4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -198,6 +198,12 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
public boolean doesNotCompleteNormally() {
return true;
}
+
+@Override
+public boolean canCompleteNormally() {
+ return false;
+}
+
/**
* Retrun statement code generation
*
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 1063a56fa..be8e8b4b6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -98,7 +98,7 @@ public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowCo
For blocks, we don't perform intra-reachability analysis. We assume the lambda body is free of intrinsic control flow errors (if such errors
exist they will not be flagged by this analysis, but are guaranteed to surface later on.)
- @see Block#doesNotCompleteNormally
+ @see Block#doesNotCompleteNormally()
*/
public boolean doesNotCompleteNormally() {
return false;
@@ -112,6 +112,23 @@ public boolean completesByContinue() {
return false;
}
+/**
+ * Switch Expression analysis: *Assuming* this is reachable, analyze if this completes normally
+ * i.e control flow can reach the textually next statement, as per JLS 14 Sec 14.22
+ * For blocks, we don't perform intra-reachability analysis.
+ * Note: delinking this from a similar (opposite) {@link #doesNotCompleteNormally()} since that was
+ * coded for a specific purpose of Lambda Shape Analysis.
+ */
+public boolean canCompleteNormally() {
+ return true;
+}
+/**
+ * The equivalent function of completesByContinue - implements both the rules concerning continue with
+ * and without a label.
+ */
+public boolean continueCompletes() {
+ return false;
+}
public static final int NOT_COMPLAINED = 0;
public static final int COMPLAINED_FAKE_REACHABLE = 1;
public static final int COMPLAINED_UNREACHABLE = 2;
@@ -367,7 +384,8 @@ public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previo
if (flowInfo == FlowInfo.DEAD_END) {
if (previousComplaintLevel < COMPLAINED_UNREACHABLE) {
/* OT: */ if (shouldReport)
- scope.problemReporter().unreachableCode(this);
+ if (!this.doNotReportUnreachable())
+ scope.problemReporter().unreachableCode(this);
if (endOfBlock)
scope.checkUnclosedCloseables(flowInfo, null, null, null);
}
@@ -386,6 +404,9 @@ public int complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, int previo
return previousComplaintLevel;
}
+protected boolean doNotReportUnreachable() {
+ return false;
+}
/**
* Generate invocation arguments, considering varargs methods
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
index 42b6e6342..e0c96327b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
@@ -102,12 +102,9 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
if (this.switchLabeledRules // do this check for every block if '->' (Switch Labeled Rules)
&& stmt instanceof Block) {
Block block = (Block) stmt;
- if (block.doesNotCompleteNormally()) {
+ if (!block.canCompleteNormally()) {
return BREAKING;
}
- //JLS 12 15.28.1 Given a switch expression, if the switch block consists of switch labeled rules,
- //then it is a compile-time error if any switch labeled block can complete normally.
- blockScope.problemReporter().switchExpressionSwitchLabeledBlockCompletesNormally(block);
}
return FALLTHROUGH;
}
@@ -144,9 +141,20 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
@Override
protected void completeNormallyCheck(BlockScope blockScope) {
- if (this.switchLabeledRules) return; // already taken care in getFallThroughState()
int sz = this.statements != null ? this.statements.length : 0;
if (sz == 0) return;
+ /* JLS 12 15.28.1 Given a switch expression, if the switch block consists of switch labeled rules
+ * then it is a compile-time error if any switch labeled block can complete normally.
+ */
+ if (this.switchLabeledRules) {
+ for (Statement stmt : this.statements) {
+ if (!(stmt instanceof Block))
+ continue;
+ if (stmt.canCompleteNormally())
+ blockScope.problemReporter().switchExpressionLastStatementCompletesNormally(stmt);
+ }
+ return;
+ }
/* JLS 12 15.28.1
* If, on the other hand, the switch block consists of switch labeled statement groups, then it is a
* compile-time error if either the last statement in the switch block can complete normally, or the
@@ -164,7 +172,7 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
}
}
if (lastNonCaseStmt != null) {
- if (!lastNonCaseStmt.doesNotCompleteNormally())
+ if (lastNonCaseStmt.canCompleteNormally())
blockScope.problemReporter().switchExpressionLastStatementCompletesNormally(lastNonCaseStmt);
else if (lastNonCaseStmt instanceof ContinueStatement || lastNonCaseStmt instanceof ReturnStatement) {
blockScope.problemReporter().switchExpressionIllegalLastStatement(lastNonCaseStmt);
@@ -421,12 +429,21 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
return true;
}
@Override
+ public boolean visit(LambdaExpression lambdaExpression, BlockScope blockScope) {
+ return false;
+ }
+ @Override
public boolean visit(LabeledStatement stmt, BlockScope blockScope) {
if (stmt.label != null && stmt.label.length != 0)
this.labelDecls.add(new String(stmt.label));
return true;
}
@Override
+ public boolean visit(ReturnStatement stmt, BlockScope blockScope) {
+ blockScope.problemReporter().switchExpressionsReturnWithinSwitchExpression(stmt);
+ return false;
+ }
+ @Override
public boolean visit(TypeDeclaration stmt, BlockScope blockScope) {
return false;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index c19fc9d2a..ad6f8bb65 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -84,14 +84,14 @@ public class SwitchStatement extends Expression {
if (this.switchLabeledRules) {
if ((stmt instanceof Expression && ((Expression) stmt).isTrulyExpression()) || stmt instanceof ThrowStatement)
return BREAKING;
+ if (!stmt.canCompleteNormally())
+ return BREAKING;
if (stmt instanceof Block) {
Block block = (Block) stmt;
- if (block.doesNotCompleteNormally()) {
- return BREAKING;
- }
- // else add an implicit break
+ // Note implicit break anyway - Let the flow analysis do the dead code analysis
BreakStatement breakStatement = new BreakStatement(null, block.sourceEnd -1, block.sourceEnd);
+ breakStatement.isSynthetic = true; // suppress dead code flagging - codegen will not generate dead code anyway
int l = block.statements == null ? 0 : block.statements.length;
if (l == 0) {
@@ -905,6 +905,55 @@ public class SwitchStatement extends Expression {
}
@Override
+ public boolean canCompleteNormally() {
+ if (this.statements == null || this.statements.length == 0)
+ return true;
+ if (!this.switchLabeledRules) { // switch labeled statement group
+ if (this.statements[this.statements.length - 1].canCompleteNormally())
+ return true; // last statement as well as last switch label after blocks if exists.
+ if (this.defaultCase == null)
+ return true;
+ for (int i = 0, length = this.statements.length; i < length; i++) {
+ if (this.statements[i].breaksOut(null))
+ return true;
+ }
+ } else {
+ // switch block consists of switch rules
+ for (Statement stmt : this.statements) {
+ if (stmt instanceof CaseStatement)
+ continue; // skip case
+ if (this.defaultCase == null)
+ return true;
+ if (stmt instanceof Expression)
+ return true;
+ if (stmt.canCompleteNormally())
+ return true;
+ if (stmt instanceof YieldStatement && ((YieldStatement) stmt).isImplicit) // note: artificially introduced
+ return true;
+ if (stmt instanceof Block) {
+ Block block = (Block) stmt;
+ if (block.canCompleteNormally())
+ return true;
+ if (block.breaksOut(null))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean continueCompletes() {
+ if (this.statements == null || this.statements.length == 0)
+ return false;
+ for (int i = 0, length = this.statements.length; i < length; i++) {
+ if (this.statements[i].continueCompletes())
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public StringBuffer printExpression(int indent, StringBuffer output) {
return printStatement(indent, output);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
index cbc5e9170..dbede2343 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
@@ -234,7 +234,18 @@ public boolean doesNotCompleteNormally() {
return this.block.doesNotCompleteNormally();
}
@Override
+
public boolean completesByContinue() {
return this.block.completesByContinue();
}
+
+@Override
+public boolean canCompleteNormally() {
+ return this.block.canCompleteNormally();
+}
+
+@Override
+public boolean continueCompletes() {
+ return this.block.continueCompletes();
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
index 3271257fa..2e408809d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
@@ -133,4 +133,10 @@ public void traverse(ASTVisitor visitor, BlockScope blockScope) {
public boolean doesNotCompleteNormally() {
return true;
}
+
+@Override
+public boolean canCompleteNormally() {
+ return false;
+}
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index 26a9cecc3..bd9e21c05 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -1382,4 +1382,34 @@ public boolean completesByContinue() {
}
return this.finallyBlock != null && this.finallyBlock.completesByContinue();
}
+@Override
+public boolean canCompleteNormally() {
+ if (this.tryBlock.canCompleteNormally()) {
+ return (this.finallyBlock != null) ? this.finallyBlock.canCompleteNormally() : true;
+ }
+ if (this.catchBlocks != null) {
+ for (int i = 0; i < this.catchBlocks.length; i++) {
+ if (this.catchBlocks[i].canCompleteNormally()) {
+ return (this.finallyBlock != null) ? this.finallyBlock.canCompleteNormally() : true;
+ }
+ }
+ }
+ return false;
+}
+@Override
+public boolean continueCompletes() {
+ if (this.tryBlock.continueCompletes()) {
+ return (this.finallyBlock == null) ? true :
+ this.finallyBlock.canCompleteNormally() || this.finallyBlock.continueCompletes();
+ }
+ if (this.catchBlocks != null) {
+ for (int i = 0; i < this.catchBlocks.length; i++) {
+ if (this.catchBlocks[i].continueCompletes()) {
+ return (this.finallyBlock == null) ? true :
+ this.finallyBlock.canCompleteNormally() || this.finallyBlock.continueCompletes();
+ }
+ }
+ }
+ return this.finallyBlock != null && this.finallyBlock.continueCompletes();
+}
}
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 1021c6273..3f23f0274 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
@@ -158,7 +158,7 @@ public class TypeDeclaration extends Statement implements ProblemSeverities, Ref
public TypeParameter[] typeParameters;
// 14 Records preview support
- public Argument[] args;
+ public RecordComponent[] recordComponents;
public int nRecordComponents;
public boolean isLocalRecord;
public static Set<String> disallowedComponentNames;
@@ -734,7 +734,7 @@ public ConstructorDeclaration createDefaultConstructorForRecord(boolean needExpl
// constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
constructor.modifiers = this.modifiers & ClassFileConstants.AccPublic;
constructor.modifiers |= ClassFileConstants.AccPublic; // JLS 14 8.10.5
- constructor.arguments = this.args;
+ constructor.arguments = getArgumentsFromComponents(this.recordComponents);
constructor.declarationSourceStart = constructor.sourceStart =
constructor.bodyStart = this.sourceStart;
@@ -751,19 +751,19 @@ public ConstructorDeclaration createDefaultConstructorForRecord(boolean needExpl
* to a record component with the corresponding formal parameter in the order that they appear
* in the record component list.*/
List<Statement> statements = new ArrayList<>();
- int l = this.args != null ? this.args.length : 0;
+ int l = this.recordComponents != null ? this.recordComponents.length : 0;
if (l > 0 && this.fields != null) {
List<String> fNames = Arrays.stream(this.fields)
.filter(f -> f.isARecordComponent)
.map(f ->new String(f.name))
.collect(Collectors.toList());
for (int i = 0; i < l; ++i) {
- Argument arg = this.args[i];
- if (!fNames.contains(new String(arg.name)))
+ RecordComponent component = this.recordComponents[i];
+ if (!fNames.contains(new String(component.name)))
continue;
- FieldReference lhs = new FieldReference(arg.name, 0);
+ FieldReference lhs = new FieldReference(component.name, 0);
lhs.receiver = ThisReference.implicitThis();
- statements.add(new Assignment(lhs, new SingleNameReference(arg.name, 0), 0));
+ statements.add(new Assignment(lhs, new SingleNameReference(component.name, 0), 0));
}
}
constructor.statements = statements.toArray(new Statement[0]);
@@ -788,6 +788,18 @@ public ConstructorDeclaration createDefaultConstructorForRecord(boolean needExpl
}
+private Argument[] getArgumentsFromComponents(RecordComponent[] comps) {
+ Argument[] args2 = comps == null || comps.length == 0 ? ASTNode.NO_ARGUMENTS :
+ new Argument[comps.length];
+ int count = 0;
+ for (RecordComponent comp : comps) {
+ Argument argument = new Argument(comp.name, ((long)comp.sourceStart) << 32 | comp.sourceEnd,
+ comp.type, comp.modifiers);
+ args2[count++] = argument;
+ }
+ return args2;
+}
+
public ConstructorDeclaration createDefaultConstructor( boolean needExplicitConstructorCall, boolean needToInsert) {
if (this.isRecord())
return createDefaultConstructorForRecord(needExplicitConstructorCall, needToInsert);
@@ -981,6 +993,20 @@ public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
return null;
}
+/**
+ * Find the matching parse node, answers null if nothing found
+ */
+public RecordComponent declarationOf(RecordComponentBinding recordComponentBinding) {
+ if (recordComponentBinding != null && this.recordComponents != null) {
+ for (int i = 0, max = this.fields.length; i < max; i++) {
+ RecordComponent recordComponent;
+ if ((recordComponent = this.recordComponents[i]).binding == recordComponentBinding)
+ return recordComponent;
+ }
+ }
+ return null;
+}
+
//{ObjectTeams: find source of a method mapping
public AbstractMethodMappingDeclaration declarationOf(CallinCalloutBinding mappingBinding) {
if (mappingBinding != null && this.callinCallouts != null) {
@@ -1047,11 +1073,11 @@ public ConstructorDeclaration getConstructor(Parser parser) {
CompactConstructorDeclaration ccd = (CompactConstructorDeclaration) am;
ccd.recordDeclaration = this;
if (ccd.arguments == null)
- ccd.arguments = this.args;
+ ccd.arguments = getArgumentsFromComponents(this.recordComponents);
return ccd;
}
// now we are looking at a "normal" constructor
- if (this.args == null && am.arguments == null)
+ if (this.recordComponents == null && am.arguments == null)
return (ConstructorDeclaration) am;
}
}
@@ -2097,6 +2123,11 @@ public void resolve() {
boolean hasFieldInit = false;
if (fieldsAndMethods) {
// SH}
+ if (this.recordComponents != null) {
+ for (RecordComponent rc : this.recordComponents) {
+ rc.resolve(this.initializerScope);
+ }
+ }
if (this.fields != null) {
for (int i = 0, count = this.fields.length; i < count; i++) {
FieldDeclaration field = this.fields[i];
@@ -2450,6 +2481,11 @@ public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
this.typeParameters[i].traverse(visitor, this.scope);
}
}
+ if (this.recordComponents != null) {
+ int length = this.recordComponents.length;
+ for (int i = 0; i < length; i++)
+ this.recordComponents[i].traverse(visitor, this.initializerScope);
+ }
if (this.memberTypes != null) {
int length = this.memberTypes.length;
for (int i = 0; i < length; i++)
@@ -2513,6 +2549,11 @@ public void traverse(ASTVisitor visitor, BlockScope blockScope) {
this.typeParameters[i].traverse(visitor, this.scope);
}
}
+ if (this.recordComponents != null) {
+ int length = this.recordComponents.length;
+ for (int i = 0; i < length; i++)
+ this.recordComponents[i].traverse(visitor, this.initializerScope);
+ }
if (this.memberTypes != null) {
int length = this.memberTypes.length;
for (int i = 0; i < length; i++)
@@ -2570,6 +2611,11 @@ public void traverse(ASTVisitor visitor, ClassScope classScope) {
this.typeParameters[i].traverse(visitor, this.scope);
}
}
+ if (this.recordComponents != null) {
+ int length = this.recordComponents.length;
+ for (int i = 0; i < length; i++)
+ this.recordComponents[i].traverse(visitor, this.initializerScope);
+ }
if (this.memberTypes != null) {
int length = this.memberTypes.length;
for (int i = 0; i < length; i++)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 6a6732d0f..9ca77a6cc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -106,6 +106,7 @@ static class AnnotationCollector extends ASTVisitor {
Annotation[][] annotationsOnDimensions;
int dimensions;
Wildcard currentWildcard;
+ RecordComponentBinding recordComponentBinding;
public AnnotationCollector(
TypeParameter typeParameter,
@@ -190,6 +191,13 @@ static class AnnotationCollector extends ASTVisitor {
this.dimensions = dimensions;
}
+ public AnnotationCollector(RecordComponent recordComponent, int targetType, List annotationContexts) {
+ this.annotationContexts = annotationContexts;
+ this.typeReference = recordComponent.type;
+ this.targetType = targetType;
+ this.recordComponentBinding = recordComponent.binding;
+ }
+
private boolean internalVisit(Annotation annotation) {
AnnotationContext annotationContext = null;
if (annotation.isRuntimeTypeInvisible()) {
@@ -227,6 +235,7 @@ static class AnnotationCollector extends ASTVisitor {
annotationContext.info = this.info;
break;
case AnnotationTargetTypeConstants.FIELD :
+// case AnnotationTargetTypeConstants.RECORD_COMPONENT : // value same as FIELD
case AnnotationTargetTypeConstants.METHOD_RETURN :
case AnnotationTargetTypeConstants.METHOD_RECEIVER :
break;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index 3db9b23d3..3863cde89 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -319,4 +319,20 @@ public class WhileStatement extends Statement {
public boolean completesByContinue() {
return this.action.continuesAtOuterLabel();
}
+
+ @Override
+ public boolean canCompleteNormally() {
+ Constant cst = this.condition.constant;
+ boolean isConditionTrue = cst == null || cst != Constant.NotAConstant && cst.booleanValue() == true;
+ cst = this.condition.optimizedBooleanConstant();
+ boolean isConditionOptimizedTrue = cst == null ? true : cst != Constant.NotAConstant && cst.booleanValue() == true;
+ if (!(isConditionTrue || isConditionOptimizedTrue))
+ return true;
+ return this.action != null && this.action.breaksOut(null);
+ }
+
+ @Override
+ public boolean continueCompletes() {
+ return this.action.continuesAtOuterLabel();
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java
index 87b8c8687..84a9106bc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java
@@ -224,4 +224,10 @@ public void traverse(ASTVisitor visitor, BlockScope blockscope) {
public boolean doesNotCompleteNormally() {
return true;
}
+
+@Override
+public boolean canCompleteNormally() {
+ return false;
+}
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java
index 012ef693c..837b1bd09 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2013 IBM Corporation and others.
+ * Copyright (c) 2012, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -28,6 +28,7 @@ public interface AnnotationTargetTypeConstants {
int CLASS_TYPE_PARAMETER_BOUND = 0x11;
int METHOD_TYPE_PARAMETER_BOUND = 0x12;
int FIELD = 0x13;
+ int RECORD_COMPONENT = 0x13; // same as field
int METHOD_RETURN = 0x14;
int METHOD_RECEIVER = 0x15;
int METHOD_FORMAL_PARAMETER = 0x16;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerStats.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerStats.java
index 120c4b17f..9fae8f505 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerStats.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerStats.java
@@ -19,6 +19,7 @@ public class CompilerStats implements Comparable {
// overall
public long startTime;
public long endTime;
+ public long overallTime;
public long lineCount;
// compile phases
@@ -32,7 +33,7 @@ public class CompilerStats implements Comparable {
* @return the time spent between start and end
*/
public long elapsedTime() {
- return this.endTime - this.startTime;
+ return this.overallTime;
}
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index 814a7aec9..534e8fa3f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -54,6 +54,9 @@ public abstract class Binding {
public static final int TYPE_USE = TYPE | ASTNode.Bit15;
public static final int INTERSECTION_TYPE18 = TYPE | ASTNode.Bit16;
public static final int POLY_TYPE = TYPE | ASTNode.Bit17;
+ // Java 14 - Records - preview
+ public static final int RECORD_COMPONENT = ASTNode.Bit18;
+// public static final int VARIABLE = FIELD | LOCAL | RECORD_COMPONENT;
// In the unlikely event you add a new type binding, remember to update TypeBindingVisitor and Scope.substitute methods.
@@ -83,7 +86,9 @@ public abstract class Binding {
public static final CallinCalloutBinding[] NO_CALLIN_CALLOUT_BINDINGS = new CallinCalloutBinding[0];
public static final SyntheticArgumentBinding[] NO_SYNTH_ARGUMENTS = new SyntheticArgumentBinding[0];
//Markus Witte}
+ public static final RecordComponentBinding[] NO_COMPONENTS = new RecordComponentBinding[0];
+ public static final RecordComponentBinding[] UNINITIALIZED_COMPONENTS = new RecordComponentBinding[0];
public static final FieldBinding[] UNINITIALIZED_FIELDS = new FieldBinding[0];
public static final MethodBinding[] UNINITIALIZED_METHODS = new MethodBinding[0];
public static final ReferenceBinding[] UNINITIALIZED_REFERENCE_TYPES = new ReferenceBinding[0];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
index 643964fda..352115d53 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2017 GK Software AG.
+ * Copyright (c) 2013, 2020 GK Software AG.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -339,10 +339,10 @@ class BoundSet {
/** 18.1.3 bullet 5: throws α */
Set<InferenceVariable> inThrows = new HashSet<>();
- private TypeBound [] incorporatedBounds = new TypeBound[0];
- private TypeBound [] unincorporatedBounds = new TypeBound [1024];
+ private TypeBound[] incorporatedBounds = Binding.NO_TYPE_BOUNDS;
+ private TypeBound[] unincorporatedBounds = new TypeBound[8];
private int unincorporatedBoundsCount = 0;
- private TypeBound [] mostRecentBounds = new TypeBound[4]; // for quick & dirty duplicate elimination.
+ private TypeBound[] mostRecentBounds = new TypeBound[4]; // for quick & dirty duplicate elimination
public BoundSet() {}
@@ -367,8 +367,8 @@ class BoundSet {
Iterator<ThreeSets> outerIt = this.boundsPerVariable.values().iterator();
while (outerIt.hasNext())
size += outerIt.next().size();
+ if (size == 0) return Binding.NO_TYPE_BOUNDS;
TypeBound[] collected = new TypeBound[size];
- if (size == 0) return collected;
outerIt = this.boundsPerVariable.values().iterator();
int idx = 0;
while (outerIt.hasNext())
@@ -382,15 +382,19 @@ class BoundSet {
*/
public BoundSet copy() {
BoundSet copy = new BoundSet();
- Iterator<Entry<InferenceVariable, ThreeSets>> setsIterator = this.boundsPerVariable.entrySet().iterator();
- while (setsIterator.hasNext()) {
- Entry<InferenceVariable, ThreeSets> entry = setsIterator.next();
- copy.boundsPerVariable.put(entry.getKey(), entry.getValue().copy());
+ if (!this.boundsPerVariable.isEmpty()) {
+ Iterator<Entry<InferenceVariable, ThreeSets>> setsIterator = this.boundsPerVariable.entrySet().iterator();
+ while (setsIterator.hasNext()) {
+ Entry<InferenceVariable, ThreeSets> entry = setsIterator.next();
+ copy.boundsPerVariable.put(entry.getKey(), entry.getValue().copy());
+ }
}
copy.inThrows.addAll(this.inThrows);
copy.captures.putAll(this.captures);
- System.arraycopy(this.incorporatedBounds, 0, copy.incorporatedBounds = new TypeBound[this.incorporatedBounds.length], 0, this.incorporatedBounds.length);
- System.arraycopy(this.unincorporatedBounds, 0, copy.unincorporatedBounds = new TypeBound[this.unincorporatedBounds.length], 0, this.unincorporatedBounds.length);
+ if (this.incorporatedBounds.length > 0)
+ System.arraycopy(this.incorporatedBounds, 0, copy.incorporatedBounds = new TypeBound[this.incorporatedBounds.length], 0, this.incorporatedBounds.length);
+ if (this.unincorporatedBoundsCount > 0)
+ System.arraycopy(this.unincorporatedBounds, 0, copy.unincorporatedBounds = new TypeBound[this.unincorporatedBounds.length], 0, this.unincorporatedBounds.length);
copy.unincorporatedBoundsCount = this.unincorporatedBoundsCount;
return copy;
}
@@ -496,8 +500,7 @@ class BoundSet {
// Driver for the real workhorse - Implements generational incorporation a la generational garbage collector.
boolean incorporate(InferenceContext18 context) throws InferenceFailureException {
-
- if (this.unincorporatedBoundsCount == 0 && this.captures.size() == 0)
+ if (this.unincorporatedBoundsCount == 0 && this.captures.isEmpty())
return true;
do {
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 32398fd6c..56e0a1b12 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
@@ -39,7 +39,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
-
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult.CheckPoint;
@@ -53,6 +52,7 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -235,6 +235,61 @@ public class ClassScope extends Scope {
anonymousType.verifyMethods(environment().methodVerifier());
}
+ void buildComponents() {
+ SourceTypeBinding sourceType = this.referenceContext.binding;
+ if (!sourceType.isRecord()) return;
+ if (sourceType.areComponentsInitialized()) return;
+ if (this.referenceContext.recordComponents == null) {
+ sourceType.setComponents(Binding.NO_COMPONENTS);
+ return;
+ }
+ // count the number of fields vs. initializers
+ RecordComponent[] recComps = this.referenceContext.recordComponents;
+ int size = recComps.length;
+ int count = size;
+
+ // iterate the field declarations to create the bindings, lose all duplicates
+ RecordComponentBinding[] componentBindings = new RecordComponentBinding[count];
+ HashtableOfObject knownComponentNames = new HashtableOfObject(count);
+ count = 0;
+ for (int i = 0; i < size; i++) {
+ RecordComponent recComp = recComps[i];
+ RecordComponentBinding compBinding = new RecordComponentBinding(sourceType, recComp, null,
+ recComp.modifiers | ExtraCompilerModifiers.AccUnresolved);
+ compBinding.id = count;
+ checkAndSetModifiersForComponents(compBinding, recComp);
+
+ if (knownComponentNames.containsKey(recComp.name)) {
+ RecordComponentBinding previousBinding = (RecordComponentBinding) knownComponentNames.get(recComp.name);
+ if (previousBinding != null) {
+ for (int f = 0; f < i; f++) {
+ RecordComponent previousComponent = recComps[f];
+ if (previousComponent.binding == previousBinding) {
+ // flag the duplicate component name error here.
+ problemReporter().recordDuplicateComponent(previousComponent);
+ break;
+ }
+ }
+ }
+ knownComponentNames.put(recComp.name, null); // ensure that the duplicate field is found & removed
+ problemReporter().recordDuplicateComponent(recComp);
+ recComp.binding = null;
+ } else {
+ knownComponentNames.put(recComp.name, compBinding);
+ // remember that we have seen a component with this name
+ componentBindings[count++] = compBinding;
+ }
+ }
+ // remove duplicate components
+ if (count != componentBindings.length)
+ System.arraycopy(componentBindings, 0, componentBindings = new RecordComponentBinding[count], 0, count);
+ sourceType.setComponents(componentBindings);
+ }
+ private void checkAndSetModifiersForComponents(RecordComponentBinding compBinding, RecordComponent comp) {
+ // TODO Auto-generated method stub
+
+ }
+
void buildFields() {
SourceTypeBinding sourceType = this.referenceContext.binding;
if (sourceType.areFieldsInitialized()) return;
@@ -332,6 +387,7 @@ public class ClassScope extends Scope {
LookupEnvironment.BUILD_FIELDS_AND_METHODS))
return; // catchup was blocked.
// SH}
+ buildComponents();
buildFields();
buildMethods();
//{ObjectTeams: build callins and callouts
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtendedTagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtendedTagBits.java
new file mode 100644
index 000000000..42a43d490
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtendedTagBits.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2020 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
+public interface ExtendedTagBits {
+
+ int AreRecordComponentsComplete = ASTNode.Bit1;
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
index f4dfe2034..9fd2eba53 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
@@ -80,6 +80,17 @@ class ExternalAnnotationSuperimposer extends TypeBindingVisitor {
binding.externalAnnotationProvider = provider; // for superimposing method signatures
}
+ public static void annotateComponentBinding(RecordComponentBinding componentBinding, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ char[] componentSignature = componentBinding.genericSignature();
+ if (componentSignature == null && componentBinding.type != null)
+ componentSignature = componentBinding.type.signature();
+ // TODO: check - do we need a provider.forRecordComponent; won't the field be sufficient - SH?
+ ITypeAnnotationWalker walker = provider.forField(componentBinding.name, componentSignature, environment);
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ if (visitor.go(walker))
+ componentBinding.type = visitor.superimpose(componentBinding.type, TypeBinding.class);
+ }
+
public static void annotateFieldBinding(FieldBinding field, ExternalAnnotationProvider provider, LookupEnvironment environment) {
char[] fieldSignature = field.genericSignature();
if (fieldSignature == null && field.type != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index e40381e20..52761319c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -499,7 +499,8 @@ public final int kind() {
return FIELD;
}
public boolean isRecordComponent() {
- return this.declaringClass != null && this.declaringClass.isRecord() && !this.isStatic();
+ return this.declaringClass != null && this.declaringClass.isRecord() && !this.isStatic()
+ && (this.modifiers & ExtraCompilerModifiers.AccRecord) != 0;
}
/* Answer true if the receiver is visible to the invocationPackage.
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index 8fe6c449c..39abf79e6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -47,6 +47,7 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -1863,6 +1864,9 @@ public AbstractMethodDeclaration sourceMethod() {
public LambdaExpression sourceLambda() {
return null;
}
+public RecordComponent sourceRecordComponent() {
+ return null;
+}
public final int sourceStart() {
AbstractMethodDeclaration method = sourceMethod();
if (method == null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
index cb042ad91..fa87a9349 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
@@ -78,6 +78,20 @@ public ReferenceBinding closestReferenceMatch() {
}
@Override
+public ReferenceBinding superclass() {
+ if (this.closestMatch != null)
+ return this.closestMatch.superclass();
+ return super.superclass();
+}
+
+@Override
+public ReferenceBinding[] superInterfaces() {
+ if (this.closestMatch != null)
+ return this.closestMatch.superInterfaces();
+ return super.superInterfaces();
+}
+
+@Override
public boolean hasTypeBit(int bit) {
if (this.closestMatch != null)
return this.closestMatch.hasTypeBit(bit);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RecordComponentBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RecordComponentBinding.java
new file mode 100644
index 000000000..baf68a094
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RecordComponentBinding.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2020 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.TeamAnchor;
+
+public class RecordComponentBinding extends VariableBinding {
+
+ public ReferenceBinding declaringRecord;
+ public BlockScope declaringScope; // back-pointer to its declaring scope
+
+ public RecordComponentBinding(ReferenceBinding declaringRecord, RecordComponent declaration, TypeBinding type, int modifiers) {
+ super(declaration.name, type, modifiers, null);
+ this.declaringRecord = declaringRecord;
+ declaration.binding = this;
+ }
+
+
+ /* API
+ * Answer the receiver's binding type from Binding.BindingID.
+ */
+ @Override
+ public final int kind() {
+ return RECORD_COMPONENT;
+ }
+
+//{ObjectTeams:
+ @Override
+ public boolean isBaseAnchor() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ private RecordComponentBinding(ReferenceBinding declaringRecord, char[] name, int modifiers) {
+ super(name, null, modifiers, null);
+ this.declaringRecord = declaringRecord;
+ }
+ @Override
+ protected TeamAnchor getClone() {
+ return new RecordComponentBinding(this.declaringRecord, this.name, this.modifiers);
+ }
+// SH}
+
+ /*
+ * declaringUniqueKey # recordComponentName
+ * p.X (int first, int second) { } --> Lp/X;#first
+ */
+ @Override
+ public char[] computeUniqueKey(boolean isLeaf) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(this.declaringRecord.computeUniqueKey(false/*not a leaf*/));
+ // variable name
+ buffer.append('#');
+ buffer.append(this.name);
+
+ int length = buffer.length();
+ char[] uniqueKey = new char[length];
+ buffer.getChars(0, length, uniqueKey, 0);
+ return uniqueKey;
+ }
+
+ /**
+ * X<T> t --> LX<TT;>;
+ */
+ public char[] genericSignature() {
+ if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) return null;
+ return this.type.genericTypeSignature();
+ }
+
+ @Override
+ public AnnotationBinding[] getAnnotations() {
+ RecordComponentBinding originalRecordComponentBinding = original();
+ ReferenceBinding declaringRecordBinding = originalRecordComponentBinding.declaringRecord;
+ if (declaringRecordBinding == null) {
+ return Binding.NO_ANNOTATIONS;
+ }
+ return declaringRecordBinding.retrieveAnnotations(originalRecordComponentBinding);
+ }
+
+ @Override
+ public long getAnnotationTagBits() {
+ RecordComponentBinding originalRecordComponentBinding = original();
+ if ((originalRecordComponentBinding.tagBits & TagBits.AnnotationResolved) == 0 &&
+ originalRecordComponentBinding.declaringRecord instanceof SourceTypeBinding) {
+ ClassScope scope = ((SourceTypeBinding) originalRecordComponentBinding.declaringRecord).scope;
+ if (scope == null) {// should not be true - but safety net
+ this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
+ return 0;
+ }
+ TypeDeclaration typeDecl = scope.referenceContext;
+ RecordComponent recordComponent = typeDecl.declarationOf(originalRecordComponentBinding);
+ if (recordComponent != null) {
+ ASTNode.resolveAnnotations(typeDecl.initializerScope, recordComponent.annotations, originalRecordComponentBinding);
+ }
+ }
+ return originalRecordComponentBinding.tagBits;
+ }
+
+ public final boolean isDeprecated() {
+ return (this.modifiers & ClassFileConstants.AccDeprecated) != 0;
+ }
+
+ // TODO: check
+ public final boolean isPublic() {
+ return (this.modifiers & ClassFileConstants.AccPublic) != 0;
+ }
+ /**
+ * Returns the original RecordComponent (as opposed to parameterized instances)
+ */
+ public RecordComponentBinding original() {
+ return this;
+ }
+
+ @Override
+ public void setAnnotations(AnnotationBinding[] annotations, boolean forceStore) {
+ this.declaringRecord.storeAnnotations(this, annotations, forceStore);
+ }
+
+ public RecordComponent sourceRecordComponent() {
+ if (!(this.declaringRecord instanceof SourceTypeBinding))
+ return null;
+ SourceTypeBinding sourceType = (SourceTypeBinding) this.declaringRecord;
+ RecordComponent[] recordComponents = sourceType.scope.referenceContext.recordComponents;
+ if (recordComponents != null) {
+ for (int i = recordComponents.length; --i >= 0;)
+ if (this == recordComponents[i].binding)
+ return recordComponents[i];
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 02520c70a..e20a467f3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -62,6 +62,7 @@
* Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
* Pierre-Yves B. <pyvesdev@gmail.com> - Contributions for
* Bug 559618 - No compiler warning for import from same package
+ * Bug 560630 - No warning on unused import on class from same package
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -3837,7 +3838,7 @@ public abstract class Scope {
if (resolvedImport == null) continue nextImport;
if (resolvedImport instanceof TypeBinding) {
ImportReference importReference = importBinding.reference;
- if (importReference != null)
+ if (importReference != null && !isUnnecessarySamePackageImport(importBinding.resolvedImport, unitScope))
importReference.bits |= ASTNode.Used;
return resolvedImport; // already know its visible
}
@@ -3959,8 +3960,9 @@ public abstract class Scope {
private boolean isUnnecessarySamePackageImport(Binding resolvedImport, Scope unitScope) {
if (resolvedImport instanceof ReferenceBinding) {
- if (unitScope.getCurrentPackage() == ((ReferenceBinding) resolvedImport).getPackage()) {
- if ((resolvedImport.getAnnotationTagBits() & TagBits.IsNestedType) != 0)
+ ReferenceBinding referenceBinding = (ReferenceBinding) resolvedImport;
+ if (unitScope.getCurrentPackage() == referenceBinding.getPackage()) {
+ if (referenceBinding.isNestedType())
return false; // importing nested types is still necessary
return true;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 9e0f3c420..4b73d97e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -79,6 +79,7 @@ import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
@@ -207,8 +208,10 @@ public class SourceTypeBinding extends ReferenceBinding {
public HashSet<SourceTypeBinding> nestMembers;
private boolean isRecordDeclaration = false;
- private FieldBinding[] recordComponents; // cache
+ private RecordComponentBinding[] components; // for Java 14 record declaration - preview
+ private FieldBinding[] implicitComponentFields; // cache
private MethodBinding[] recordComponentAccessors = null; // hash maybe an overkill
+
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
//{ObjectTeams: // share model from TypeDeclaration:
super(scope.referenceContext.getModel());
@@ -231,6 +234,7 @@ public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassSc
// SH}
// expect the fields & methods to be initialized correctly later
+ this.components = Binding.UNINITIALIZED_COMPONENTS;
this.fields = Binding.UNINITIALIZED_FIELDS;
this.methods = Binding.UNINITIALIZED_METHODS;
this.prototype = this;
@@ -1187,7 +1191,11 @@ public List<MethodBinding> checkAndAddSyntheticRecordComponentAccessors(MethodBi
* unless a public method with the same signature is explicitly declared in the body of the declaration of R.
*/
- List<String> componentNames = Arrays.stream(this.fields) // initialize with all the record components
+ // Note: filteredComponents implies that only those components which are successful in having field - for eg
+ // if the component name is not correct (say one of finalize, clone etc) then the compilation not successful
+ // and no accessor should be created (essentially in a recovered code if there are errors) - if there are no
+ // errors then filteredComponents equals components.
+ List<String> filteredComponents = Arrays.stream(this.fields) // initialize with all the record components
.filter(f -> f.isRecordComponent())
.map(f -> new String(f.name))
.collect(Collectors.toList());
@@ -1196,18 +1204,20 @@ public List<MethodBinding> checkAndAddSyntheticRecordComponentAccessors(MethodBi
if (this.methods != null) {
accessors = Arrays.stream(methodBindings)
.filter(m -> m.selector != null && m.selector.length > 0)
- .filter(m -> componentNames.contains(new String(m.selector)))
+ .filter(m -> filteredComponents.contains(new String(m.selector)))
.filter(m -> m.parameters == null || m.parameters.length == 0)
.collect(Collectors.toList());
List<String> candidates = accessors.stream()
.map(m -> new String(m.selector))
.collect(Collectors.toList());
- componentNames.removeAll(candidates);
+ filteredComponents.removeAll(candidates);
}
- int missingCount = componentNames.size();
+ int missingCount = filteredComponents.size();
for (int i = 0; i < missingCount; ++i) {
- implicitMethods.add(addSyntheticRecordComponentAccessor(componentNames.get(i).toCharArray(), i));
+ RecordComponentBinding rcb = this.getRecordComponent(filteredComponents.get(i).toCharArray());
+ assert rcb != null;
+ implicitMethods.add(addSyntheticRecordComponentAccessor(rcb, i));
}
accessors.addAll(implicitMethods);
this.recordComponentAccessors = accessors.toArray(new MethodBinding[0]);
@@ -1216,35 +1226,36 @@ public List<MethodBinding> checkAndAddSyntheticRecordComponentAccessors(MethodBi
/* Add a new synthetic component accessor for the recordtype. Selector should be identical to component name.
* char[] component name of the record
*/
-public SyntheticMethodBinding addSyntheticRecordComponentAccessor(char[] selector, int index) {
+public SyntheticMethodBinding addSyntheticRecordComponentAccessor(RecordComponentBinding rcb, int index) {
if (!isPrototype()) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);
- SyntheticMethodBinding accessMethod = null;
- SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(selector);
- FieldBinding field = getField(selector, true);
- accessMethod = new SyntheticMethodBinding(this, field, index);
- AnnotationBinding[] annotations = field.getAnnotations();
- if (annotations.length > 0) {
- List<AnnotationBinding> list = new ArrayList<>();
- for (AnnotationBinding binding : annotations) {
- long bits = binding.getAnnotationType().getAnnotationTagBits();
- if ((bits & TagBits.AnnotationForMethod) != 0
- || (bits & TagBits.AnnotationTargetMASK) == 0) {
- list.add(binding);
- }
- }
- if (list.size() > 0) {
- AnnotationBinding[] annots = new AnnotationBinding[list.size()];
- annotations = list.toArray(annots);
- accessMethod.setAnnotations(annotations, true);
- }
- }
+ SyntheticMethodBinding accessMethod = new SyntheticMethodBinding(this, rcb, index);
+ SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(rcb.name);
+// TODO: Annotation propagation to be done later.
+// FieldBinding field = getField(selector, true);
+// accessMethod = new SyntheticMethodBinding(this, field, index);
+// AnnotationBinding[] annotations = field.getAnnotations();
+// if (annotations.length > 0) {
+// List<AnnotationBinding> list = new ArrayList<>();
+// for (AnnotationBinding binding : annotations) {
+// long bits = binding.getAnnotationType().getAnnotationTagBits();
+// if ((bits & TagBits.AnnotationForMethod) != 0
+// || (bits & TagBits.AnnotationTargetMASK) == 0) {
+// list.add(binding);
+// }
+// }
+// if (list.size() > 0) {
+// AnnotationBinding[] annots = new AnnotationBinding[list.size()];
+// annotations = list.toArray(annots);
+// accessMethod.setAnnotations(annotations, true);
+// }
+// }
if (accessors == null) {
- this.synthetics[SourceTypeBinding.METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
+ this.synthetics[SourceTypeBinding.METHOD_EMUL].put(rcb.name, accessors = new SyntheticMethodBinding[2]);
accessors[0] = accessMethod;
} else {
if ((accessMethod = accessors[0]) == null) {
@@ -1272,6 +1283,11 @@ public SyntheticMethodBinding addSyntheticRecordOverrideMethod(char[] selector,
}
return accessMethod;
}
+boolean areComponentsInitialized() {
+ if (!isPrototype())
+ return this.prototype.areComponentsInitialized();
+ return this.components != Binding.UNINITIALIZED_COMPONENTS;
+}
/* JLS 14 Record - Preview - end */
boolean areFieldsInitialized() {
if (!isPrototype())
@@ -1375,6 +1391,155 @@ void faultInTypesForFieldsAndMethods() {
checkAnnotationsInType();
internalFaultInTypeForFieldsAndMethods();
}
+public RecordComponentBinding[] components() {
+
+ if (!this.isRecordDeclaration)
+ return null;
+ if (!isPrototype()) {
+ if ((this.extendedTagBits & ExtendedTagBits.AreRecordComponentsComplete) != 0)
+ return this.components;
+ this.extendedTagBits |= ExtendedTagBits.AreRecordComponentsComplete;
+ return this.components = this.prototype.components();
+ }
+
+ if ((this.extendedTagBits & ExtendedTagBits.AreRecordComponentsComplete) != 0)
+ return this.components;
+
+ if (!areComponentsInitialized()) {
+ this.scope.buildComponents();
+ }
+ int failed = 0;
+ RecordComponentBinding[] resolvedComponents = this.components;
+ try {
+ // Note: do not sort the components
+ RecordComponentBinding[] componentsSnapshot = this.components;
+ for (int i = 0, length = componentsSnapshot.length; i < length; i++) {
+ if (resolveTypeFor(componentsSnapshot[i]) == null) {
+ // do not alter original component array until resolution is over, due to reentrance (143259)
+ // TODO: to check for relevance
+ if (resolvedComponents == componentsSnapshot) {
+ System.arraycopy(componentsSnapshot, 0, resolvedComponents = new RecordComponentBinding[length], 0, length);
+ }
+ resolvedComponents[i] = null;
+ failed++;
+ } else {
+ // we need to complete some unfinished work here - find the synthetic accessor method
+ // and fill in the blanks
+ RecordComponentBinding rcb = resolvedComponents[i];
+ MethodBinding accessor = getRecordComponentAccessor(rcb.name);
+ if (accessor instanceof SyntheticMethodBinding) { // double checking
+ SyntheticMethodBinding smb = (SyntheticMethodBinding) accessor;
+ if (rcb.type instanceof TypeVariableBinding ||
+ rcb.type instanceof ParameterizedTypeBinding)
+ smb.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
+ smb.returnType = rcb.type;
+ // add code for implicit canonical constructor argument annotations also
+ for (FieldBinding f : this.fields) {
+ if (f.isRecordComponent() && CharOperation.equals(f.name, rcb.name)) {
+ smb.targetReadField = f;
+ ASTNode.copyRecordComponentAnnotations(this.scope, smb,
+ rcb.sourceRecordComponent().annotations);
+ // Note: a) type use bit set above and b) reusing rcb type, so
+ // copySE8Annot already done for rcb.type, hence not
+ // required here (tricky on an SMB without ast)
+ break;
+ }
+ }
+ }
+ }
+ }
+ } finally {
+ if (failed > 0) {
+ int newSize = resolvedComponents.length - failed;
+ if (newSize == 0)
+ return setComponents(Binding.NO_COMPONENTS);
+
+ RecordComponentBinding[] newComponents = new RecordComponentBinding[newSize];
+ for (int i = 0, j = 0, length = resolvedComponents.length; i < length; i++) {
+ if (resolvedComponents[i] != null)
+ newComponents[j++] = resolvedComponents[i];
+ }
+ setComponents(newComponents);
+ }
+ }
+ this.extendedTagBits |= ExtendedTagBits.AreRecordComponentsComplete;
+ return this.components;
+}
+
+public RecordComponentBinding resolveTypeFor(RecordComponentBinding component) {
+ if (!isPrototype())
+ return this.prototype.resolveTypeFor(component);
+
+ if ((component.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
+ return component;
+
+ component.getAnnotationTagBits();
+ if ((component.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) // TODO: Watch out the spec changes
+ component.modifiers |= ClassFileConstants.AccDeprecated; // expected to be available soon.
+
+ if (isViewedAsDeprecated() && !component.isDeprecated()) {
+ component.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+ component.tagBits |= this.tagBits & TagBits.AnnotationTerminallyDeprecated;
+ }
+ if (hasRestrictedAccess())
+ component.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
+ RecordComponent[] componentDecls = this.scope.referenceContext.recordComponents;
+ int length = componentDecls == null ? 0 : componentDecls.length;
+ for (int f = 0; f < length; f++) {
+ if (componentDecls[f].binding != component)
+ continue;
+
+ // component cannot be static, hence no static initializer scope
+ MethodScope initializationScope = this.scope.referenceContext.initializerScope;
+ RecordComponent componentDecl = componentDecls[f];
+ TypeBinding componentType = componentDecl.type.resolveType(initializationScope, true /* check bounds*/);
+ component.type = componentType;
+ component.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+ if (componentType == null) {
+ componentDecl.binding = null;
+ return null;
+ }
+ if (componentType == TypeBinding.VOID) {
+ this.scope.problemReporter().recordComponentCannotBeVoid(componentDecl);
+ componentDecl.binding = null;
+ return null;
+ }
+ if (componentType.isArrayType() && ((ArrayBinding) componentType).leafComponentType == TypeBinding.VOID) {
+ this.scope.problemReporter().variableTypeCannotBeVoidArray(componentDecl);
+ componentDecl.binding = null;
+ return null;
+ }
+ if ((componentType.tagBits & TagBits.HasMissingType) != 0) {
+ component.tagBits |= TagBits.HasMissingType;
+ }
+ TypeBinding leafType = componentType.leafComponentType();
+ if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
+ component.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
+ }
+ Annotation [] annotations = componentDecl.annotations;
+ ASTNode.copyRecordComponentAnnotations(initializationScope, component, annotations);
+
+ long sourceLevel = this.scope.compilerOptions().sourceLevel;
+ if (sourceLevel >= ClassFileConstants.JDK1_8) {
+ if (annotations != null && annotations.length != 0) {
+ // piggybacking on an existing method to move type_use annotations to type in record component
+ ASTNode.copySE8AnnotationsToType(initializationScope, component, annotations, false);
+ }
+ Annotation.isTypeUseCompatible(componentDecl.type, this.scope, annotations);
+ }
+ // TODO Bug 562478: apply null default: - to check anything to be done? - SH
+// if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {}
+
+ if (initializationScope.shouldCheckAPILeaks(this, component.isPublic()) && componentDecl.type != null) // fieldDecl.type is null for enum constants
+ initializationScope.detectAPILeaks(componentDecl.type, componentType);
+
+ if (this.externalAnnotationProvider != null) {
+ ExternalAnnotationSuperimposer.annotateComponentBinding(component, this.externalAnnotationProvider, this.environment);
+ }
+ return component;
+ }
+ return null; // should never reach this point
+}
private void internalFaultInTypeForFieldsAndMethods() {
fields();
@@ -1395,6 +1560,7 @@ private void internalFaultInTypeForFieldsAndMethods() {
@Override
public FieldBinding[] fields() {
+ components(); // In a record declaration, the components should be complete prior to fields and probably for methods
if (!isPrototype()) {
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
@@ -2273,7 +2439,7 @@ private MethodBinding[] checkAndGetExplicitCanonicalConstructors() {
if (!this.isRecordDeclaration)
return ec.toArray(new MethodBinding[0]);
- FieldBinding[] recComps = this.getRecordComponents();
+ RecordComponentBinding[] recComps = this.components;
int nRecordComponents = recComps.length;
if (this.methods != null && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK14) {
for (MethodBinding method : this.methods) {
@@ -2311,6 +2477,8 @@ private int getImplicitMethod(char[] name) {
@Override
public MethodBinding[] methods() {
+ components(); // In a record declaration, the components should be complete prior to fields and probably for methods
+
if (!isPrototype()) {
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
@@ -2712,8 +2880,21 @@ public FieldBinding resolveTypeFor(FieldBinding field) {
field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
}
+ Annotation[] relevantRecordComponentAnnotations = null;
+ if (sourceLevel >= ClassFileConstants.JDK14) {
+ // copy annotations from record component if applicable
+ if (field.isRecordComponent()) {
+ RecordComponentBinding rcb = getRecordComponent(field.name);
+ assert rcb != null;
+ relevantRecordComponentAnnotations = ASTNode.copyRecordComponentAnnotations(initializationScope,
+ field, rcb.sourceRecordComponent().annotations);
+ }
+ }
if (sourceLevel >= ClassFileConstants.JDK1_8) {
Annotation [] annotations = fieldDecl.annotations;
+ if (annotations == null && relevantRecordComponentAnnotations != null) // field represents a record component.
+ annotations = relevantRecordComponentAnnotations;
+
if (annotations != null && annotations.length != 0) {
ASTNode.copySE8AnnotationsToType(initializationScope, field, annotations,
fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT); // type annotation is illegal on enum constant
@@ -3359,6 +3540,23 @@ public void tagAsHavingDefectiveContainerType() {
this.containerAnnotationType = new ProblemReferenceBinding(this.containerAnnotationType.compoundName, this.containerAnnotationType, ProblemReasons.DefectiveContainerAnnotationType);
}
+// Record Declaration - Java 14 - preview
+//Propagate writes to all annotated variants so the clones evolve along.
+public RecordComponentBinding[] setComponents(RecordComponentBinding[] comps) {
+
+ if (!isPrototype())
+ return this.prototype.setComponents(comps);
+
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.components = comps;
+ }
+ }
+ return this.components = comps;
+}
+
// Propagate writes to all annotated variants so the clones evolve along.
public FieldBinding [] setFields(FieldBinding[] fields) {
@@ -4052,8 +4250,17 @@ public List<String> getNestMembers() {
}
/* Get the field bindings in the order of record component declaration
* should be called only after a called to fields() */
-public FieldBinding[] getRecordComponents() {
- return this.recordComponents;
+public FieldBinding[] getImplicitComponentFields() {
+ return this.implicitComponentFields;
+}
+public RecordComponentBinding getRecordComponent(char[] name) {
+ if (this.isRecordDeclaration && this.components != null) {
+ for (RecordComponentBinding rcb : this.components) {
+ if (CharOperation.equals(name, rcb.name))
+ return rcb;
+ }
+ }
+ return null;
}
/**
* Get the accessor method given the record component name
@@ -4073,9 +4280,9 @@ public MethodBinding getRecordComponentAccessor(char[] name) {
return accessor;
}
public void computeRecordComponents() {
- if (!this.isRecordDeclaration || this.recordComponents != null)
+ if (!this.isRecordDeclaration || this.implicitComponentFields != null)
return;
- Argument[] recComps = this.scope.referenceContext.args;
+ RecordComponent[] recComps = this.scope.referenceContext.recordComponents;
List<FieldBinding> list = new ArrayList<>();
if (recComps != null && recComps.length > 0 && this.fields != null) {
List<String> recordComponentNames = new ArrayList<>(0);
@@ -4090,7 +4297,7 @@ public void computeRecordComponents() {
}
}
}
- this.recordComponents = list.toArray(new FieldBinding[0]);
+ this.implicitComponentFields = list.toArray(new FieldBinding[0]);
}
public void cleanUp() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 3c7010cc3..371ce00ec 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -50,6 +50,7 @@ public class SyntheticMethodBinding extends MethodBinding {
public MethodBinding targetMethod; // method or constructor
public TypeBinding targetEnumType; // enum type
public LambdaExpression lambda;
+ public RecordComponentBinding recordComponentBinding;
/** Switch (one from many) linked to the switch table */
public SwitchStatement switchStatement;
@@ -553,38 +554,28 @@ public class SyntheticMethodBinding extends MethodBinding {
this.index = methodId;
}
- public SyntheticMethodBinding(ReferenceBinding declaringClass, FieldBinding targetField, int index) {
+ public SyntheticMethodBinding(ReferenceBinding declaringClass, RecordComponentBinding rcb, int index) {
SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
assert declaringSourceType.isRecord();
this.declaringClass = declaringSourceType;
this.modifiers = ClassFileConstants.AccPublic;
- if (targetField.type instanceof TypeVariableBinding ||
- targetField.type instanceof ParameterizedTypeBinding)
- this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
+ // rcb not resolved fully yet - to be filled in later - see STB.components()
+// if (rcb.type instanceof TypeVariableBinding ||
+// rcb.type instanceof ParameterizedTypeBinding)
+// this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
if (this.declaringClass.isStrictfp())
this.modifiers |= ClassFileConstants.AccStrictfp;
this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
this.parameters = Binding.NO_PARAMETERS;
- this.returnType = targetField.type;
- this.selector = targetField.name;
- this.targetReadField = targetField;
+// this.returnType = rcb.type; Not resolved yet - to be filled in later
+ this.selector = rcb.name;
+ this.recordComponentBinding = rcb;
+// this.targetReadField = ??; // not fully resolved yet - to be filled in later
this.purpose = SyntheticMethodBinding.FieldReadAccess;
this.thrownExceptions = Binding.NO_EXCEPTIONS;
this.declaringClass = declaringSourceType;
- this.setTypeAnnotations(targetField.getAnnotations());
this.index = index;
-
- // retrieve sourceStart position for the target field for line number attributes
- FieldDeclaration[] fieldDecls = declaringSourceType.scope.referenceContext.fields;
- if (fieldDecls != null) {
- for (int i = 0, max = fieldDecls.length; i < max; i++) {
- if (fieldDecls[i].binding == targetField) {
- this.sourceStart = fieldDecls[i].sourceStart;
- return;
- }
- }
- }
- this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart;
+ this.sourceStart = rcb.sourceRecordComponent().sourceStart;
}
public SyntheticMethodBinding(ReferenceBinding declaringClass, char[] selector, int index) {
SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index 6302bfb48..204ad06c9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -72,6 +72,7 @@ abstract public class TypeBinding extends Binding {
public int id = TypeIds.NoId;
public long tagBits = 0; // See values in the interface TagBits below
+ public int extendedTagBits = 0; // See values in the interface ExtendedTagBits
protected AnnotationBinding [] typeAnnotations = Binding.NO_ANNOTATIONS;
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 d47bfd3b3..ec8464f91 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
@@ -12204,7 +12204,7 @@ protected void consumeDefaultLabelExpr() {
}
@Override
public boolean visit(SwitchStatement stmt, BlockScope blockScope) {
- return false;
+ return true;
}
@Override
public boolean visit(TypeDeclaration stmt, BlockScope blockScope) {
@@ -13535,15 +13535,17 @@ protected void consumeRecordComponentHeaderRightParen() {
this.astStack[this.astPtr] = typeDecl;
// rd.sourceEnd = this.rParenPos;
if (length != 0) {
- Argument[] args = new Argument[length];
+ RecordComponent[] recComps = new RecordComponent[length];
System.arraycopy(
this.astStack,
this.astPtr + 1,
- args,
+ recComps,
0,
length);
- typeDecl.args = args;
- convertToFields(typeDecl, args);
+ typeDecl.recordComponents = recComps;
+ convertToFields(typeDecl, recComps);
+ } else {
+ typeDecl.recordComponents = ASTNode.NO_RECORD_COMPONENTS;
}
typeDecl.bodyStart = this.rParenPos+1;
this.listLength = 0; // reset this.listLength after having read all parameters
@@ -13553,38 +13555,37 @@ protected void consumeRecordComponentHeaderRightParen() {
if (this.currentElement.parseTree() == typeDecl) return;
}
}
-private void convertToFields(TypeDeclaration typeDecl, Argument[] args) {
- int length = args.length;
+private void convertToFields(TypeDeclaration typeDecl, RecordComponent[] recComps) {
+ int length = recComps.length;
FieldDeclaration[] fields = new FieldDeclaration[length];
int nFields = 0;
Set<String> argsSet = new HashSet<>();
- for (int i = 0, max = args.length; i < max; i++) {
- Argument arg = args[i];
- arg.bits |= ASTNode.IsRecordComponent;
- String argName = new String(arg.name);
+ for (int i = 0, max = recComps.length; i < max; i++) {
+ RecordComponent recComp = recComps[i];
+ String argName = new String(recComp.name);
if (TypeDeclaration.disallowedComponentNames.contains(argName)) {
- problemReporter().recordIllegalComponentNameInRecord(arg, typeDecl);
+ problemReporter().recordIllegalComponentNameInRecord(recComp, typeDecl);
continue;
}
if (argsSet.contains(argName)) {
// flag the error at the place where duplicate params of methods would have been flagged.
continue;
}
- if (arg.type.getLastToken() == TypeConstants.VOID) {
- problemReporter().recordComponentCannotBeVoid(typeDecl, arg);
+ if (recComp.type.getLastToken() == TypeConstants.VOID) {
+ problemReporter().recordComponentCannotBeVoid(recComp);
continue;
}
- if (arg.isVarArgs() && i < max - 1)
- problemReporter().recordIllegalVararg(arg, typeDecl);
+ if (recComp.isVarArgs() && i < max - 1)
+ problemReporter().recordIllegalVararg(recComp, typeDecl);
argsSet.add(argName);
- FieldDeclaration f = fields[nFields++] = createFieldDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
- f.bits = arg.bits;
- f.declarationSourceStart = arg.declarationSourceStart;
- f.declarationEnd = arg.declarationEnd;
- f.declarationSourceEnd = arg.declarationSourceEnd;
- f.endPart1Position = arg.sourceEnd; //TODO BETA_JAVA14 - recheck
- f.endPart2Position = arg.declarationSourceEnd;
+ FieldDeclaration f = fields[nFields++] = createFieldDeclaration(recComp.name, recComp.sourceStart, recComp.sourceEnd);
+ f.bits = recComp.bits;
+ f.declarationSourceStart = recComp.declarationSourceStart;
+ f.declarationEnd = recComp.declarationEnd;
+ f.declarationSourceEnd = recComp.declarationSourceEnd;
+ f.endPart1Position = recComp.sourceEnd; //TODO BETA_JAVA14 - recheck
+ f.endPart2Position = recComp.declarationSourceEnd;
f.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccFinal;
// Note: JVMS 14 S 4.7.8 The Synthetic Attribute mandates do not mark Synthetic for Record compoents.
// hence marking this "explicitly" as implicit.
@@ -13602,10 +13603,11 @@ private void convertToFields(TypeDeclaration typeDecl, Argument[] args) {
* component and the type as the declared type of the record component.
*/
f.modifiers |= ClassFileConstants.AccPrivate | ClassFileConstants.AccFinal;
- f.modifiersSourceStart = arg.modifiersSourceStart;
- f.sourceStart = arg.sourceStart;
- f.sourceEnd = arg.sourceEnd;
- f.type = arg.type;
+ f.modifiers |= ExtraCompilerModifiers.AccRecord;
+ f.modifiersSourceStart = recComp.modifiersSourceStart;
+ f.sourceStart = recComp.sourceStart;
+ f.sourceEnd = recComp.sourceEnd;
+ f.type = recComp.type;
/*
* JLS 14 SEC 8.10.3 Item 1 says the following:
* "This field is annotated with the annotation that appears on the corresponding
@@ -13616,9 +13618,9 @@ private void convertToFields(TypeDeclaration typeDecl, Argument[] args) {
* targeted by the annotation. Hence, do a blanket assignment for now and later (read binding
* time) weed out the irrelevant ones.
*/
- f.annotations = arg.annotations;
- arg.annotations = null;
- if ((args[i].bits & ASTNode.HasTypeAnnotations) != 0) {
+// f.annotations = recComp.annotations;
+// comp.annotations = null;
+ if ((recComp.bits & ASTNode.HasTypeAnnotations) != 0) {
f.bits |= ASTNode.HasTypeAnnotations;
}
}
@@ -13688,28 +13690,28 @@ protected void consumeRecordComponent(boolean isVarArgs) {
type.bits |= ASTNode.IsVarArgs; // set isVarArgs
}
int modifierPositions = this.intStack[this.intPtr--];
- Argument arg;
- arg = new Argument(
+ RecordComponent recordComponent;
+ recordComponent = new RecordComponent(
identifierName,
namePositions,
type,
this.intStack[this.intPtr--] & ~ClassFileConstants.AccDeprecated); // modifiers
- arg.declarationSourceStart = modifierPositions;
- arg.bits |= (type.bits & ASTNode.HasTypeAnnotations);
+ recordComponent.declarationSourceStart = modifierPositions;
+ recordComponent.bits |= (type.bits & ASTNode.HasTypeAnnotations);
// consume annotations
if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
System.arraycopy(
this.expressionStack,
(this.expressionPtr -= length) + 1,
- arg.annotations = new Annotation[length],
+ recordComponent.annotations = new Annotation[length],
0,
length);
- arg.bits |= ASTNode.HasTypeAnnotations;
+ recordComponent.bits |= ASTNode.HasTypeAnnotations;
RecoveredType currentRecoveryType = this.currentRecoveryType();
if (currentRecoveryType != null)
- currentRecoveryType.annotationsConsumed(arg.annotations);
+ currentRecoveryType.annotationsConsumed(recordComponent.annotations);
}
- pushOnAstStack(arg);
+ pushOnAstStack(recordComponent);
/* if incomplete record header, this.listLength counter will not have been reset,
indicating that some arguments are available on the stack */
@@ -13718,10 +13720,10 @@ protected void consumeRecordComponent(boolean isVarArgs) {
if (!this.statementRecoveryActivated &&
this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
- problemReporter().invalidUsageOfVarargs(arg);
+ problemReporter().invalidUsageOfVarargs(recordComponent);
} else if (!this.statementRecoveryActivated &&
extendedDimensions > 0) {
- problemReporter().illegalExtendedDimensions(arg);
+ problemReporter().illegalExtendedDimensions(recordComponent);
}
}
}
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 48bd9be2e..9dba8b392 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
@@ -155,6 +155,7 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Receiver;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
@@ -651,6 +652,7 @@ public static int getIrritant(int problemID) {
case IProblem.JavadocIncorrectArityForParameterizedConstructor:
case IProblem.JavadocParameterizedConstructorArgumentTypeMismatch:
case IProblem.JavadocTypeArgumentsForRawGenericConstructor:
+ case IProblem.JavadocNotAccessibleType:
case IProblem.JavadocNotVisibleField:
case IProblem.JavadocNotVisibleConstructor:
case IProblem.JavadocNotVisibleMethod:
@@ -3080,13 +3082,13 @@ public void illegalExtendedDimensions(AnnotationMethodDeclaration annotationType
annotationTypeMemberDeclaration.sourceStart,
annotationTypeMemberDeclaration.sourceEnd);
}
-public void illegalExtendedDimensions(Argument argument) {
+public void illegalExtendedDimensions(AbstractVariableDeclaration aVarDecl) {
this.handle(
IProblem.IllegalExtendedDimensionsForVarArgs,
NoArgument,
NoArgument,
- argument.sourceStart,
- argument.sourceEnd);
+ aVarDecl.sourceStart,
+ aVarDecl.sourceEnd);
}
public void illegalGenericArray(TypeBinding leafComponentType, ASTNode location) {
this.handle(
@@ -5602,15 +5604,14 @@ public void invalidUsageOfTypeParametersForEnumDeclaration(TypeDeclaration annot
parameters[0].declarationSourceStart,
parameters[length - 1].declarationSourceEnd);
}
-public void invalidUsageOfVarargs(Argument argument) {
+public void invalidUsageOfVarargs(AbstractVariableDeclaration aVarDecl) {
this.handle(
IProblem.InvalidUsageOfVarargs,
NoArgument,
NoArgument,
- argument.type.sourceStart,
- argument.sourceEnd);
+ aVarDecl.type.sourceStart,
+ aVarDecl.sourceEnd);
}
-
public void invalidUsageOfTypeAnnotations(Annotation annotation) {
this.handle(
IProblem.InvalidUsageOfTypeAnnotations,
@@ -6390,6 +6391,9 @@ public void javadocInvalidType(ASTNode location, TypeBinding type, int modifiers
case ProblemReasons.NotVisible :
id = IProblem.JavadocNotVisibleType;
break;
+ case ProblemReasons.NotAccessible:
+ id = IProblem.JavadocNotAccessibleType;
+ break;
case ProblemReasons.Ambiguous :
id = IProblem.JavadocAmbiguousType;
break;
@@ -9057,6 +9061,22 @@ public void typeCastError(CastExpression expression, TypeBinding leftType, TypeB
expression.sourceStart,
expression.sourceEnd);
}
+public void unsafeCastInInstanceof(Expression expression, TypeBinding leftType, TypeBinding rightType) {
+ String leftName = new String(leftType.readableName());
+ String rightName = new String(rightType.readableName());
+ String leftShortName = new String(leftType.shortReadableName());
+ String rightShortName = new String(rightType.shortReadableName());
+ if (leftShortName.equals(rightShortName)){
+ leftShortName = leftName;
+ rightShortName = rightName;
+ }
+ this.handle(
+ IProblem.UnsafeCast,
+ new String[] { rightName, leftName },
+ new String[] { rightShortName, leftShortName },
+ expression.sourceStart,
+ expression.sourceEnd);
+}
public void typeCollidesWithEnclosingType(TypeDeclaration typeDecl) {
String[] arguments = new String[] {new String(typeDecl.name)};
this.handle(
@@ -15787,7 +15807,7 @@ public void switchExpressionSwitchLabeledBlockCompletesNormally(Block block) {
IProblem.SwitchExpressionaYieldSwitchLabeledBlockCompletesNormally,
NoArgument,
NoArgument,
- block.sourceStart,
+ block.sourceEnd - 1,
block.sourceEnd);
}
public void switchExpressionLastStatementCompletesNormally(Statement stmt) {
@@ -15795,7 +15815,7 @@ public void switchExpressionLastStatementCompletesNormally(Statement stmt) {
IProblem.SwitchExpressionaYieldSwitchLabeledBlockCompletesNormally,
NoArgument,
NoArgument,
- stmt.sourceStart,
+ stmt.sourceEnd - 1,
stmt.sourceEnd);
}
public void switchExpressionIllegalLastStatement(Statement stmt) {
@@ -15926,6 +15946,14 @@ public void switchExpressionsContinueOutOfSwitchExpression(ASTNode statement) {
statement.sourceStart,
statement.sourceEnd);
}
+public void switchExpressionsReturnWithinSwitchExpression(ASTNode statement) {
+ this.handle(
+ IProblem.SwitchExpressionsReturnWithinSwitchExpression,
+ NoArgument,
+ NoArgument,
+ statement.sourceStart,
+ statement.sourceEnd);
+}
public void illegalModifierForInnerRecord(SourceTypeBinding type) {
if (!this.options.enablePreviewFeatures)
return;
@@ -15992,29 +16020,29 @@ public void recordCompactConstructorHasReturnStatement(ReturnStatement stmt) {
stmt.sourceStart,
stmt.sourceEnd);
}
-public void recordIllegalComponentNameInRecord(Argument arg, TypeDeclaration typeDecl) {
+public void recordIllegalComponentNameInRecord(RecordComponent recComp, TypeDeclaration typeDecl) {
if (!this.options.enablePreviewFeatures)
return;
this.handle(
IProblem.RecordIllegalComponentNameInRecord,
new String[] {
- new String(arg.name), new String(typeDecl.name)
+ new String(recComp.name), new String(typeDecl.name)
},
new String[] {
- new String(arg.name), new String(typeDecl.name)
+ new String(recComp.name), new String(typeDecl.name)
},
- arg.sourceStart,
- arg.sourceEnd);
+ recComp.sourceStart,
+ recComp.sourceEnd);
}
-public void recordDuplicateComponent(Argument arg) {
+public void recordDuplicateComponent(RecordComponent recordComponent) {
if (!this.options.enablePreviewFeatures)
return;
this.handle(
IProblem.RecordDuplicateComponent,
- new String[] { new String(arg.name)},
- new String[] { new String(arg.name)},
- arg.sourceStart,
- arg.sourceEnd);
+ new String[] { new String(recordComponent.name)},
+ new String[] { new String(recordComponent.name)},
+ recordComponent.sourceStart,
+ recordComponent.sourceEnd);
}
public void recordIllegalNativeModifierInRecord(AbstractMethodDeclaration method) {
if (!this.options.enablePreviewFeatures)
@@ -16170,7 +16198,7 @@ public void recordCannotExtendRecord(SourceTypeBinding type, TypeReference super
superclass.sourceStart,
superclass.sourceEnd);
}
-public void recordComponentCannotBeVoid(ASTNode recordDecl, Argument arg) {
+public void recordComponentCannotBeVoid(RecordComponent arg) {
if (!this.options.enablePreviewFeatures)
return;
String[] arguments = new String[] { new String(arg.name) };
@@ -16178,10 +16206,10 @@ public void recordComponentCannotBeVoid(ASTNode recordDecl, Argument arg) {
IProblem.RecordComponentCannotBeVoid,
arguments,
arguments,
- recordDecl.sourceStart,
- recordDecl.sourceEnd);
+ arg.sourceStart,
+ arg.sourceEnd);
}
-public void recordIllegalVararg(Argument argType, TypeDeclaration typeDecl) {
+public void recordIllegalVararg(RecordComponent argType, TypeDeclaration typeDecl) {
String[] arguments = new String[] {CharOperation.toString(argType.type.getTypeName()), new String(typeDecl.name)};
this.handle(
IProblem.RecordIllegalVararg,
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 ee9d91638..5a45fb6b9 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
@@ -246,6 +246,7 @@
209 = Syntax error on keyword "{0}"; {1} expected
210 = Syntax error on keyword "{0}", no accurate correction available
211 = Comparing identical expressions
+212 = Type {0} cannot be safely cast to {1}
220 = Unmatched bracket
221 = The primitive type {0} of {1} does not have a field {2}
@@ -1022,6 +1023,7 @@
1721 = Switch Expressions are supported from Java 14 onwards only
1722 = Breaking out of switch expressions not permitted
1723 = Continue out of switch expressions not permitted
+1724 = Return within switch expressions not permitted
# Java 14 Preview - begin
# Records
1730 = Illegal modifier for the record {0}; only public, private, protected, static, final and strictfp are permitted
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java
new file mode 100644
index 000000000..8a04b703e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java
@@ -0,0 +1,429 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Andrey Loskutov and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemAlreadyExistsException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Abstraction to the ct.sym file access (see https://openjdk.java.net/jeps/247). The ct.sym file is required to
+ * implement JEP 247 feature (compile with "--release" option against class stubs for older releases) and is currently
+ * (Java 15) a jar file with undocumented internal structure, currently existing in at least two different format
+ * versions (pre Java 12 and Java 12 and later).
+ * <p>
+ * The only documentation known seem to be the current implementation of
+ * com.sun.tools.javac.platform.JDKPlatformProvider and probably some JDK build tools that construct ct.sym file. Root
+ * directories inside the file are somehow related to the Java release number, encoded as hex (if they contain release
+ * number as hex).
+ * <p>
+ * If a release directory contains "system-modules" file, it is a flag that this release files are not inside ct.sym
+ * file because it is the current release, and jrt file system should be used instead.
+ * <p>
+ * All other release directories contain encoded signature (*.sig) files with class stubs for classes in the release.
+ * <p>
+ * Some directories contain files that are shared between different releases, exact logic how they are distributed is
+ * not known.
+ * <p>
+ * Known format versions of ct.sym:
+ * <p>
+ * Pre JDK 12:
+ *
+ * <pre>
+ * ct.sym -> 9 -> java/ -> lang/
+ * ct.sym -> 9-modules -> java.base -> module-info.sig
+ * </pre>
+ *
+ * From JDK 12 onward:
+ *
+ * <pre>
+ * ct.sym -> 9 -> java.base -> java/ -> lang/
+ * ct.sym -> 9 -> java.base -> module-info.sig
+ * </pre>
+ *
+ * Notably,
+ * <ol>
+ * <li>in JDK 12 modules classes and ordinary classes are located in the same location
+ * <li>in JDK 12, ordinary classes are found inside their respective modules
+ * </ol>
+ * <p>
+ *
+ * Searching a file for a given release in ct.sym means finding & traversing all possible release related directories
+ * and searching for matching path.
+ */
+public class CtSym {
+
+ public static final boolean DISABLE_CACHE = Boolean.getBoolean("org.eclipse.jdt.disable_CTSYM_cache"); //$NON-NLS-1$
+
+ static boolean VERBOSE = false;
+
+ /**
+ * Map from path (release) inside ct.sym file to all class signatures loaded
+ */
+ private final Map<Path, Optional<byte[]>> fileCache = new ConcurrentHashMap<>(10007);
+
+ private final Path jdkHome;
+
+ private final Path ctSymFile;
+
+ private FileSystem fs;
+
+ Path root;
+
+ private boolean isJRE12Plus;
+
+ /**
+ * Paths of all root directories, per release (as hex number). e.g. in JDK 11, Java 10 mapping looks like A -> [A,
+ * A-modules, A789, A9] but to have more fun, in JDK 14, same mapping looks like A -> [A, AB, ABC, ABCD]
+ */
+ private final Map<String, List<Path>> releaseRootPaths = new ConcurrentHashMap<>();
+
+ /**
+ * All paths that exist in all release root directories, per release (as hex number). The first key is release
+ * number in hex. The second key is the "full qualified binary name" of the class (without module name and
+ * with .sig suffix). The value is the full path of the corresponding signature file in the ct.sym file.
+ */
+ private final Map<String, Map<String, Path>> allReleasesPaths = new ConcurrentHashMap<>();
+
+ CtSym(Path jdkHome) {
+ this.jdkHome = jdkHome;
+ this.ctSymFile = jdkHome.resolve("lib/ct.sym"); //$NON-NLS-1$
+ FileSystem fst = null;
+ boolean exists = Files.exists(this.ctSymFile);
+ if (exists) {
+ URI uri = URI.create("jar:file:" + this.ctSymFile.toUri().getRawPath()); //$NON-NLS-1$
+ try {
+ fst = FileSystems.getFileSystem(uri);
+ } catch (Exception fne) {
+ // Ignore and move on
+ }
+ if (fst == null) {
+ try {
+ fst = FileSystems.newFileSystem(uri, new HashMap<>());
+ } catch (FileSystemAlreadyExistsException e) {
+ fst = FileSystems.getFileSystem(uri);
+ } catch (IOException e) {
+ //
+ }
+ }
+ }
+ this.fs = fst;
+ if (fst == null) {
+ this.root = null;
+ this.isJRE12Plus = false;
+ } else {
+ try {
+ this.root = fst.getPath("/"); //$NON-NLS-1$
+ this.isJRE12Plus = isCurrentRelease12plus();
+ } catch (IOException e) {
+ this.root = null;
+ }
+ }
+
+ }
+
+ /**
+ * @return true if ct.sym file exists and can be read
+ */
+ public boolean exists() {
+ return this.fs != null;
+ }
+
+ /**
+ * @return may return null if ct.sym file doesn't exist
+ */
+ public FileSystem getFs() {
+ return this.fs;
+ }
+
+ /**
+ *
+ * @return true if this file is from Java 12+ JRE
+ */
+ public boolean isJRE12Plus() {
+ return this.isJRE12Plus;
+ }
+
+ /**
+ * @return may return null if ct.sym file doesn't exist
+ */
+ public Path getRoot() {
+ return this.root;
+ }
+
+ /**
+ * @param releaseInHex
+ * major JDK version segment as hex number (8, 9, A, etc)
+ * @return set with all root paths related to given release in ct.sym file
+ */
+ public List<Path> releaseRoots(String releaseInHex) {
+ if (!exists()) {
+ return Collections.emptyList();
+ }
+ List<Path> list = this.releaseRootPaths.computeIfAbsent(releaseInHex, x -> {
+ List<Path> rootDirs = new ArrayList<>();
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root)) {
+ for (final Path subdir : stream) {
+ String rel = subdir.getFileName().toString();
+ if (rel.contains("-")) { //$NON-NLS-1$
+ // Ignore META-INF etc. We are only interested in A-F 0-9
+ continue;
+ }
+ // Line below looks crazy. Latest with release 24 (hex 18)
+ // we will find "8" release paths inside all release 24 related
+ // directories and with release 26 (hex 1A) we will match "10" release
+ // paths inside release 24 directories. I can't believe this is sane.
+ // But looks like similar code is in
+ // com.sun.tools.javac.platform.JDKPlatformProvider.PlatformDescriptionImpl.getFileManager()
+ // https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java
+ if (rel.contains(releaseInHex)) {
+ rootDirs.add(subdir);
+ } else {
+ continue;
+ }
+ }
+ } catch (IOException e) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(rootDirs);
+ });
+ return list;
+ }
+
+ /**
+ * Retrieves the full path in ct.sym file fro given signature file in given release
+ * <p>
+ * 12+: something like
+ * <p>
+ * java/io/Reader.sig -> /879/java.base/java/io/Reader.sig
+ * <p>
+ * before 12:
+ * <p>
+ * java/io/Reader.sig -> /8769/java/io/Reader.sig
+ *
+ * @param releaseInHex release number in hex
+ * @param qualifiedSignatureFileName signature file name (without module)
+ * @param moduleName
+ * @return corresponding path in ct.sym file system or null if not found
+ */
+ public Path getFullPath(String releaseInHex, String qualifiedSignatureFileName, String moduleName) {
+ String sep = this.fs.getSeparator();
+ if (DISABLE_CACHE) {
+ List<Path> releaseRoots = releaseRoots(releaseInHex);
+ for (Path rroot : releaseRoots) {
+ // Calculate file path
+ Path p = null;
+ if (isJRE12Plus()) {
+ if (moduleName == null) {
+ moduleName = getModuleInJre12plus(releaseInHex, qualifiedSignatureFileName);
+ }
+ p = rroot.resolve(moduleName + sep + qualifiedSignatureFileName);
+ } else {
+ p = rroot.resolve(qualifiedSignatureFileName);
+ }
+
+ // If file is known, read it from ct.sym
+ if (Files.exists(p)) {
+ if (VERBOSE) {
+ System.out.println("found: " + qualifiedSignatureFileName + " in " + p + " for module " + moduleName + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ return p;
+ }
+ }
+ if (VERBOSE) {
+ System.out.println("not found: " + qualifiedSignatureFileName + " for module " + moduleName); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return null;
+ }
+ Map<String, Path> releasePaths = getCachedReleasePaths(releaseInHex);
+ Path path;
+ if(moduleName != null) {
+ // Without this, org.eclipse.jdt.core.tests.model.ModuleBuilderTests.testConvertToModule() fails on 12+ JRE
+ path = releasePaths.get(moduleName + sep + qualifiedSignatureFileName);
+
+ // Special handling of broken module shema in java 11 for compilation with --release 10
+ if(path == null && !this.isJRE12Plus() && "A".equals(releaseInHex)){ //$NON-NLS-1$
+ path = releasePaths.get(qualifiedSignatureFileName);
+ }
+ } else {
+ path = releasePaths.get(qualifiedSignatureFileName);
+ }
+ if (VERBOSE) {
+ if (path != null) {
+ System.out.println("found: " + qualifiedSignatureFileName + " in " + path + " for module " + moduleName +"\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ } else {
+ System.out.println("not found: " + qualifiedSignatureFileName + " for module " + moduleName); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ return path;
+ }
+
+ private String getModuleInJre12plus(String releaseInHex, String qualifiedSignatureFileName) {
+ if (DISABLE_CACHE) {
+ return findModuleForFileInJre12plus(releaseInHex, qualifiedSignatureFileName);
+ }
+ Map<String, Path> releasePaths = getCachedReleasePaths(releaseInHex);
+ Path path = releasePaths.get(qualifiedSignatureFileName);
+ if (path != null && path.getNameCount() > 2) {
+ // First segment is release, second: module
+ return path.getName(1).toString();
+ }
+ return null;
+ }
+
+ private String findModuleForFileInJre12plus(String releaseInHex, String qualifiedSignatureFileName) {
+ for (Path rroot : releaseRoots(releaseInHex)) {
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(rroot)) {
+ for (final Path subdir : stream) {
+ Path p = subdir.resolve(qualifiedSignatureFileName);
+ if (Files.exists(p)) {
+ if (subdir.getNameCount() == 2) {
+ return subdir.getName(1).toString();
+ }
+ }
+ }
+ } catch (IOException e) {
+ // not found...
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Populates {@link #allReleasesPaths} with the paths of all files within each matching release directory in ct.sym.
+ * This cache is an optimization to avoid excessive calls into the zip filesystem in
+ * {@code ClasspathJrtWithReleaseOption#findClass(String, String, String, String, boolean, Predicate)}.
+ * <p>
+ * 12+: something like
+ * <p>
+ * java.base/javax/net/ssl/SSLSocketFactory.sig -> /89ABC/java.base/javax/net/ssl/SSLSocketFactory.sig
+ * <p> or
+ * javax/net/ssl/SSLSocketFactory.sig -> /89ABC/java.base/javax/net/ssl/SSLSocketFactory.sig
+ * <p>
+ * before 12: javax/net/ssl/SSLSocketFactory.sig -> /89ABC/java.base/javax/net/ssl/SSLSocketFactory.sig
+ */
+ private Map<String, Path> getCachedReleasePaths(String releaseInHex) {
+ Map<String, Path> result = this.allReleasesPaths.computeIfAbsent(releaseInHex, x -> {
+ List<Path> roots = releaseRoots(releaseInHex);
+ Map<String, Path> allReleaseFiles = new HashMap<>(4999);
+ for (Path start : roots) {
+ try {
+ Files.walk(start).filter(Files::isRegularFile).forEach(p -> {
+ if (isJRE12Plus()) {
+ // Don't use module name as part of the key
+ String binaryNameWithoutModule = p.subpath(2, p.getNameCount()).toString();
+ allReleaseFiles.put(binaryNameWithoutModule, p);
+ // Cache extra key with module added, see getFullPath().
+ String binaryNameWithModule = p.subpath(1, p.getNameCount()).toString();
+ allReleaseFiles.put(binaryNameWithModule, p);
+ } else {
+ String binaryNameWithoutModule = p.subpath(1, p.getNameCount()).toString();
+ allReleaseFiles.put(binaryNameWithoutModule, p);
+ }
+ });
+ } catch (IOException e) {
+ // Not much do to if we can't list the dir; anything in there will be treated
+ // as if it were missing.
+ }
+ }
+ return Collections.unmodifiableMap(allReleaseFiles);
+ });
+ return result;
+ }
+
+ public byte[] getFileBytes(Path path) throws IOException {
+ if (!exists()) {
+ return null;
+ }
+ if (DISABLE_CACHE) {
+ return JRTUtil.safeReadBytes(path);
+ } else {
+ Optional<byte[]> bytes = this.fileCache.computeIfAbsent(path, key -> {
+ try {
+ return Optional.ofNullable(JRTUtil.safeReadBytes(key));
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ });
+ if (VERBOSE) {
+ System.out.println("got bytes: " + path); //$NON-NLS-1$
+ }
+ return bytes.orElse(null);
+ }
+ }
+
+ private boolean isCurrentRelease12plus() throws IOException {
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root)) {
+ for (final Path subdir : stream) {
+ String rel = JRTUtil.sanitizedFileName(subdir);
+ if (rel.contains("-")) { //$NON-NLS-1$
+ continue;
+ }
+ try {
+ int version = Integer.parseInt(rel, 16);
+ // If a release directory contains "system-modules" file, it is a flag
+ // that this is the *current* release
+ if (version > 11 && Files.exists(this.fs.getPath(rel, "system-modules"))) { //$NON-NLS-1$
+ return true;
+ }
+ } catch (NumberFormatException e) {
+ // META-INF, A-modules etc
+ continue;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.jdkHome.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof CtSym)) {
+ return false;
+ }
+ CtSym other = (CtSym) obj;
+ return this.jdkHome.equals(other.jdkHome);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("CtSym ["); //$NON-NLS-1$
+ sb.append("file="); //$NON-NLS-1$
+ sb.append(this.ctSymFile);
+ sb.append(", exists="); //$NON-NLS-1$
+ sb.append(this.exists());
+ sb.append("]"); //$NON-NLS-1$
+ return sb.toString();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
index 685478e85..c109246d1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
@@ -23,7 +23,6 @@ import java.net.URLClassLoader;
import java.nio.channels.ClosedByInterruptException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
-import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
@@ -47,6 +46,8 @@ import org.eclipse.jdt.internal.compiler.env.IModule;
public class JRTUtil {
+ public static final boolean DISABLE_CACHE = Boolean.getBoolean("org.eclipse.jdt.disable_JRT_cache"); //$NON-NLS-1$
+
public static final String JAVA_BASE = "java.base"; //$NON-NLS-1$
public static final char[] JAVA_BASE_CHAR = JAVA_BASE.toCharArray();
static final String MODULES_SUBDIR = "/modules"; //$NON-NLS-1$
@@ -65,6 +66,11 @@ public class JRTUtil {
// TODO: Java 9 Think about clearing the cache too.
private static Map<String, Optional<JrtFileSystem>> images = new ConcurrentHashMap<>();
+ /**
+ * Map from JDK home path to ct.sym file (located in /lib in the JDK)
+ */
+ private static final Map<Path, CtSym> ctSymFiles = new ConcurrentHashMap<>();
+
public interface JrtFileVisitor<T> {
public FileVisitResult visitPackage(T dir, T mod, BasicFileAttributes attrs) throws IOException;
@@ -121,6 +127,10 @@ public class JRTUtil {
return system.orElse(null);
}
+ public static CtSym getCtSym(Path jdkHome) {
+ return ctSymFiles.computeIfAbsent(jdkHome, x -> new CtSym(x));
+ }
+
/** TEST ONLY (use when changing the "modules.to.load" property). */
public static void reset() {
images.clear();
@@ -207,8 +217,9 @@ class JrtFileSystemWithOlderRelease extends JrtFileSystem {
final String release;
String releaseInHex;
- private String[] subReleases;
+ private List<Path> releaseRoots = Collections.emptyList();
protected Path modulePath;
+ private CtSym ctSym;
/**
* The jrt file system is based on the location of the JRE home whose libraries
@@ -234,87 +245,60 @@ class JrtFileSystemWithOlderRelease extends JrtFileSystem {
super.initialize(jdk);
this.fs = null;// reset and proceed, TODO: this is crude and need to be removed.
this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
- Path ct = Paths.get(this.jdkHome, "lib", "ct.sym"); //$NON-NLS-1$ //$NON-NLS-2$
- if (!Files.exists(ct)) {
+ this.ctSym = JRTUtil.getCtSym(Paths.get(this.jdkHome));
+
+ if (!this.ctSym.exists()) {
return;
}
- URI uri = URI.create("jar:file:" + ct.toUri().getRawPath()); //$NON-NLS-1$
- try {
- this.fs = FileSystems.getFileSystem(uri);
- } catch(FileSystemNotFoundException fne) {
- // Ignore and move on
- }
- if (this.fs == null) {
- HashMap<String, ?> env = new HashMap<>();
- try {
- this.fs = FileSystems.newFileSystem(uri, env);
- } catch (IOException e) {
- return;
- }
- }
- Path releasePath = this.fs.getPath("/"); //$NON-NLS-1$
+ this.fs = this.ctSym.getFs();
if (!Files.exists(this.fs.getPath(this.releaseInHex))
|| Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
this.fs = null;
}
- List<String> sub = new ArrayList<>();
- try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(releasePath)) {
- for (final java.nio.file.Path subdir: stream) {
- String r = JRTUtil.sanitizedFileName(subdir);
- if (r.contains(this.releaseInHex)) {
- sub.add(r);
- } else {
- continue;
- }
- }
- }
- this.subReleases = sub.toArray(new String[0]);
+ this.releaseRoots = this.ctSym.releaseRoots(this.releaseInHex);
}
@Override
void walkModuleImage(final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, final int notify) throws IOException {
- if (this.subReleases != null && this.subReleases.length > 0) {
- for (String rel : this.subReleases) {
- Path p = this.fs.getPath(rel);
- Files.walkFileTree(p, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
- @Override
- public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
- throws IOException {
- int count = dir.getNameCount();
- if (count == 1) {
- return FileVisitResult.CONTINUE;
- }
- if (count == 2) {
- // e.g. /9A/java.base
- java.nio.file.Path mod = dir.getName(1);
- if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0
- && JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) {
- return FileVisitResult.SKIP_SUBTREE;
- }
- return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? FileVisitResult.CONTINUE
- : visitor.visitModule(dir, JRTUtil.sanitizedFileName(mod));
- }
- if ((notify & JRTUtil.NOTIFY_PACKAGES) == 0) {
- // client is not interested in packages
- return FileVisitResult.CONTINUE;
+ for (Path p : this.releaseRoots) {
+ Files.walkFileTree(p, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ int count = dir.getNameCount();
+ if (count == 1) {
+ return FileVisitResult.CONTINUE;
+ }
+ if (count == 2) {
+ // e.g. /9A/java.base
+ java.nio.file.Path mod = dir.getName(1);
+ if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0
+ && JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) {
+ return FileVisitResult.SKIP_SUBTREE;
}
- return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs);
+ return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? FileVisitResult.CONTINUE
+ : visitor.visitModule(dir, JRTUtil.sanitizedFileName(mod));
+ }
+ if ((notify & JRTUtil.NOTIFY_PACKAGES) == 0) {
+ // client is not interested in packages
+ return FileVisitResult.CONTINUE;
}
+ return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs);
+ }
- @Override
- public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs)
- throws IOException {
- if ((notify & JRTUtil.NOTIFY_FILES) == 0) {
- return FileVisitResult.CONTINUE;
- }
- // This happens when a file in a default package is present. E.g. /modules/some.module/file.name
- if (file.getNameCount() == 3) {
- cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString());
- }
- return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs);
+ @Override
+ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs)
+ throws IOException {
+ if ((notify & JRTUtil.NOTIFY_FILES) == 0) {
+ return FileVisitResult.CONTINUE;
}
- });
- }
+ // This happens when a file in a default package is present. E.g. /modules/some.module/file.name
+ if (file.getNameCount() == 3) {
+ cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString());
+ }
+ return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs);
+ }
+ });
}
}
@@ -326,7 +310,6 @@ class JrtFileSystem {
private final Map<String, List<String>> packageToModules = new HashMap<String, List<String>>();
- private static boolean DISABLE_CACHE = Boolean.getBoolean("org.eclipse.jdt.disable_JRT_cache"); //$NON-NLS-1$
private final Map<Path, Optional<byte[]>> classCache = new ConcurrentHashMap<>(10007);
@@ -501,7 +484,7 @@ class JrtFileSystem {
private byte[] getFileBytes(String fileName, String module) throws IOException {
Path path = this.fs.getPath(JRTUtil.MODULES_SUBDIR, module, fileName);
- if(DISABLE_CACHE) {
+ if(JRTUtil.DISABLE_CACHE) {
return JRTUtil.safeReadBytes(path);
} else {
try {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index 1280b5079..939ce12e9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -60,6 +60,7 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Receiver;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
@@ -1774,6 +1775,84 @@ class ASTConverter {
}
}
+ public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.RecordComponent component) {
+ SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+ setModifiers(variableDecl, component);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(component.name));
+ int start = component.sourceStart;
+ int nameEnd = component.sourceEnd;
+ name.setSourceRange(start, nameEnd - start + 1);
+ variableDecl.setName(name);
+ final int typeSourceEnd = component.type.sourceEnd;
+ TypeReference typeReference = component.type;
+ final int extraDimensions = typeReference.extraDimensions();
+ if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
+ setExtraAnnotatedDimensions(nameEnd + 1, typeSourceEnd, typeReference,
+ variableDecl.extraDimensions(), extraDimensions);
+ } else {
+ internalSetExtraDimensions(variableDecl, extraDimensions);
+ }
+ final boolean isVarArgs = component.isVarArgs();
+ if (isVarArgs && extraDimensions == 0) {
+ // remove the ellipsis from the type source end
+ component.type.sourceEnd = retrieveEllipsisStartPosition(component.type.sourceStart, typeSourceEnd);
+ }
+ Type type = convertType(component.type);
+ int typeEnd = type.getStartPosition() + type.getLength() - 1;
+ int rightEnd = Math.max(typeEnd, component.declarationSourceEnd);
+ /*
+ * There is extra work to do to set the proper type positions
+ * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+ */
+ if (isVarArgs) {
+ Dimension lastDimension = null;
+ if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
+ if (type.isArrayType()) { // should always be true
+ List dimensions = ((ArrayType) type).dimensions();
+ if (!dimensions.isEmpty()) {
+ lastDimension = (Dimension) dimensions.get(dimensions.size() - 1);
+ }
+ }
+ }
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391898
+ if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
+ if (lastDimension != null) { // should always be true
+ List annotations = lastDimension.annotations();
+ Iterator iter = annotations.iterator();
+ while (iter.hasNext()) {
+ Annotation annotation = (Annotation) iter.next();
+ annotation.setParent(null, null);
+ variableDecl.varargsAnnotations().add(annotation);
+ }
+ }
+ }
+ if (extraDimensions != 0) {
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ } else {
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+ }
+ variableDecl.setSourceRange(component.declarationSourceStart, rightEnd - component.declarationSourceStart + 1);
+
+ if (isVarArgs) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ break;
+ default :
+ variableDecl.setVarargs(true);
+ }
+ }
+ if (this.resolveBindings) {
+ recordNodes(name, component);
+ recordNodes(variableDecl, component);
+ variableDecl.resolveBinding();
+ }
+ return variableDecl;
+ }
+
public Assignment convert(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment expression) {
Assignment assignment = new Assignment(this.ast);
Expression lhs = convert(expression.lhs);
@@ -3873,10 +3952,10 @@ class ASTConverter {
recordDeclaration.typeParameters().add(convert(typeParameter));
}
}
- Argument[] args = typeDeclaration.args;
- if (args != null) {
- for (Argument arg : args) {
- recordDeclaration.recordComponents().add(convert(arg));
+ RecordComponent[] recComps = typeDeclaration.recordComponents;
+ if (recComps != null) {
+ for (RecordComponent recComp : recComps) {
+ recordDeclaration.recordComponents().add(convert(recComp));
}
}
buildBodyDeclarations(typeDeclaration, recordDeclaration, false);
@@ -6213,6 +6292,86 @@ class ASTConverter {
}
/**
+ * @param variableDecl
+ * @param component
+ *
+ * TODO: just plain copy of sM(SVD, Argument) - need to cut the flab here.
+ */
+ protected void setModifiers(SingleVariableDeclaration variableDecl, RecordComponent component) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.internalSetModifiers(component.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ if (component.annotations != null) {
+ variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ break;
+ default :
+ this.scanner.resetTo(component.declarationSourceStart, component.sourceStart);
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = component.annotations;
+ int indexInAnnotations = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestrictfp:
+ modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameAT :
+ // we have an annotation
+ if (annotations != null && indexInAnnotations < annotations.length) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+ modifier = convert(annotation);
+ this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+ }
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDecl.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+ /**
* @param typeDecl
* @param typeDeclaration
*/
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 65c1a1293..418954ad4 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -274,6 +274,7 @@ class DefaultBindingResolver extends BindingResolver {
return getModuleBinding((org.eclipse.jdt.internal.compiler.lookup.ModuleBinding) binding);
case Binding.FIELD:
case Binding.LOCAL:
+ case Binding.RECORD_COMPONENT:
return getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.VariableBinding) binding);
}
return null;
@@ -2088,6 +2089,9 @@ class DefaultBindingResolver extends BindingResolver {
if (abstractVariableDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
variableBinding = this.getVariableBinding(fieldDeclaration.binding, variable);
+ } else if (abstractVariableDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.RecordComponent) {
+ org.eclipse.jdt.internal.compiler.ast.RecordComponent recordComponent = (org.eclipse.jdt.internal.compiler.ast.RecordComponent) abstractVariableDeclaration;
+ variableBinding = this.getVariableBinding(recordComponent.binding, variable);
} else {
variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding, variable);
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
index 919dc28c8..320cbe865 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
@@ -28,6 +28,7 @@ import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.RecordComponentBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.core.JavaElement;
@@ -279,6 +280,9 @@ class VariableBinding implements IVariableBinding {
char[] typeSig = this.binding.type.genericTypeSignature();
JavaElement parent = null;
IMethodBinding declaringMethod = getDeclaringMethod();
+ if (this.binding instanceof RecordComponentBinding) {
+ return null; // TODO : SEE Bug 562736/ BUG 562637
+ }
final LocalVariableBinding localVariableBinding = (LocalVariableBinding) this.binding;
if (declaringMethod == null) {
ReferenceContext referenceContext = localVariableBinding.declaringScope.referenceContext();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java
index 6a80b780e..34f95335e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java
@@ -90,5 +90,13 @@ boolean isEnumConstant() throws JavaModelException;
* @since 3.1
*/
boolean isResolved();
+/**
+ * Returns whether this field represents a record component.
+ *
+ * @return whether this field represents a record component.
+ * @throws JavaModelException
+ * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
+ */
+boolean isRecordComponent() throws JavaModelException;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
index e511ae155..0d16aaf89 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
@@ -523,6 +523,7 @@ public interface IType extends IMember, IAnnotatable {
/**
* Returns the fields declared by this type in the order in which they appear
* in the source or class file. For binary types, this includes synthetic fields.
+ * This does not include the implicit fields representing record components.
*
* @exception JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource.
@@ -913,6 +914,28 @@ public interface IType extends IMember, IAnnotatable {
* @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
*/
boolean isRecord() throws JavaModelException;
+ /**
+ * Returns the record components declared by this record class, or an empty
+ * array if this is not a record.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return record components declared by this record class
+ * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
+ */
+ default IField[] getRecordComponents() throws JavaModelException {
+ return null;
+ }
+ /**
+ * Returns the record component with the specified name
+ * in this type (for example, <code>"bar"</code>).
+ * This is a handle-only method. The record component may or may not exist.
+ *
+ * @param name the given name
+ * @return the record component with the specified name in this record
+ * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
+ */
+ IField getRecordComponent(String name);
/**
* Returns whether this type represents an interface.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
index 042e28458..5866cafac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,6 +14,12 @@
*******************************************************************************/
package org.eclipse.jdt.core;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
@@ -46,6 +52,37 @@ public final class JavaConventions {
private static final Pattern DOT_DOT = Pattern.compile("(\\.)(\\1)+"); //$NON-NLS-1$
private static final Pattern PREFIX_JAVA = Pattern.compile("java$"); //$NON-NLS-1$
private static final Scanner SCANNER = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
+ private static Map<String, Set<String>> restrictedIdentifiersMap, restrictedIdentifierPreviewMap;
+ private static List<String> javaVersions;
+ private static String VAR_ID = "var"; //$NON-NLS-1$
+ private static String YIELD_ID = "yield"; //$NON-NLS-1$
+ private static String RECORD_ID = "record"; //$NON-NLS-1$
+
+ static {
+ javaVersions= new ArrayList<String>();
+ javaVersions.add(0, CompilerOptions.VERSION_10);
+ javaVersions.add(1, CompilerOptions.VERSION_11);
+ javaVersions.add(2, CompilerOptions.VERSION_12);
+ javaVersions.add(3, CompilerOptions.VERSION_13);
+ javaVersions.add(4, CompilerOptions.VERSION_14);
+
+ restrictedIdentifiersMap= new HashMap<>();
+ //restricted identifier for Java10 and above
+ Set<String> set= new HashSet<String>();
+ set.add(new String(VAR_ID));
+ restrictedIdentifiersMap.put(CompilerOptions.VERSION_10, set);
+ //restricted identifier for Java14 and above
+ set= new HashSet<String>();
+ set.add(new String(YIELD_ID));
+ restrictedIdentifiersMap.put(CompilerOptions.VERSION_14, set);
+
+ restrictedIdentifierPreviewMap= new HashMap<>();
+ //restricted identifier for Java10 and above
+ set= new HashSet<String>();
+ set.add(new String(RECORD_ID));
+ restrictedIdentifierPreviewMap.put(CompilerOptions.VERSION_14, set);
+
+ }
//{ObjectTeams: be conservative: this class has no context so cannot distinguish OT vs. Java projects, always assume pure Java:
static {
@@ -80,16 +117,25 @@ public final class JavaConventions {
/*
* Returns the current identifier extracted by the scanner (without unicode
- * escapes) from the given id and for the given source and compliance levels.
+ * escapes) from the given id and for the given source and compliance levels and preview enabled flag.
* Returns <code>null</code> if the id was not valid
*/
private static synchronized char[] scannedIdentifier(String id, String sourceLevel, String complianceLevel) {
+ return scannedIdentifier( id, sourceLevel, complianceLevel, null, true);
+ }
+ /*
+ * Returns the current identifier extracted by the scanner (without unicode
+ * escapes) from the given id and for the given source and compliance levels and preview enabled flag.
+ * Returns <code>null</code> if the id was not valid
+ */
+ private static synchronized char[] scannedIdentifier(String id, String sourceLevel, String complianceLevel, String previewEnabled, boolean allowRestrictedKeyWords) {
if (id == null) {
return null;
}
// Set scanner for given source and compliance levels
SCANNER.sourceLevel = sourceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(sourceLevel);
SCANNER.complianceLevel = complianceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(complianceLevel);
+ SCANNER.previewEnabled = previewEnabled == null ? false : JavaCore.ENABLED.equals(previewEnabled);
try {
SCANNER.setSource(id.toCharArray());
@@ -97,7 +143,9 @@ public final class JavaConventions {
if (token != TerminalTokens.TokenNameIdentifier) return null;
if (SCANNER.currentPosition == SCANNER.eofPosition) { // to handle case where we had an ArrayIndexOutOfBoundsException
try {
- return SCANNER.getCurrentIdentifierSource();
+ char[] src= SCANNER.getCurrentIdentifierSource();
+ src= scanForRestrictedKeyWords(src, sourceLevel, complianceLevel, SCANNER.previewEnabled, allowRestrictedKeyWords);
+ return src;
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
@@ -110,6 +158,30 @@ public final class JavaConventions {
}
}
+ private static char[] scanForRestrictedKeyWords(char[] id, String sourceLevel, String complianceLevel, boolean previewEnabled, boolean allowRestrictedKeyWords) {
+ if (allowRestrictedKeyWords) {
+ return id;
+ }
+ int index= javaVersions.indexOf(sourceLevel);
+ String searchId= new String(id);
+ for (int i=index; i>=0; i--) {
+ String level= javaVersions.get(i);
+ if (level != null) {
+ Set<String> rIds= restrictedIdentifiersMap.get(level);
+ if (rIds != null && rIds.contains(searchId)) {
+ return null;
+ }
+ if (previewEnabled) {
+ Set<String> prIds= restrictedIdentifierPreviewMap.get(level);
+ if (prIds != null && prIds.contains(searchId)) {
+ return null;
+ }
+ }
+ }
+ }
+ return id;
+ }
+
/**
* Validate the given compilation unit name.
* <p>
@@ -435,8 +507,57 @@ public final class JavaConventions {
* @see JavaCore#VERSION_1_7
* @see JavaCore#VERSION_1_8
* @see JavaCore#VERSION_9
+ * @deprecated
*/
public static IStatus validateJavaTypeName(String name, String sourceLevel, String complianceLevel) {
+ return internalValidateJavaTypeName(name, sourceLevel, complianceLevel, null);
+ }
+
+ /**
+ * Validate the given Java type name, either simple or qualified, for the given source level, compliance levels
+ * and the preview flag.
+ *
+ * <p>For example, <code>"java.lang.Object"</code>, or <code>"Object"</code>.</p>
+ *
+ * <p>The source level and compliance level values should be taken from the constant defined inside
+ * {@link JavaCore} class. The constants are named <code>JavaCore#VERSION_1_x</code>, x being set
+ * between '1' and '8'.
+ * </p>
+ * <p>The preview flag should be one of <code>JavaCore.ENABLED</code>, <code>JavaCore#DISABLED</code> or null.
+ * When null is passed, the preview is considered to be disabled.
+ * </p>
+ *
+ * @param name the name of a type
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @param previewEnabled preview flag
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a Java type name,
+ * a status with code <code>IStatus.WARNING</code>
+ * indicating why the given name is discouraged,
+ * otherwise a status object indicating what is wrong with
+ * the name
+ * @since 3.22
+ * @see JavaCore#VERSION_1_1
+ * @see JavaCore#VERSION_1_2
+ * @see JavaCore#VERSION_1_3
+ * @see JavaCore#VERSION_1_4
+ * @see JavaCore#VERSION_1_5
+ * @see JavaCore#VERSION_1_6
+ * @see JavaCore#VERSION_1_7
+ * @see JavaCore#VERSION_1_8
+ * @see JavaCore#VERSION_9
+ * @see JavaCore#VERSION_10
+ * @see JavaCore#VERSION_11
+ * @see JavaCore#VERSION_12
+ * @see JavaCore#VERSION_13
+ * @see JavaCore#VERSION_14
+ */
+ public static IStatus validateJavaTypeName(String name, String sourceLevel, String complianceLevel, String previewEnabled) {
+ return internalValidateJavaTypeName(name, sourceLevel, complianceLevel, previewEnabled);
+ }
+
+ private static IStatus internalValidateJavaTypeName(String name, String sourceLevel, String complianceLevel, String previewEnabled) {
if (name == null) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null);
}
@@ -448,7 +569,7 @@ public final class JavaConventions {
char[] scannedID;
if (index == -1) {
// simple name
- scannedID = scannedIdentifier(name, sourceLevel, complianceLevel);
+ scannedID = scannedIdentifier(name, sourceLevel, complianceLevel, previewEnabled, false);
} else {
// qualified name
String pkg = name.substring(0, index).trim();
@@ -457,7 +578,7 @@ public final class JavaConventions {
return status;
}
String type = name.substring(index + 1).trim();
- scannedID = scannedIdentifier(type, sourceLevel, complianceLevel);
+ scannedID = scannedIdentifier(type, sourceLevel, complianceLevel, previewEnabled, false);
}
if (scannedID != null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
index 7e7782fb8..42de861ac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
@@ -24,6 +24,7 @@ import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
@@ -168,6 +169,18 @@ public interface ISourceElementRequestor {
public FieldDeclaration node;
}
+ public static class RecordComponentInfo {
+ public boolean typeAnnotated;
+ public int declarationStart;
+ public int modifiers;
+ public char[] type;
+ public char[] name;
+ public int nameSourceStart;
+ public int nameSourceEnd;
+ public char[][] categories;
+ public Annotation[] annotations;
+ public RecordComponent node;
+ }
void acceptAnnotationTypeReference(char[][] annotation, int sourceStart, int sourceEnd);
void acceptAnnotationTypeReference(char[] annotation, int sourcePosition);
@@ -231,6 +244,8 @@ public interface ISourceElementRequestor {
void enterMethod(MethodInfo methodInfo);
+ void enterRecordComponent(RecordComponentInfo recordComponentInfo);
+
void enterType(TypeInfo typeInfo);
void exitCompilationUnit(int declarationEnd);
@@ -243,6 +258,8 @@ public interface ISourceElementRequestor {
*/
void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd);
+ void exitRecordComponent(int declarationEnd, int declarationSourceEnd);
+
void exitInitializer(int declarationEnd);
void exitMethod(int declarationEnd, Expression defaultValue);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java
index ed3130524..63f85d59a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java
@@ -49,6 +49,7 @@ import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.RecordComponent;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
@@ -801,6 +802,8 @@ protected void notifySourceElementRequestor(FieldDeclaration fieldDeclaration, T
fieldInfo.declarationStart = fieldDeclaration.declarationSourceStart;
fieldInfo.name = fieldDeclaration.name;
fieldInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
+ if (fieldDeclaration.isARecordComponent)
+ fieldInfo.modifiers |= ExtraCompilerModifiers.AccRecord;
fieldInfo.type = typeName;
fieldInfo.nameSourceStart = fieldDeclaration.sourceStart;
fieldInfo.nameSourceEnd = fieldDeclaration.sourceEnd;
@@ -884,6 +887,40 @@ protected void notifySourceElementRequestor(ModuleDeclaration moduleDeclaration)
this.requestor.exitModule(moduleDeclaration.declarationSourceEnd);
}
}
+protected void notifySourceElementRequestor(RecordComponent recordComponent, TypeDeclaration declaringType) {
+ assert declaringType.isRecord();
+
+ // range check
+ boolean isInRange =
+ this.initialPosition <= recordComponent.declarationSourceStart
+ && this.eofPosition >= recordComponent.declarationSourceEnd;
+ int recordComponentEndPosition = this.sourceEnds.get(recordComponent);
+ if (recordComponentEndPosition == -1) {
+ // use the declaration source end by default
+ recordComponentEndPosition = recordComponent.declarationSourceEnd;
+ }
+ if (isInRange) {
+ char[] typeName = CharOperation.concatWith(recordComponent.type.getParameterizedTypeName(), '.');
+ ISourceElementRequestor.RecordComponentInfo recordComponentInfo = new ISourceElementRequestor.RecordComponentInfo();
+ recordComponentInfo.typeAnnotated = ((recordComponent.bits & ASTNode.HasTypeAnnotations) != 0);
+ recordComponentInfo.declarationStart = recordComponent.declarationSourceStart;
+ recordComponentInfo.name = recordComponent.name;
+ recordComponentInfo.type = typeName;
+ recordComponentInfo.nameSourceStart = recordComponent.sourceStart;
+ recordComponentInfo.nameSourceEnd = recordComponent.sourceEnd;
+ recordComponentInfo.categories = this.nodesToCategories.get(recordComponent);
+ recordComponentInfo.annotations = recordComponent.annotations;
+ recordComponentInfo.node = recordComponent;
+ this.requestor.enterRecordComponent(recordComponentInfo);
+ }
+ this.visitIfNeeded(recordComponent, declaringType);
+ if (isInRange){
+ this.requestor.exitRecordComponent(
+ recordComponentEndPosition,
+ recordComponent.declarationSourceEnd);
+ }
+
+}
protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) {
//{ObjectTeams: don't convert generated types (role ifc part):
@@ -903,18 +940,21 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
//{ObjectTeams: treatment for method mappings
AbstractMethodMappingDeclaration[] bindings = typeDeclaration.callinCallouts;
//ak}
+ RecordComponent[] recordComponents = typeDeclaration.recordComponents;
int fieldCounter = fields == null ? 0 : fields.length;
int methodCounter = methods == null ? 0 : methods.length;
int memberTypeCounter = memberTypes == null ? 0 : memberTypes.length;
//{ObjectTeams: treatment for method mappings
int bindingCount = (bindings == null) ? 0 : bindings.length;
//ak}
+ int recordComponentCounter = recordComponents == null ? 0 : recordComponents.length;
int fieldIndex = 0;
int methodIndex = 0;
int memberTypeIndex = 0;
//ObjectTeams: treatment for method mappings
int bindingIndex = 0;
//ak}
+ int recordComponentIndex = 0;
if (notifyTypePresence){
char[][] interfaceNames = getInterfaceNames(typeDeclaration);
@@ -1022,6 +1062,8 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
while ((fieldIndex < fieldCounter)
|| (memberTypeIndex < memberTypeCounter)
|| (methodIndex < methodCounter)
+ || (methodIndex < methodCounter)
+ || (recordComponentIndex < recordComponentCounter)
// {ObjectTeams: treatment for method mappings
|| (bindingIndex < bindingCount))
// orig:
@@ -1032,6 +1074,7 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
// :giro
AbstractMethodMappingDeclaration nextBindingDeclaration = null;
//ak}
+ RecordComponent nextRecordComponent = null;
int position = Integer.MAX_VALUE;
int nextDeclarationType = -1;
@@ -1056,6 +1099,13 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
nextDeclarationType = 2; // MEMBER
}
}
+ if (recordComponentIndex < recordComponentCounter) {
+ nextRecordComponent = recordComponents[recordComponentIndex];
+ if (nextRecordComponent.declarationSourceStart < position) {
+ position = nextRecordComponent.declarationSourceStart;
+ nextDeclarationType = 3; // RECORD_COMPONENT
+ }
+ }
//{ObjectTeams: treatment for method mappings
if (bindingIndex < bindingCount)
{
@@ -1063,7 +1113,7 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
if (nextBindingDeclaration.sourceStart < position)
{
position = nextBindingDeclaration.sourceStart;
- nextDeclarationType = 3; // BINDING
+ nextDeclarationType = 4; // BINDING
}
}
//ak}
@@ -1075,6 +1125,8 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
&& CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, nextFieldDeclaration.name))
break;
// SH}
+// if (typeDeclaration.isRecord() && nextFieldDeclaration.isARecordComponent)
+// break;
notifySourceElementRequestor(nextFieldDeclaration, typeDeclaration);
break;
case 1 :
@@ -1093,9 +1145,14 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
&& CharOperation.equals(IOTConstants.CONFINED, nextMemberDeclaration.name))
break;
notifySourceElementRequestor(nextMemberDeclaration, true, null, currentPackage);
-//{ObjectTeams: treatment for method mappings
+// SH}
+ break;
+ case 3 :
+ recordComponentIndex++;
+ notifySourceElementRequestor(nextRecordComponent, typeDeclaration);
break;
- case 3:
+//{ObjectTeams: treatment for method mappings
+ case 4:
bindingIndex++;
notifySourceElementRequestor(nextBindingDeclaration);
break;
@@ -1253,6 +1310,19 @@ private void visitIfNeeded(FieldDeclaration field, TypeDeclaration declaringType
}
}
}
+private void visitIfNeeded(RecordComponent component, TypeDeclaration declaringType) {
+ if (this.localDeclarationVisitor != null
+ && (component.bits & ASTNode.HasLocalType) != 0) {
+ if (component.initialization != null) {
+ try {
+ this.localDeclarationVisitor.pushDeclaringType(declaringType);
+ component.initialization.traverse(this.localDeclarationVisitor, (MethodScope) null);
+ } finally {
+ this.localDeclarationVisitor.popDeclaringType();
+ }
+ }
+ }
+}
private void visitIfNeeded(Initializer initializer) {
if (this.localDeclarationVisitor != null
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
index add1fd1d5..f14f22009 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
@@ -182,6 +182,10 @@ public class SourceElementRequestorAdapter implements ISourceElementRequestor {
}
@Override
+ public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
+ // default implementation: do nothing
+ }
+ @Override
public void enterType(TypeInfo typeInfo) {
// default implementation: do nothing
}
@@ -233,6 +237,12 @@ public class SourceElementRequestorAdapter implements ISourceElementRequestor {
public void exitType(int declarationEnd) {
// default implementation: do nothing
}
+
+ @Override
+ public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ // default implementation: do nothing
+ }
+
//{OTDTUI: added default implementation to corresponding extension in ISourceElementRequestor
@Override
public void enterCalloutMapping(CalloutInfo calloutInfo)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index abf5a9292..e5c5c39c0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -35,6 +35,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
+import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
@@ -298,6 +299,30 @@ public class SourceTypeConverter extends TypeConverter {
/*
* Convert a field source element into a parsed field declaration
*/
+ private RecordComponent convertRecordComponents(SourceField component,
+ TypeDeclaration type,
+ CompilationResult compilationResult) throws JavaModelException {
+
+ SourceFieldElementInfo compInfo = (SourceFieldElementInfo) component.getElementInfo();
+ RecordComponent comp = new RecordComponent(null, -1, -1);
+
+ int start = compInfo.getNameSourceStart();
+ int end = compInfo.getNameSourceEnd();
+
+ comp.name = component.getElementName().toCharArray();
+ comp.sourceStart = start;
+ comp.sourceEnd = end;
+ comp.declarationSourceStart = compInfo.getDeclarationSourceStart();
+ comp.declarationSourceEnd = compInfo.getDeclarationSourceEnd();
+ comp.type = createTypeReference(compInfo.getTypeName(), start, end);
+
+ /* convert annotations */
+ comp.annotations = convertAnnotations(component);
+ return comp;
+ }
+ /*
+ * Convert a record component source element into a parsed record component declaration
+ */
private FieldDeclaration convert(SourceField fieldHandle, TypeDeclaration type, CompilationResult compilationResult) throws JavaModelException {
SourceFieldElementInfo fieldInfo = (SourceFieldElementInfo) fieldHandle.getElementInfo();
@@ -549,6 +574,11 @@ public class SourceTypeConverter extends TypeConverter {
// The first choice constructor that takes CompilationResult as arg is not setting all the fields
// Hence, use the one that does
type.modifiers |= ExtraCompilerModifiers.AccRecord;
+ IField[] recordComponents = typeHandle.getRecordComponents();
+ type.recordComponents = new RecordComponent[recordComponents.length];
+ for(int i = 0; i < recordComponents.length; i++) {
+ type.recordComponents[i] = convertRecordComponents((SourceField)recordComponents[i], type, compilationResult);
+ }
}
if (typeInfo.getEnclosingType() == null) {
if (typeHandle.isAnonymous()) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java
index e2bfa9eff..a56925643 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/TypeConverter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2015 IBM Corporation and others.
+ * Copyright (c) 2008, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -69,11 +69,13 @@ public abstract class TypeConverter {
protected ProblemReporter problemReporter;
protected boolean has1_5Compliance;
+ protected boolean has14_Compliance;
private char memberTypeSeparator;
protected TypeConverter(ProblemReporter problemReporter, char memberTypeSeparator) {
this.problemReporter = problemReporter;
this.has1_5Compliance = problemReporter.options.originalComplianceLevel >= ClassFileConstants.JDK1_5;
+ this.has14_Compliance = problemReporter.options.originalComplianceLevel >= ClassFileConstants.JDK14;
this.memberTypeSeparator = memberTypeSeparator;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
index 7e9b40fd5..0428c85f0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -136,4 +136,8 @@ public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelExcep
if (javadocContents == null) return null;
return javadocContents.getFieldDoc(this);
}
+@Override
+public boolean isRecordComponent() throws JavaModelException {
+ return false;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
index 517a8e9fe..dc7c301d5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -339,20 +339,50 @@ public int getElementType() {
public IField getField(String fieldName) {
return new BinaryField(this, fieldName);
}
-
@Override
public IField[] getFields() throws JavaModelException {
- ArrayList list = getChildrenOfType(FIELD);
- int size;
- if ((size = list.size()) == 0) {
- return NO_FIELDS;
- } else {
- IField[] array= new IField[size];
+ if (!isRecord()) {
+ ArrayList list = getChildrenOfType(FIELD);
+ if (list.size() == 0) {
+ return NO_FIELDS;
+ }
+ IField[] array= new IField[list.size()];
list.toArray(array);
return array;
}
+ return getFieldsOrComponents(false);
+}
+@Override
+public IField[] getRecordComponents() throws JavaModelException {
+ if (!isRecord())
+ return new IField[0];
+ return getFieldsOrComponents(true);
+}
+private IField[] getFieldsOrComponents(boolean component) throws JavaModelException {
+ ArrayList list = getChildrenOfType(FIELD);
+ if (list.size() == 0) {
+ return NO_FIELDS;
+ }
+ ArrayList<IField> fields = new ArrayList<>();
+ for (Object object : list) {
+ IField field = (IField) object;
+ if (field.isRecordComponent() == component)
+ fields.add(field);
+ }
+ IField[] array= new IField[fields.size()];
+ fields.toArray(array);
+ return array;
+}
+@Override
+public IField getRecordComponent(String compName) {
+ try {
+ if (isRecord())
+ return new BinaryField(this, compName);
+ } catch (JavaModelException e) {
+ //
+ }
+ return null;
}
-
@Override
public int getFlags() throws JavaModelException {
IBinaryType info = (IBinaryType) getElementInfo();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index 797fa7c96..615ad5088 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -259,6 +259,16 @@ protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) {
String fieldName = JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name));
return new SourceField(parent, fieldName);
}
+protected SourceField createRecordComponent(JavaElement parent, RecordComponentInfo compInfo) {
+ String name = JavaModelManager.getJavaModelManager().intern(new String(compInfo.name));
+ SourceField field = new SourceField(parent, name) {
+ @Override
+ public boolean isRecordComponent() throws JavaModelException {
+ return true;
+ }
+ };
+ return field;
+}
protected ImportContainer createImportContainer(ICompilationUnit parent) {
return (ImportContainer)parent.getImportContainer();
}
@@ -779,6 +789,40 @@ public void exitField(int initializationStart, int declarationEnd, int declarati
* @see ISourceElementRequestor
*/
@Override
+public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ JavaElement handle = (JavaElement) this.handleStack.peek();
+ RecordComponentInfo compInfo = (RecordComponentInfo) this.infoStack.peek();
+ IJavaElement[] elements = getChildren(compInfo);
+ SourceFieldElementInfo info = elements.length == 0 ? new SourceFieldElementInfo() : new SourceFieldWithChildrenInfo(elements);
+ info.isRecordComponent = true;
+ info.setNameSourceStart(compInfo.nameSourceStart);
+ info.setNameSourceEnd(compInfo.nameSourceEnd);
+ info.setSourceRangeStart(compInfo.declarationStart);
+ info.setFlags(compInfo.modifiers);
+ char[] typeName = JavaModelManager.getJavaModelManager().intern(compInfo.type);
+ info.setTypeName(typeName);
+ this.newElements.put(handle, info);
+
+ if (compInfo.annotations != null) {
+ int length = compInfo.annotations.length;
+ this.unitInfo.annotationNumber += length;
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = compInfo.annotations[i];
+ acceptAnnotation(annotation, info, handle);
+ }
+ }
+ info.setSourceRangeEnd(declarationSourceEnd);
+ this.handleStack.pop();
+ this.infoStack.pop();
+
+ if (compInfo.typeAnnotated) {
+ this.unitInfo.annotationNumber = CompilationUnitElementInfo.ANNOTATION_THRESHOLD_FOR_DIET_PARSE;
+ }
+}
+/**
+ * @see ISourceElementRequestor
+ */
+@Override
public void exitInitializer(int declarationEnd) {
JavaElement handle = (JavaElement) this.handleStack.peek();
int[] initializerInfo = (int[]) this.infoStack.peek();
@@ -964,6 +1008,26 @@ protected Object getMemberValue(org.eclipse.jdt.internal.core.MemberValuePair me
return null;
}
}
+@Override
+public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
+ TypeInfo parentInfo = (TypeInfo) this.infoStack.peek();
+ JavaElement parentHandle= (JavaElement) this.handleStack.peek();
+ SourceField handle = null;
+ if (parentHandle.getElementType() == IJavaElement.TYPE) {
+ handle = createRecordComponent(parentHandle, recordComponentInfo);
+ }
+ else {
+ Assert.isTrue(false); // Should not happen
+ }
+ resolveDuplicates(handle);
+
+ addToChildren(parentInfo, handle);
+ parentInfo.childrenCategories.put(handle, recordComponentInfo.categories);
+
+ this.infoStack.push(recordComponentInfo);
+ this.handleStack.push(handle);
+}
+
//{OTDTUI: added implementation to corresponding extension in ISourceElementRequestor
@Override
public void exitCallinMapping(int sourceEnd, int declarationSourceEnd)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 7aad5d08c..9a916030b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -19,6 +19,7 @@ package org.eclipse.jdt.internal.core;
import java.io.*;
import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
@@ -448,6 +449,7 @@ public class JavaProject
String existingMessage = cycleMarker.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$
String newMessage = new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE,
project, cycleString.toString()).getMessage();
+ newMessage = truncateIfNecessary(newMessage);
if (!newMessage.equals(existingMessage)) {
cycleMarker.setAttribute(IMarker.MESSAGE, newMessage);
}
@@ -466,6 +468,18 @@ public class JavaProject
}
}
+ static String truncateIfNecessary(String markerMessage) {
+ // cf. org.eclipse.core.internal.resources.MarkerInfo.checkValidAttribute(Object)
+ if (markerMessage.length() > 21000) {
+ byte[] bytes = markerMessage.getBytes(StandardCharsets.UTF_8);
+ if (bytes.length > 65535) {
+ bytes = Arrays.copyOfRange(bytes, 0, 65500);
+ markerMessage = new String(bytes, StandardCharsets.UTF_8)+"..."; //$NON-NLS-1$
+ }
+ }
+ return markerMessage;
+ }
+
/**
* Adds a builder to the build spec for the given project.
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
index 7883d8444..5f958a60e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2017 IBM Corporation and others.
+ * Copyright (c) 2009, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -82,14 +82,13 @@ public class JavadocContents {
if (this.typeDocRange != null) {
if (this.typeDocRange == UNKNOWN_FORMAT) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this.type));
- return String.valueOf(CharOperation.subarray(this.content, this.typeDocRange[0], this.typeDocRange[1]));
+ return new String(this.content, this.typeDocRange[0], this.typeDocRange[1] - this.typeDocRange[0]);
}
return null;
}
public String getPackageDoc() throws JavaModelException {
if (this.content == null) return null;
- int[] range = null;
int index = CharOperation.indexOf(JavadocConstants.PACKAGE_DESCRIPTION_START2, this.content, false, 0);
if (index == -1) {
index = CharOperation.indexOf(JavadocConstants.PACKAGE_DESCRIPTION_START, this.content, false, 0);
@@ -109,8 +108,7 @@ public class JavadocContents {
if (index != -1) {
int end = CharOperation.indexOf(JavadocConstants.BOTTOM_NAVBAR, this.content, false, index);
if (end == -1) end = this.content.length -1;
- range = new int[]{index, end};
- return String.valueOf(CharOperation.subarray(this.content, range[0], range[1]));
+ return new String(this.content, index, end - index);
}
return null;
}
@@ -121,7 +119,7 @@ public class JavadocContents {
if (index == -1) return null;
int end = CharOperation.indexOf(JavadocConstants.BOTTOM_NAVBAR, this.content, false, index);
if (end == -1) end = this.content.length -1;
- return String.valueOf(CharOperation.subarray(this.content, index, end));
+ return new String(this.content, index, end - index);
}
/*
@@ -146,7 +144,7 @@ public class JavadocContents {
if (range != null) {
if (range == UNKNOWN_FORMAT) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, child));
- return String.valueOf(CharOperation.subarray(this.content, range[0], range[1]));
+ return new String(this.content, range[0], range[1] - range[0]);
}
return null;
}
@@ -175,7 +173,7 @@ public class JavadocContents {
if (range == UNKNOWN_FORMAT) {
throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, child));
}
- return String.valueOf(CharOperation.subarray(this.content, range[0], range[1]));
+ return new String(this.content, range[0], range[1] - range[0]);
}
return null;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index e402b9935..040a89c90 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -673,14 +673,14 @@ protected void acceptSourceMethod(
if (this.elementIndex == -1) {
try {
if (type.isRecord()) {
- IField field= type.getField(name);
- if (field != null) {
- if (!Flags.isStatic(field.getFlags())) {
+ IField comp = type.getRecordComponent(name);
+ if (comp != null) {
+ if (!Flags.isStatic(comp.getFlags())) {
// no match was actually found, but a method was originally given -> default accessor
- addElement(field);
+ addElement(comp);
if(SelectionEngine.DEBUG){
System.out.print("SELECTION - accept field("); //$NON-NLS-1$
- System.out.print(field.toString());
+ System.out.print(comp.toString());
System.out.println(")"); //$NON-NLS-1$
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
index 47cf74f2d..c171d5f9c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -179,4 +179,9 @@ protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean s
}
}
}
+@Override
+public boolean isRecordComponent() throws JavaModelException {
+ SourceFieldElementInfo info = (SourceFieldElementInfo) getElementInfo();
+ return info.isRecordComponent;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
index 950cc6048..c525afe0b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -34,6 +34,7 @@ public class SourceFieldElementInfo extends AnnotatableInfo implements ISourceFi
* The field's initializer string (if the field is a constant).
*/
protected char[] initializationSource;
+ protected boolean isRecordComponent;
/*
* Returns the initialization source for this field.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
index 56db33fa6..039200a59 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -917,6 +917,24 @@ public class SourceMapper
addCategories(field, fieldInfo.categories);
}
}
+ /**
+ * @see ISourceElementRequestor
+ */
+ @Override
+ public void enterRecordComponent(RecordComponentInfo compInfo) {
+ if (this.typeDepth >= 0) {
+ this.memberDeclarationStart[this.typeDepth] = compInfo.declarationStart;
+ this.memberNameRange[this.typeDepth] =
+ new SourceRange(compInfo.nameSourceStart, compInfo.nameSourceEnd - compInfo.nameSourceStart + 1);
+ String fieldName = new String(compInfo.name);
+ this.memberName[this.typeDepth] = fieldName;
+
+ // categories
+ IType currentType = this.types[this.typeDepth];
+ IField field = currentType.getRecordComponent(fieldName);
+ addCategories(field, compInfo.categories);
+ }
+ }
/**
* @see ISourceElementRequestor
@@ -1069,6 +1087,21 @@ public class SourceMapper
this.memberNameRange[this.typeDepth]);
}
}
+ /**
+ * @see ISourceElementRequestor
+ */
+ @Override
+ public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ if (this.typeDepth >= 0) {
+ IType currentType = this.types[this.typeDepth];
+ setSourceRange(
+ currentType.getRecordComponent(this.memberName[this.typeDepth]),
+ new SourceRange(
+ this.memberDeclarationStart[this.typeDepth],
+ declarationEnd - this.memberDeclarationStart[this.typeDepth] + 1),
+ this.memberNameRange[this.typeDepth]);
+ }
+ }
/**
* @see ISourceElementRequestor
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
index 116002781..e7a7dd649 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
@@ -59,6 +59,7 @@ public class SourceType extends NamedMember implements IType {
* Currently this is computed and used only for anonymous types.
*/
public int localOccurrenceCount = 1;
+private static final IField[] NO_FIELDS = new IField[0];
protected SourceType(JavaElement parent, String name) {
super(parent, name);
@@ -296,11 +297,48 @@ public IField getField(String fieldName) {
*/
@Override
public IField[] getFields() throws JavaModelException {
+ if (!isRecord()) {
+ ArrayList list = getChildrenOfType(FIELD);
+ if (list.size() == 0) {
+ return NO_FIELDS;
+ }
+ IField[] array= new IField[list.size()];
+ list.toArray(array);
+ return array;
+ }
+ return getFieldsOrComponents(false);
+}
+@Override
+public IField[] getRecordComponents() throws JavaModelException {
+ if (!isRecord())
+ return NO_FIELDS;
+ return getFieldsOrComponents(true);
+}
+private IField[] getFieldsOrComponents(boolean component) throws JavaModelException {
ArrayList list = getChildrenOfType(FIELD);
- IField[] array= new IField[list.size()];
- list.toArray(array);
+ if (list.size() == 0) {
+ return NO_FIELDS;
+ }
+ ArrayList<IField> fields = new ArrayList<>();
+ for (Object object : list) {
+ IField field = (IField) object;
+ if (field.isRecordComponent() == component)
+ fields.add(field);
+ }
+ IField[] array= new IField[fields.size()];
+ fields.toArray(array);
return array;
}
+@Override
+public IField getRecordComponent(String compName) {
+ try {
+ if (isRecord())
+ return new SourceField(this, compName);
+ } catch (JavaModelException e) {
+ // Should throw an exception instead?
+ }
+ return null;
+}
/**
* @see IType#getFullyQualifiedName()
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index 8b8edff9e..39698fddb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -694,7 +694,7 @@ protected void recordParticipantResult(CompilationParticipantResult result) {
String[] dependencies = result.dependencies;
if (dependencies != null) {
- ReferenceCollection refs = (ReferenceCollection) this.newState.references.get(result.sourceFile.typeLocator());
+ ReferenceCollection refs = this.newState.references.get(result.sourceFile.typeLocator());
if (refs != null)
refs.addDependencies(dependencies);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index ec2f1f1db..52b280c58 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -290,8 +290,8 @@ private void printStats() {
long time = compilerStats.elapsedTime();
long lineCount = compilerStats.lineCount;
double speed = ((int) (lineCount * 10000.0 / time)) / 10.0;
- System.out.println(">FULL BUILD STATS for: "+this.javaBuilder.javaProject.getElementName()); //$NON-NLS-1$
- System.out.println("> compiled " + lineCount + " lines in " + time + "ms:" + speed + " lines/s"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ System.out.println("\n>FULL BUILD STATS for: "+this.javaBuilder.javaProject.getElementName()); //$NON-NLS-1$
+ System.out.println("> compiled " + lineCount + " lines in " + time + " ms: " + speed + " lines/s"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
System.out.print("> parse: " + compilerStats.parseTime + " ms (" + ((int) (compilerStats.parseTime * 1000.0 / time)) / 10.0 + "%)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
System.out.print(", resolve: " + compilerStats.resolveTime + " ms (" + ((int) (compilerStats.resolveTime * 1000.0 / time)) / 10.0 + "%)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
System.out.print(", analyze: " + compilerStats.analyzeTime + " ms (" + ((int) (compilerStats.analyzeTime * 1000.0 / time)) / 10.0 + "%)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
index 3ba883267..e27831f55 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
@@ -47,26 +47,35 @@ public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry
//private HashMap<String, SimpleSet> packagesInModule = null;
protected static HashMap<String, HashMap<String, SimpleSet>> PackageCache = new HashMap<>();
-protected static HashMap<String, Set<IModule>> ModulesCache = new HashMap<>();
+protected static HashMap<String, HashMap<String, IModule>> ModulesCache = new HashMap<>();
String externalAnnotationPath;
protected ZipFile annotationZipFile;
String zipFilename; // keep for equals
+File jrtFile;
AccessRuleSet accessRuleSet;
static final Set<String> NO_LIMIT_MODULES = new HashSet<>();
/*
- * Only for use from ClasspathJrtWithOlderRelease
+ * Only for use from ClasspathJrtWithReleaseOption
*/
protected ClasspathJrt() {
}
public ClasspathJrt(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
- this.zipFilename = zipFilename;
+ setZipFile(zipFilename);
this.accessRuleSet = accessRuleSet;
if (externalAnnotationPath != null)
this.externalAnnotationPath = externalAnnotationPath.toString();
loadModules(this);
}
+
+void setZipFile(String zipFilename) {
+ this.zipFilename = zipFilename;
+ if(zipFilename != null) {
+ this.jrtFile = new File(zipFilename);
+ }
+}
+
/**
* Calculate and cache the package list available in the zipFile.
* @param jrt The ClasspathJar to use
@@ -81,7 +90,7 @@ static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrt jrt)
final HashMap<String, SimpleSet> packagesInModule = new HashMap<>();
PackageCache.put(zipFileName, packagesInModule);
try {
- final File imageFile = new File(zipFileName);
+ final File imageFile = jrt.jrtFile;
org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile,
new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
SimpleSet packageSet = null;
@@ -98,7 +107,7 @@ static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrt jrt)
@Override
public FileVisitResult visitModule(Path path, String name) throws IOException {
- jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModule.MODULE_INFO_CLASS, name));
+ jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModule.MODULE_INFO_CLASS, name), name);
this.packageSet = new SimpleSet(41);
this.packageSet.add(""); //$NON-NLS-1$
if (name.endsWith("/")) { //$NON-NLS-1$
@@ -115,11 +124,11 @@ static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrt jrt)
}
public static void loadModules(final ClasspathJrt jrt) {
- Set<IModule> cache = ModulesCache.get(jrt.getKey());
+ HashMap<String, IModule> cache = ModulesCache.get(jrt.getKey());
if (cache == null) {
try {
- final File imageFile = new File(jrt.zipFilename);
+ final File imageFile = jrt.jrtFile;
org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile,
new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
SimpleSet packageSet = null;
@@ -139,7 +148,7 @@ public static void loadModules(final ClasspathJrt jrt) {
@Override
public FileVisitResult visitModule(Path path, String name) throws IOException {
- jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModule.MODULE_INFO_CLASS, name));
+ jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModule.MODULE_INFO_CLASS, name), name);
return FileVisitResult.SKIP_SUBTREE;
}
}, JRTUtil.NOTIFY_MODULES);
@@ -155,7 +164,7 @@ public static void loadModules(final ClasspathJrt jrt) {
protected String getKey() {
return this.zipFilename;
}
-void acceptModule(byte[] content) {
+void acceptModule(byte[] content, String name) {
if (content == null)
return;
ClassFileReader reader = null;
@@ -168,11 +177,11 @@ void acceptModule(byte[] content) {
String key = getKey();
IModule moduleDecl = reader.getModuleDeclaration();
if (moduleDecl != null) {
- Set<IModule> cache = ModulesCache.get(key);
+ HashMap<String, IModule> cache = ModulesCache.get(key);
if (cache == null) {
- ModulesCache.put(key, cache = new HashSet<IModule>());
+ ModulesCache.put(key, cache = new HashMap<String, IModule>());
}
- cache.add(moduleDecl);
+ cache.put(name, moduleDecl);
}
}
}
@@ -205,7 +214,7 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa
try {
String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
- IBinaryType reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName, moduleNameFilter);
+ IBinaryType reader = ClassFileReader.readFromModule(this.jrtFile, moduleName, qualifiedBinaryFileName, moduleNameFilter);
return createAnswer(fileNameWithoutExtension, reader);
} catch (ClassFormatException | IOException e) { // treat as if class file is missing
}
@@ -243,16 +252,16 @@ public int hashCode() {
}
@Override
public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
- List<String> moduleNames = JRTUtil.getModulesDeclaringPackage(new File(this.zipFilename), qualifiedPackageName, moduleName);
+ List<String> moduleNames = JRTUtil.getModulesDeclaringPackage(this.jrtFile, qualifiedPackageName, moduleName);
return CharOperation.toCharArrays(moduleNames);
}
@Override
public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) {
- return JRTUtil.hasCompilationUnit(new File(this.zipFilename), qualifiedPackageName, moduleName);
+ return JRTUtil.hasCompilationUnit(this.jrtFile, qualifiedPackageName, moduleName);
}
@Override
public boolean isPackage(String qualifiedPackageName, String moduleName) {
- return JRTUtil.getModulesDeclaringPackage(new File(this.zipFilename), qualifiedPackageName, moduleName) != null;
+ return JRTUtil.getModulesDeclaringPackage(this.jrtFile, qualifiedPackageName, moduleName) != null;
}
@Override
@@ -277,12 +286,12 @@ public boolean hasModule() {
}
@Override
public IModule getModule(char[] moduleName) {
- Set<IModule> modules = ModulesCache.get(getKey());
+ return getModule(String.valueOf(moduleName));
+}
+public IModule getModule(String moduleName) {
+ HashMap<String, IModule> modules = ModulesCache.get(getKey());
if (modules != null) {
- for (IModule mod : modules) {
- if (CharOperation.equals(mod.name(), moduleName))
- return mod;
- }
+ return modules.get(moduleName);
}
return null;
}
@@ -303,7 +312,7 @@ protected Collection<String> selectModules(Set<String> keySet, Collection<String
result.retainAll(limitModules);
rootModules = result;
} else {
- rootModules = JavaProject.internalDefaultRootModules(keySet, s -> s, m -> getModule(m.toCharArray()));
+ rootModules = JavaProject.internalDefaultRootModules(keySet, s -> s, m -> getModule(m));
}
Set<String> allModules = new HashSet<>(rootModules);
for (String mod : rootModules)
@@ -312,16 +321,16 @@ protected Collection<String> selectModules(Set<String> keySet, Collection<String
}
protected void addRequired(String mod, Set<String> allModules) {
- IModule iMod = getModule(mod.toCharArray());
+ IModule iMod = getModule(mod);
if(iMod == null) {
return;
}
for (IModuleReference requiredRef : iMod.requires()) {
- IModule reqMod = getModule(requiredRef.name());
+ String moduleName = String.valueOf(requiredRef.name());
+ IModule reqMod = getModule(moduleName);
if (reqMod != null) {
- String reqModName = String.valueOf(reqMod.name());
- if (allModules.add(reqModName))
- addRequired(reqModName, allModules);
+ if (allModules.add(moduleName))
+ addRequired(moduleName, allModules);
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
index 7220b0e0a..579cf00ba 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
@@ -13,24 +13,18 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
-import java.io.File;
import java.io.IOException;
-import java.net.URI;
-import java.nio.file.DirectoryStream;
-import java.nio.file.FileSystemNotFoundException;
-import java.nio.file.FileSystems;
+import java.nio.file.FileSystem;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.Set;
import java.util.function.Predicate;
import org.eclipse.core.runtime.CoreException;
@@ -44,6 +38,7 @@ import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.IModule;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.CtSym;
import org.eclipse.jdt.internal.compiler.util.JRTUtil;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
@@ -55,12 +50,16 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
final String release;
String releaseInHex;
- private String[] subReleases;
- private java.nio.file.FileSystem fs;
+ /**
+ * Null for releases without ct.sym file or for releases matching current one
+ */
+ private FileSystem fs;
protected Path releasePath;
protected Path modulePath;
private String modPathString;
- private boolean isJRE12Plus;
+ final CtSym ctSym;
+
+
public ClasspathJrtWithReleaseOption(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath,
String release) throws CoreException {
@@ -68,13 +67,15 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
if (release == null || release.equals("")) { //$NON-NLS-1$
throw new IllegalArgumentException("--release argument can not be null"); //$NON-NLS-1$
}
- this.zipFilename = zipFilename;
+ setZipFile(zipFilename);
this.accessRuleSet = accessRuleSet;
- if (externalAnnotationPath != null)
+ if (externalAnnotationPath != null) {
this.externalAnnotationPath = externalAnnotationPath.toString();
+ }
this.release = getReleaseOptionFromCompliance(release);
+ this.ctSym = JRTUtil.getCtSym(Paths.get(this.zipFilename).getParent().getParent());
initialize();
- loadModules(this);
+ loadModules();
}
/*
* JDK 11 doesn't contain release 5. Hence
@@ -92,54 +93,21 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
return comp;
}
}
- private boolean isJRE12Plus(Path path) {
- try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
- for (final java.nio.file.Path subdir : stream) {
- String rel = JRTUtil.sanitizedFileName(subdir);
- if (Files.exists(this.fs.getPath(rel, "system-modules"))) { //$NON-NLS-1$
- int parseInt = Integer.parseInt(rel, 16);
- return (parseInt > 11);
- }
- }
- } catch (IOException e) {
- this.fs = null;
- }
- return false;
- }
- /*
+
+ /**
* Set up the paths where modules and regular classes need to be read. We need to deal with two different kind of
- * formats of cy.sym: Post JDK 12: ct.sym -> 9 -> java/ -> lang/* 9-modules -> java.base -> module-info.sig
- *
- * From JDK 12 onward: ct.sym -> 9 -> java.base -> module-info.sig java/ -> lang/* Notably, 1) in JDK 12 modules
- * classes and ordinary classes are located in the same location 2) in JDK 12, ordinary classes are found inside
- * their respective modules
+ * formats of cy.sym, see {@link CtSym} javadoc.
*
+ * @see CtSym
*/
protected void initialize() throws CoreException {
this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
- Path lib = Paths.get(this.zipFilename).getParent();
- Path filePath = Paths.get(lib.toString(), "ct.sym"); //$NON-NLS-1$
- URI t = filePath.toUri();
- if (!Files.exists(filePath)) {
+ if (!this.ctSym.exists()) {
return;
}
- URI uri = URI.create("jar:file:" + t.getRawPath()); //$NON-NLS-1$
- try {
- this.fs = FileSystems.getFileSystem(uri);
- } catch (FileSystemNotFoundException fne) {
- // Ignore and move on
- }
- if (this.fs == null) {
- HashMap<String, ?> env = new HashMap<>();
- try {
- this.fs = FileSystems.newFileSystem(uri, env);
- } catch (IOException e) {
- return;
- }
- }
- this.releasePath = this.fs.getPath("/"); //$NON-NLS-1$
- this.isJRE12Plus = isJRE12Plus(this.releasePath);
- Path modPath = this.fs.getPath(this.releaseInHex + (this.isJRE12Plus ? "" : "-modules")); //$NON-NLS-1$ //$NON-NLS-2$
+ this.fs = this.ctSym.getFs();
+ this.releasePath = this.ctSym.getRoot();
+ Path modPath = this.fs.getPath(this.releaseInHex + (this.ctSym.isJRE12Plus() ? "" : "-modules")); //$NON-NLS-1$ //$NON-NLS-2$
if (Files.exists(modPath)) {
this.modulePath = modPath;
this.modPathString = this.zipFilename + "|"+ modPath.toString(); //$NON-NLS-1$
@@ -150,44 +118,25 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, e.getMessage(), e));
}
if (Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
- this.fs = null; // Fallback to default version
- return;
- }
- if (this.release != null) {
- List<String> sub = new ArrayList<>();
- try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
- for (final java.nio.file.Path subdir : stream) {
- String rel = JRTUtil.sanitizedFileName(subdir);
- if (rel.contains(this.releaseInHex)) {
- sub.add(rel);
- } else {
- continue;
- }
- }
- } catch (IOException e) {
- this.fs = null; // Fallback to default version
- }
- this.subReleases = sub.toArray(new String[sub.size()]);
+ this.fs = null; // Fallback to default version, all classes are on jrt fs, not here.
}
}
- static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrtWithReleaseOption jrt) {
+
+ HashMap<String, SimpleSet> findPackagesInModules() {
// In JDK 11 and before, classes are not listed under their respective modules
// Hence, we simply go to the default module system for package-module mapping
- if (jrt.fs == null || !jrt.isJRE12Plus) {
- return ClasspathJrt.findPackagesInModules(jrt);
+ if (this.fs == null || !this.ctSym.isJRE12Plus()) {
+ return ClasspathJrt.findPackagesInModules(this);
}
- String zipFileName = jrt.zipFilename;
- HashMap<String, SimpleSet> cache = PackageCache.get(jrt.modPathString);
+ HashMap<String, SimpleSet> cache = PackageCache.get(this.modPathString);
if (cache != null) {
return cache;
}
final HashMap<String, SimpleSet> packagesInModule = new HashMap<>();
- PackageCache.put(jrt.modPathString, packagesInModule);
+ PackageCache.put(this.modPathString, packagesInModule);
try {
- final File imageFile = new File(zipFileName);
- org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile, jrt.release,
- new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
+ JRTUtil.walkModuleImage(this.jrtFile, this.release, new JRTUtil.JrtFileVisitor<Path>() {
SimpleSet packageSet = null;
@Override
@@ -220,21 +169,20 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
return packagesInModule;
}
- public static void loadModules(final ClasspathJrtWithReleaseOption jrt) {
- if (jrt.fs == null || !jrt.isJRE12Plus) {
- ClasspathJrt.loadModules(jrt);
+ public void loadModules() {
+ if (this.fs == null || !this.ctSym.isJRE12Plus()) {
+ ClasspathJrt.loadModules(this);
return;
}
- if (jrt.modPathString == null)
+ if (this.modPathString == null) {
return;
- Set<IModule> cache = ModulesCache.get(jrt.modPathString);
+ }
+ HashMap<String, IModule> cache = ModulesCache.get(this.modPathString);
if (cache == null) {
- try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(jrt.releasePath)) {
- for (final java.nio.file.Path subdir : stream) {
- if (!subdir.getFileName().toString().contains(jrt.releaseInHex)) {
- continue;
- }
- Files.walkFileTree(subdir, Collections.EMPTY_SET, 2, new FileVisitor<java.nio.file.Path>() {
+ List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseInHex);
+ for (Path root : releaseRoots) {
+ try {
+ Files.walkFileTree(root, Collections.EMPTY_SET, 2, new FileVisitor<java.nio.file.Path>() {
@Override
public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
throws IOException {
@@ -248,10 +196,11 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
return FileVisitResult.CONTINUE;
}
if (f.getFileName().toString().equals(MODULE_INFO)) {
- byte[] content = JRTUtil.safeReadBytes(f);
- if (content == null)
+ byte[] content = ClasspathJrtWithReleaseOption.this.ctSym.getFileBytes(f);
+ if (content == null) {
return FileVisitResult.CONTINUE;
- jrt.acceptModule(content);
+ }
+ ClasspathJrtWithReleaseOption.this.acceptModule(content, f.getParent().getFileName().toString());
}
return FileVisitResult.SKIP_SIBLINGS;
}
@@ -268,9 +217,9 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
return FileVisitResult.CONTINUE;
}
});
+ } catch (IOException e) {
+ // Nothing much to do
}
- } catch (IOException e) {
- // Nothing much to do
}
}
}
@@ -284,51 +233,31 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
return super.findClass(binaryFileName, qualifiedPackageName, moduleName, qualifiedBinaryFileName,
asBinaryOnly, moduleNameFilter);
}
- if (!isPackage(qualifiedPackageName, moduleName))
+ if (!isPackage(qualifiedPackageName, moduleName)) {
return null; // most common case
-
+ }
+ List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseInHex);
try {
IBinaryType reader = null;
byte[] content = null;
String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0,
qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
- if (this.subReleases != null && this.subReleases.length > 0) {
+ if (!releaseRoots.isEmpty()) {
qualifiedBinaryFileName = qualifiedBinaryFileName.replace(".class", ".sig"); //$NON-NLS-1$ //$NON-NLS-2$
- outer: for (String rel : this.subReleases) {
- Path p = null;
- inner: if (this.isJRE12Plus) {
+ Path fullPath = this.ctSym.getFullPath(this.releaseInHex, qualifiedBinaryFileName, moduleName);
+ // If file is known, read it from ct.sym
+ if (fullPath != null) {
+ content = this.ctSym.getFileBytes(fullPath);
+ if (content != null) {
+ reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
if (moduleName != null) {
- p = this.fs.getPath(rel, moduleName, qualifiedBinaryFileName);
- }
- else {
- try (DirectoryStream<java.nio.file.Path> stream = Files
- .newDirectoryStream(this.fs.getPath(rel))) {
- for (final java.nio.file.Path subdir : stream) {
- p = subdir.resolve(qualifiedBinaryFileName);
- if (Files.exists(p)) {
- if (subdir.getNameCount() == 2 ) {
- moduleName = subdir.getName(1).toString();
- }
- break inner;
- }
- }
- }
- }
- } else {
- p = this.fs.getPath(rel, qualifiedBinaryFileName);
- }
- if (Files.exists(p)) {
- content = JRTUtil.safeReadBytes(p);
- if (content != null) {
- reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
- if (moduleName != null)
- ((ClassFileReader) reader).moduleName = moduleName.toCharArray();
- break outer;
+ ((ClassFileReader) reader).moduleName = moduleName.toCharArray();
}
}
}
} else {
- reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName,
+ // Read the file in a "classic" way from the JDK itself
+ reader = ClassFileReader.readFromModule(this.jrtFile, moduleName, qualifiedBinaryFileName,
moduleNameFilter);
}
return createAnswer(fileNameWithoutExtension, reader);
@@ -340,7 +269,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
@Override
public Collection<String> getModuleNames(Collection<String> limitModules) {
- HashMap<String, SimpleSet> cache = findPackagesInModules(this);
+ HashMap<String, SimpleSet> cache = findPackagesInModules();
if (cache != null)
return selectModules(cache.keySet(), limitModules);
return Collections.emptyList();
@@ -349,7 +278,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
@Override
public void cleanup() {
try {
- super.reset();
+ super.cleanup();
} finally {
// The same file system is also used in JRTUtil, so don't close it here.
this.fs = null;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 5fffe471f..bb82ffc4b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -34,6 +34,7 @@ import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import java.io.*;
import java.net.URI;
import java.util.*;
+import java.util.Map.Entry;
/**
* <h4>OTDT changes:</h4>
@@ -252,25 +253,21 @@ protected void addAffectedSourceFiles(Set<String> qualifiedSet, Set<String> simp
internedSimpleNames = null;
char[][] internedRootNames = ReferenceCollection.internSimpleNames(rootSet, false);
- Object[] keyTable = this.newState.references.keyTable;
- Object[] valueTable = this.newState.references.valueTable;
- next : for (int i = 0, l = valueTable.length; i < l; i++) {
- String typeLocator = (String) keyTable[i];
- if (typeLocator != null) {
- if (affectedTypes != null && !affectedTypes.contains(typeLocator)) continue next;
- ReferenceCollection refs = (ReferenceCollection) valueTable[i];
- if (refs.includes(internedQualifiedNames, internedSimpleNames, internedRootNames)) {
- IFile file = this.javaBuilder.currentProject.getFile(typeLocator);
- SourceFile sourceFile = findSourceFile(file, true);
- if (sourceFile == null) continue next;
- if (this.sourceFiles.contains(sourceFile)) continue next;
- if (this.compiledAllAtOnce && this.previousSourceFiles != null && this.previousSourceFiles.contains(sourceFile))
- continue next; // can skip previously compiled files since already saw hierarchy related problems
+ next: for (Entry<String, ReferenceCollection> entry : this.newState.references.entrySet()) {
+ String typeLocator = entry.getKey();
+ if (affectedTypes != null && !affectedTypes.contains(typeLocator)) continue next;
+ ReferenceCollection refs = entry.getValue();
+ if (refs.includes(internedQualifiedNames, internedSimpleNames, internedRootNames)) {
+ IFile file = this.javaBuilder.currentProject.getFile(typeLocator);
+ SourceFile sourceFile = findSourceFile(file, true);
+ if (sourceFile == null) continue next;
+ if (this.sourceFiles.contains(sourceFile)) continue next;
+ if (this.compiledAllAtOnce && this.previousSourceFiles != null && this.previousSourceFiles.contains(sourceFile))
+ continue next; // can skip previously compiled files since already saw hierarchy related problems
- if (JavaBuilder.DEBUG)
- System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$
- this.sourceFiles.add(sourceFile);
- }
+ if (JavaBuilder.DEBUG)
+ System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$
+ this.sourceFiles.add(sourceFile);
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index 218373da7..0b972e6ec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -19,23 +19,41 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.env.AccessRule;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
-import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.*;
-import org.eclipse.jdt.internal.compiler.env.AccessRule;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.AddExports;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.AddReads;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.JavaModelManager;
-import java.io.*;
-import java.util.*;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
@SuppressWarnings({"rawtypes", "unchecked"})
public class State {
// NOTE: this state cannot contain types that are not defined in this project
@@ -46,9 +64,9 @@ public ClasspathMultiDirectory[] testSourceLocations;
ClasspathLocation[] binaryLocations;
ClasspathLocation[] testBinaryLocations;
// keyed by the project relative path of the type (i.e. "src1/p1/p2/A.java"), value is a ReferenceCollection or an AdditionalTypeCollection
-SimpleLookupTable references;
+Map<String, ReferenceCollection> references;
// keyed by qualified type name "p1/p2/A", value is the project relative path which defines this type "src1/p1/p2/A.java"
-public SimpleLookupTable typeLocators;
+public Map<String, String> typeLocators;
int buildNumber;
long lastStructuralBuildTime;
@@ -80,8 +98,8 @@ protected State(JavaBuilder javaBuilder) {
this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations;
this.testSourceLocations = javaBuilder.testNameEnvironment.sourceLocations;
this.testBinaryLocations = javaBuilder.testNameEnvironment.binaryLocations;
- this.references = new SimpleLookupTable(7);
- this.typeLocators = new SimpleLookupTable(7);
+ this.references = new LinkedHashMap<>(7);
+ this.typeLocators = new LinkedHashMap<>(7);
this.buildNumber = 0; // indicates a full build
this.lastStructuralBuildTime = computeStructuralBuildTime(javaBuilder.lastState == null ? 0 : javaBuilder.lastState.lastStructuralBuildTime);
@@ -103,24 +121,8 @@ void copyFrom(State lastState) {
this.lastStructuralBuildTime = lastState.lastStructuralBuildTime;
this.structuralBuildTimes = lastState.structuralBuildTimes;
- try {
- this.references = (SimpleLookupTable) lastState.references.clone();
- this.typeLocators = (SimpleLookupTable) lastState.typeLocators.clone();
- } catch (CloneNotSupportedException e) {
- this.references = new SimpleLookupTable(lastState.references.elementSize);
- Object[] keyTable = lastState.references.keyTable;
- Object[] valueTable = lastState.references.valueTable;
- for (int i = 0, l = keyTable.length; i < l; i++)
- if (keyTable[i] != null)
- this.references.put(keyTable[i], valueTable[i]);
-
- this.typeLocators = new SimpleLookupTable(lastState.typeLocators.elementSize);
- keyTable = lastState.typeLocators.keyTable;
- valueTable = lastState.typeLocators.valueTable;
- for (int i = 0, l = keyTable.length; i < l; i++)
- if (keyTable[i] != null)
- this.typeLocators.put(keyTable[i], valueTable[i]);
- }
+ this.references = new LinkedHashMap<>(lastState.references);
+ this.typeLocators = new LinkedHashMap<>(lastState.typeLocators);
}
public char[][] getDefinedTypeNamesFor(String typeLocator) {
Object c = this.references.get(typeLocator);
@@ -129,7 +131,7 @@ public char[][] getDefinedTypeNamesFor(String typeLocator) {
return null; // means only one type is defined with the same name as the file... saves space
}
-public SimpleLookupTable getReferences() {
+public Map<String, ReferenceCollection> getReferences() {
return this.references;
}
@@ -144,33 +146,30 @@ StringSet getStructurallyChangedTypes(State prereqState) {
}
public boolean isDuplicateLocator(String qualifiedTypeName, String typeLocator) {
- String existing = (String) this.typeLocators.get(qualifiedTypeName);
+ String existing = this.typeLocators.get(qualifiedTypeName);
return existing != null && !existing.equals(typeLocator);
}
public boolean isKnownPackage(String qualifiedPackageName) {
if (this.knownPackageNames == null) {
- LinkedHashSet<String> names = new LinkedHashSet<>(this.typeLocators.elementSize);
- Object[] keyTable = this.typeLocators.keyTable;
- for (int i = 0, l = keyTable.length; i < l; i++) {
- if (keyTable[i] != null) {
- String packageName = (String) keyTable[i]; // is a type name of the form p1/p2/A
- int last = packageName.lastIndexOf('/');
+ LinkedHashSet<String> names = new LinkedHashSet<>(this.typeLocators.size());
+ Set<Entry<String, String>> keyTable = this.typeLocators.entrySet();
+ for (Entry<String, String> entry : keyTable) {
+ String packageName = entry.getValue(); // is a type name of the form p1/p2/A
+ int last = packageName.lastIndexOf('/');
+ packageName = last == -1 ? null : packageName.substring(0, last);
+ while (packageName != null && !names.contains(packageName)) {
+ names.add(packageName);
+ last = packageName.lastIndexOf('/');
packageName = last == -1 ? null : packageName.substring(0, last);
- while (packageName != null && !names.contains(packageName)) {
- names.add(packageName);
- last = packageName.lastIndexOf('/');
- packageName = last == -1 ? null : packageName.substring(0, last);
- }
}
}
this.knownPackageNames = new String[names.size()];
names.toArray(this.knownPackageNames);
+ Arrays.sort(this.knownPackageNames);
}
- for (int i = 0, l = this.knownPackageNames.length; i < l; i++)
- if (this.knownPackageNames[i].equals(qualifiedPackageName))
- return true;
- return false;
+ int result = Arrays.binarySearch(this.knownPackageNames, qualifiedPackageName);
+ return result >= 0;
}
public boolean isKnownType(String qualifiedTypeName) {
@@ -179,10 +178,11 @@ public boolean isKnownType(String qualifiedTypeName) {
boolean isSourceFolderEmpty(IContainer sourceFolder) {
String sourceFolderName = sourceFolder.getProjectRelativePath().addTrailingSeparator().toString();
- Object[] table = this.typeLocators.valueTable;
- for (int i = 0, l = table.length; i < l; i++)
- if (table[i] != null && ((String) table[i]).startsWith(sourceFolderName))
+ for (String value : this.typeLocators.values()) {
+ if (value.startsWith(sourceFolderName)) {
return false;
+ }
+ }
return true;
}
@@ -213,10 +213,12 @@ void recordStructuralDependency(IProject prereqProject, State prereqState) {
void removeLocator(String typeLocatorToRemove) {
this.knownPackageNames = null;
- this.references.removeKey(typeLocatorToRemove);
- this.typeLocators.removeValue(typeLocatorToRemove);
+ this.references.remove(typeLocatorToRemove);
+ this.typeLocators.values().removeIf(v -> typeLocatorToRemove.equals(v));
}
+
+
void removePackage(IResourceDelta sourceDelta) {
IResource resource = sourceDelta.getResource();
switch(resource.getType()) {
@@ -234,7 +236,7 @@ void removePackage(IResourceDelta sourceDelta) {
void removeQualifiedTypeName(String qualifiedTypeNameToRemove) {
this.knownPackageNames = null;
- this.typeLocators.removeKey(qualifiedTypeNameToRemove);
+ this.typeLocators.remove(qualifiedTypeNameToRemove);
}
static State read(IProject project, DataInputStream in) throws IOException, CoreException {
@@ -387,7 +389,8 @@ static State read(IProject project, DataInputStream in) throws IOException, Core
for (int i = 0; i < length; i++)
internedTypeLocators[i] = in.readUTF();
- newState.typeLocators = new SimpleLookupTable(length = in.readInt());
+ length = in.readInt();
+ newState.typeLocators = new LinkedHashMap<>((int) (length / 0.75 + 1));
for (int i = 0; i < length; i++)
newState.recordLocatorForType(in.readUTF(), internedTypeLocators[in.readInt()]);
@@ -406,7 +409,8 @@ static State read(IProject project, DataInputStream in) throws IOException, Core
}
internedQualifiedNames = ReferenceCollection.internQualifiedNames(internedQualifiedNames, false /* drop well known */, false /* do not sort */);
- newState.references = new SimpleLookupTable(length = in.readInt());
+ length = in.readInt();
+ newState.references = new LinkedHashMap((int) (length / 0.75 + 1));
for (int i = 0; i < length; i++) {
String typeLocator = internedTypeLocators[in.readInt()];
ReferenceCollection collection = null;
@@ -726,14 +730,13 @@ void write(DataOutputStream out) throws IOException {
/*
* String[] Interned type locators
*/
- out.writeInt(length = this.references.elementSize);
+ out.writeInt(length = this.references.size());
SimpleLookupTable internedTypeLocators = new SimpleLookupTable(length);
if (length > 0) {
- keyTable = this.references.keyTable;
- for (int i = 0, l = keyTable.length; i < l; i++) {
- if (keyTable[i] != null) {
+ Set<String> keys = this.references.keySet();
+ for (String key : keys) {
+ if (key != null) {
length--;
- String key = (String) keyTable[i];
out.writeUTF(key);
internedTypeLocators.put(key, Integer.valueOf(internedTypeLocators.elementSize));
}
@@ -747,15 +750,16 @@ void write(DataOutputStream out) throws IOException {
* String type name
* int interned locator id
*/
- out.writeInt(length = this.typeLocators.elementSize);
+ out.writeInt(length = this.typeLocators.size());
if (length > 0) {
- keyTable = this.typeLocators.keyTable;
- valueTable = this.typeLocators.valueTable;
- for (int i = 0, l = keyTable.length; i < l; i++) {
- if (keyTable[i] != null) {
+ Set<Entry<String, String>> entries = this.typeLocators.entrySet();
+ for (Entry<String, String> entry : entries) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ if (key != null) {
length--;
- out.writeUTF((String) keyTable[i]);
- Integer index = (Integer) internedTypeLocators.get(valueTable[i]);
+ out.writeUTF(value);
+ Integer index = (Integer) internedTypeLocators.get(value);
out.writeInt(index.intValue());
}
}
@@ -771,34 +775,30 @@ void write(DataOutputStream out) throws IOException {
SimpleLookupTable internedRootNames = new SimpleLookupTable(3);
SimpleLookupTable internedQualifiedNames = new SimpleLookupTable(31);
SimpleLookupTable internedSimpleNames = new SimpleLookupTable(31);
- valueTable = this.references.valueTable;
- for (int i = 0, l = valueTable.length; i < l; i++) {
- if (valueTable[i] != null) {
- ReferenceCollection collection = (ReferenceCollection) valueTable[i];
- char[][] rNames = collection.rootReferences;
- for (int j = 0, m = rNames.length; j < m; j++) {
- char[] rName = rNames[j];
- if (!internedRootNames.containsKey(rName)) // remember the names have been interned
- internedRootNames.put(rName, Integer.valueOf(internedRootNames.elementSize));
- }
- char[][][] qNames = collection.qualifiedNameReferences;
- for (int j = 0, m = qNames.length; j < m; j++) {
- char[][] qName = qNames[j];
- if (!internedQualifiedNames.containsKey(qName)) { // remember the names have been interned
- internedQualifiedNames.put(qName, Integer.valueOf(internedQualifiedNames.elementSize));
- for (int k = 0, n = qName.length; k < n; k++) {
- char[] sName = qName[k];
- if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned
- internedSimpleNames.put(sName, Integer.valueOf(internedSimpleNames.elementSize));
- }
+ for (ReferenceCollection collection : this.references.values()) {
+ char[][] rNames = collection.rootReferences;
+ for (int j = 0, m = rNames.length; j < m; j++) {
+ char[] rName = rNames[j];
+ if (!internedRootNames.containsKey(rName)) // remember the names have been interned
+ internedRootNames.put(rName, Integer.valueOf(internedRootNames.elementSize));
+ }
+ char[][][] qNames = collection.qualifiedNameReferences;
+ for (int j = 0, m = qNames.length; j < m; j++) {
+ char[][] qName = qNames[j];
+ if (!internedQualifiedNames.containsKey(qName)) { // remember the names have been interned
+ internedQualifiedNames.put(qName, Integer.valueOf(internedQualifiedNames.elementSize));
+ for (int k = 0, n = qName.length; k < n; k++) {
+ char[] sName = qName[k];
+ if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned
+ internedSimpleNames.put(sName, Integer.valueOf(internedSimpleNames.elementSize));
}
}
- char[][] sNames = collection.simpleNameReferences;
- for (int j = 0, m = sNames.length; j < m; j++) {
- char[] sName = sNames[j];
- if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned
- internedSimpleNames.put(sName, Integer.valueOf(internedSimpleNames.elementSize));
- }
+ }
+ char[][] sNames = collection.simpleNameReferences;
+ for (int j = 0, m = sNames.length; j < m; j++) {
+ char[] sName = sNames[j];
+ if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned
+ internedSimpleNames.put(sName, Integer.valueOf(internedSimpleNames.elementSize));
}
}
char[][] internedArray = new char[internedRootNames.elementSize][];
@@ -848,43 +848,41 @@ void write(DataOutputStream out) throws IOException {
* int interned locator id
* ReferenceCollection
*/
- out.writeInt(length = this.references.elementSize);
+ out.writeInt(length = this.references.size());
if (length > 0) {
- keyTable = this.references.keyTable;
- for (int i = 0, l = keyTable.length; i < l; i++) {
- if (keyTable[i] != null) {
- length--;
- Integer index = (Integer) internedTypeLocators.get(keyTable[i]);
+ for (Entry<String, ReferenceCollection> entry : this.references.entrySet()) {
+ String key = entry.getKey();
+ length--;
+ Integer index = (Integer) internedTypeLocators.get(key);
+ out.writeInt(index.intValue());
+ ReferenceCollection collection = entry.getValue();
+ if (collection instanceof AdditionalTypeCollection) {
+ out.writeByte(1);
+ AdditionalTypeCollection atc = (AdditionalTypeCollection) collection;
+ writeNames(atc.definedTypeNames, out);
+ } else {
+ out.writeByte(2);
+ }
+ char[][][] qNames = collection.qualifiedNameReferences;
+ int qLength = qNames.length;
+ out.writeInt(qLength);
+ for (int j = 0; j < qLength; j++) {
+ index = (Integer) internedQualifiedNames.get(qNames[j]);
+ out.writeInt(index.intValue());
+ }
+ char[][] sNames = collection.simpleNameReferences;
+ int sLength = sNames.length;
+ out.writeInt(sLength);
+ for (int j = 0; j < sLength; j++) {
+ index = (Integer) internedSimpleNames.get(sNames[j]);
+ out.writeInt(index.intValue());
+ }
+ char[][] rNames = collection.rootReferences;
+ int rLength = rNames.length;
+ out.writeInt(rLength);
+ for (int j = 0; j < rLength; j++) {
+ index = (Integer) internedRootNames.get(rNames[j]);
out.writeInt(index.intValue());
- ReferenceCollection collection = (ReferenceCollection) valueTable[i];
- if (collection instanceof AdditionalTypeCollection) {
- out.writeByte(1);
- AdditionalTypeCollection atc = (AdditionalTypeCollection) collection;
- writeNames(atc.definedTypeNames, out);
- } else {
- out.writeByte(2);
- }
- char[][][] qNames = collection.qualifiedNameReferences;
- int qLength = qNames.length;
- out.writeInt(qLength);
- for (int j = 0; j < qLength; j++) {
- index = (Integer) internedQualifiedNames.get(qNames[j]);
- out.writeInt(index.intValue());
- }
- char[][] sNames = collection.simpleNameReferences;
- int sLength = sNames.length;
- out.writeInt(sLength);
- for (int j = 0; j < sLength; j++) {
- index = (Integer) internedSimpleNames.get(sNames[j]);
- out.writeInt(index.intValue());
- }
- char[][] rNames = collection.rootReferences;
- int rLength = rNames.length;
- out.writeInt(rLength);
- for (int j = 0; j < rLength; j++) {
- index = (Integer) internedRootNames.get(rNames[j]);
- out.writeInt(index.intValue());
- }
}
}
if (JavaBuilder.DEBUG && length != 0)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
index 1f81a0e63..1736cbfec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -210,6 +210,16 @@ protected SourceElementParser getParser(Map<String, String> settings) {
return new SourceElementParser(this, new DefaultProblemFactory(), new CompilerOptions(settings), false/*don't report local declarations*/, true/*optimize string literals*/);
}
+@Override
+public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
+ // TODO Auto-generated method stub
+}
+
+@Override
+public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ // TODO Auto-generated method stub
+}
+
//{OTDTUI: added default implementation to corresponding extension in ISourceElementRequestor
@Override
public void enterCalloutMapping(CalloutInfo calloutInfo)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
index cb1174da4..dbf479af9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -36,7 +36,7 @@ public class SimpleDocument implements IDocument {
@Override
public char getChar(int offset) {
- return 0;
+ return this.buffer.charAt(offset);
}
@Override
diff --git a/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/OTType.java b/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/OTType.java
index a0dd591ff..4ffa4dc76 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/OTType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/OTType.java
@@ -422,6 +422,11 @@ public class OTType extends OTJavaElement implements IOTType
}
@Override
+ public IField getRecordComponent(String name) {
+ return null;
+ }
+
+ @Override
public String getFullyQualifiedName()
{
return getIType().getFullyQualifiedName();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/PhantomType.java b/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/PhantomType.java
index f715cbae8..70f158e8c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/PhantomType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/objectteams/otdt/internal/core/PhantomType.java
@@ -246,7 +246,12 @@ public class PhantomType implements IPhantomType
uniqueFields.add(field);
return uniqueFields.toArray(new IField[uniqueFields.size()]);
}
-
+
+ @Override
+ public IField getRecordComponent(String name) {
+ return null;
+ }
+
@Override
public String getFullyQualifiedName()
{
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java
index fdf45f82a..b5d55a336 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java
@@ -14,6 +14,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.search;
+import java.util.Collection;
import java.util.LinkedHashSet;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -131,11 +132,9 @@ private static int canSeeFocus(IJavaElement focus, JavaProject javaProject, char
if (focusQualifiedNames != null) { // builder state is usable, hence use it to try to reduce project which can see the focus...
State projectState = (State) JavaModelManager.getJavaModelManager().getLastBuiltState(javaProject.getProject(), null);
if (projectState != null) {
- Object[] values = projectState.getReferences().valueTable;
- int vLength = values.length;
- for (int j=0; j<vLength; j++) {
- if (values[j] == null) continue;
- ReferenceCollection references = (ReferenceCollection) values[j];
+ Collection<ReferenceCollection> values = projectState.getReferences().values();
+ for (ReferenceCollection references : values) {
+ if (references == null) continue;
if (references.includes(focusQualifiedNames, null, null)) {
return PROJECT_CAN_SEE_FOCUS;
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
index ce1c3b51f..fd59ee34b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -182,6 +182,9 @@ public abstract class AbstractIndexer implements IIndexConstants {
addIndexEntry(FIELD_DECL, FieldPattern.createIndexKey(fieldName));
addTypeReference(typeName);
}
+ public void addRecordComponentDecl(char[] typeName, char[] fieldName) {
+ addFieldDeclaration(typeName, fieldName);
+ }
public void addFieldReference(char[] fieldName) {
addNameReference(fieldName);
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
index da3cb4a44..36174cb15 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
@@ -313,6 +313,14 @@ public void enterField(FieldInfo fieldInfo) {
this.methodDepth++;
}
/**
+ * @see ISourceElementRequestor#enterRecordComponent(ISourceElementRequestor.RecordComponentInfo)
+ */
+@Override
+public void enterRecordComponent(RecordComponentInfo componentInfo) {
+ this.indexer.addFieldDeclaration(componentInfo.type, componentInfo.name);
+ this.methodDepth++;
+}
+/**
* @see ISourceElementRequestor#enterInitializer(int, int)
*/
@Override
@@ -481,6 +489,13 @@ public void exitField(int initializationStart, int declarationEnd, int declarati
this.methodDepth--;
}
/**
+ * @see ISourceElementRequestor#exitRecordComponent(int, int)
+ */
+@Override
+public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ //Nothing by default
+}
+/**
* @see ISourceElementRequestor#exitInitializer(int)
*/
@Override
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index 751efcdd8..30fd398e1 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -205,7 +205,7 @@ private void addModuleClassPathInfo(PackageFragmentRoot root, IModuleDescription
private String addModuleClassPathInfo(ClasspathLocation cp, IModuleDescription imd) {
IModule mod = NameLookup.getModuleDescriptionInfo(imd);
String moduleName = null;
- if (mod != null) {
+ if (mod != null && cp != null) {
char[] name = mod.name();
if (name != null) {
moduleName = new String(name);
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/SourceElementRequestorTest.java b/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/SourceElementRequestorTest.java
index d209e1550..4f1aabe23 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/SourceElementRequestorTest.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/SourceElementRequestorTest.java
@@ -180,6 +180,12 @@ public class SourceElementRequestorTest extends FileBasedModelTest implements IS
}
+ @Override
+ public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
+ // TODO Auto-generated method stub
+
+ }
+
public void enterType(TypeInfo typeInfo) {
// TODO Auto-generated method stub
@@ -221,5 +227,10 @@ public class SourceElementRequestorTest extends FileBasedModelTest implements IS
public void exitMethod(int declarationEnd, Expression defaultValue) {
// TODO Auto-generated method stub
}
-
+
+ @Override
+ public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ // TODO Auto-generated method stub
+ }
+
}
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/smap/AbstractSourceMapGeneratorTest.java b/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/smap/AbstractSourceMapGeneratorTest.java
index ca78d1260..c9465fbae 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/smap/AbstractSourceMapGeneratorTest.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/compiler/org/eclipse/objectteams/otdt/tests/compiler/smap/AbstractSourceMapGeneratorTest.java
@@ -365,7 +365,12 @@ public abstract class AbstractSourceMapGeneratorTest extends FileBasedModelTest
public void enterField(int declarationStart, int modifiers, char[] type, char[] name, int nameSourceStart, int nameSourceEnd)
{
}
-
+
+ @Override
+ public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
+ // TODO Auto-generated method stub
+ }
+
public void enterInitializer(int declarationStart, int modifiers)
{
}
@@ -440,60 +445,54 @@ public abstract class AbstractSourceMapGeneratorTest extends FileBasedModelTest
public void acceptProblem(CategorizedProblem problem) {
// TODO Auto-generated method stub
-
}
public void enterConstructor(MethodInfo methodInfo) {
// TODO Auto-generated method stub
-
}
public void enterField(FieldInfo fieldInfo) {
// TODO Auto-generated method stub
-
}
public void enterMethod(MethodInfo methodInfo) {
// TODO Auto-generated method stub
-
}
public void enterType(TypeInfo typeInfo) {
// TODO Auto-generated method stub
-
}
public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
// TODO Auto-generated method stub
-
}
-
+
+ @Override
+ public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ // TODO Auto-generated method stub
+ }
+
public void exitType(int declarationEnd) {
// TODO Auto-generated method stub
-
}
public void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers) {
// TODO Auto-generated method stub
-
}
public void acceptAnnotationTypeReference(char[][] annotation,
int sourceStart, int sourceEnd) {
// TODO Auto-generated method stub
-
}
public void acceptAnnotationTypeReference(char[] annotation,
int sourcePosition) {
// TODO Auto-generated method stub
-
}
public void acceptImport(int declarationStart, int declarationEnd, int nameStart, int nameEnd, char[][] tokens,
boolean onDemand, int modifiers) {
// TODO Auto-generated method stub
-
}
public void callback(CompilationUnitDeclaration cuDecl) {
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/parser/org/eclipse/objectteams/otdt/tests/parser/SourceElementParserTest.java b/testplugins/org.eclipse.objectteams.otdt.tests/parser/org/eclipse/objectteams/otdt/tests/parser/SourceElementParserTest.java
index d912fa28a..4dbed97ad 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/parser/org/eclipse/objectteams/otdt/tests/parser/SourceElementParserTest.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/parser/org/eclipse/objectteams/otdt/tests/parser/SourceElementParserTest.java
@@ -282,14 +282,17 @@ public class SourceElementParserTest extends FileBasedModelTest implements ISour
}
- public void enterType(TypeInfo typeInfo) {
+ @Override
+ public void enterRecordComponent(RecordComponentInfo recordComponentInfo) {
// TODO Auto-generated method stub
+ }
+ public void enterType(TypeInfo typeInfo) {
+ // TODO Auto-generated method stub
}
public void exitType(int declarationEnd) {
// TODO Auto-generated method stub
-
}
public void acceptProblem(CategorizedProblem problem) {
@@ -324,4 +327,8 @@ public class SourceElementParserTest extends FileBasedModelTest implements ISour
// TODO Auto-generated method stub
}
+ @Override
+ public void exitRecordComponent(int declarationEnd, int declarationSourceEnd) {
+ // TODO Auto-generated method stub
+ }
}

Back to the top