diff options
author | Manoj Palat | 2020-07-13 07:21:22 +0000 |
---|---|---|
committer | Manoj Palat | 2020-07-13 15:35:08 +0000 |
commit | 1f989750adec758a5493b867b0bb9516aa5acd7d (patch) | |
tree | 2a47930c63fbd7246d8888a40dd691450f0ca45b | |
parent | 324a46c1459e2f1dc647c2c783838e64f166b7d4 (diff) | |
parent | 5ba272a2d4a7478e0eb3951208ab49b7c069f37d (diff) | |
download | eclipse.jdt.core-1f989750adec758a5493b867b0bb9516aa5acd7d.tar.gz eclipse.jdt.core-1f989750adec758a5493b867b0bb9516aa5acd7d.tar.xz eclipse.jdt.core-1f989750adec758a5493b867b0bb9516aa5acd7d.zip |
into BETA_JAVA15
# Conflicts:
# org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
# org.eclipse.jdt.core.tests.compiler/pom.xml
# org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
# org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
# org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
# org.eclipse.jdt.core.tests.model/pom.xml
# org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter14Test.java
# org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
# org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
# org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
# org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
Change-Id: I16440b774180ed8357438a1e76843bf012df959f
74 files changed, 2719 insertions, 415 deletions
diff --git a/org.eclipse.jdt.compiler.tool.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.compiler.tool.tests/META-INF/MANIFEST.MF index 0de998afc8..e64e12b710 100644 --- a/org.eclipse.jdt.compiler.tool.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.compiler.tool.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.compiler.tool.tests -Bundle-Version: 1.2.700.qualifier +Bundle-Version: 1.2.800.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/org.eclipse.jdt.compiler.tool.tests/pom.xml b/org.eclipse.jdt.compiler.tool.tests/pom.xml index 870e13bce3..c262b3fd71 100644 --- a/org.eclipse.jdt.compiler.tool.tests/pom.xml +++ b/org.eclipse.jdt.compiler.tool.tests/pom.xml @@ -20,7 +20,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.compiler.tool.tests</artifactId> - <version>1.2.700-SNAPSHOT</version> + <version>1.2.800-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> <testSuite>${project.artifactId}</testSuite> diff --git a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java index aceffbbb05..2b33f67f05 100644 --- a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java +++ b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Locale; import java.util.ServiceLoader; import java.util.Set; +import java.util.stream.Collectors; import javax.lang.model.SourceVersion; import javax.tools.Diagnostic; @@ -1157,6 +1158,111 @@ static final String[] FAKE_ZERO_ARG_OPTIONS = new String[] { //passing in the directory to no warn should ignore the path - resulting in no warnings. assertEquals("No error should be reported", 0, errors.size()); } + + private void suppressTest(String fileName, String source, String expectedDiagnostics, String expectedOutput) throws Exception { + String tmpFolder = new File(System.getProperty("java.io.tmpdir")).getCanonicalPath(); + File inputFile = new File(tmpFolder, fileName); + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(inputFile)); + writer.write(source); + writer.flush(); + writer.close(); + } catch (IOException e) { + // ignore + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + // ignore + } + } + } + + // System compiler + StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset()); + + // create new list containing inputfile + List<File> files = new ArrayList<File>(); + files.add(inputFile); + Iterable<? extends JavaFileObject> units = manager.getJavaFileObjectsFromFiles(files); + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + + List<String> options = new ArrayList<String>(); + options.add("-d"); + options.add(tmpFolder); + options.add("-warn:+unused,boxing"); + final List<Diagnostic<JavaFileObject>> errors = new ArrayList<>(); + CompilationTask task = compiler.getTask(printWriter, manager, new DiagnosticListener<JavaFileObject>() { + + @SuppressWarnings("unchecked") + @Override + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + errors.add((Diagnostic<JavaFileObject>) diagnostic); + } + + }, options, null, units); + task.call(); + printWriter.flush(); + printWriter.close(); + + assertEquals("Unexpected diagnostics:", expectedDiagnostics, + errors.stream() + .map(d -> d.getKind().toString() + ' ' + + d.getLineNumber() + ": " + d.getMessage(Locale.getDefault())) + .collect(Collectors.joining("\n"))); + assertEquals("Unexpected output:", expectedOutput.replaceAll("---OUTPUT_DIR_PLACEHOLDER---", tmpFolder), stringWriter.toString()); + } + + public void testCompilerSimpleSuppressWarnings() throws Exception { + suppressTest("p/SuppressTest.java", + "package p;\n" + + "public class SuppressTest {\n" + + "@SuppressWarnings(\"boxing\")\n" + + "public Long get(long l) {\n" + + " Long result = l * 2;\n" + + " return result;\n" + + "}\n}\n", + "", ""); + } + + public void testCompilerNestedSuppressWarnings() throws Exception { + suppressTest("p/SuppressTest.java", + "package p;\n" + + "@SuppressWarnings(\"unused\")\n" + + "public class SuppressTest {\n" + + "private String unused=\"testUnused\";\n" + + "@SuppressWarnings(\"boxing\")\n" + + "public Long get(long l) {\n" + + " Long result = l * 2;\n" + + " return result;\n" + + "}\n}\n", + "", ""); + } + + public void testCompilerUnrelatedSuppressWarnings() throws Exception { + suppressTest("p/SuppressTest.java", + "package p;\n" + + "@SuppressWarnings(\"unused\")\n" + + "public class SuppressTest {\n" + + "private String unused=\"testUnused\";\n" + + "public Long get(long l) {\n" + + " Long result = l * 2;\n" + + " return result;\n" + + "}\n}\n", + "WARNING 6: The expression of type long is boxed into java.lang.Long", + "----------\n" + + "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/SuppressTest.java (at line 6)\n" + + " Long result = l * 2;\n" + + " ^^^^^\n" + + "The expression of type long is boxed into Long\n" + + "----------\n" + + "1 problem (1 warning)\n" + ); + } + public void testSupportedCompilerVersions() throws IOException { Set<SourceVersion> sourceVersions = compiler.getSourceVersions(); SourceVersion[] values = SourceVersion.values(); diff --git a/org.eclipse.jdt.core.tests.builder/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.builder/META-INF/MANIFEST.MF index fe8d50e0b1..df663955d5 100644 --- a/org.eclipse.jdt.core.tests.builder/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core.tests.builder/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core.tests.builder; singleton:=true -Bundle-Version: 3.10.900.qualifier +Bundle-Version: 3.10.1000.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.jdt.core.tests.builder diff --git a/org.eclipse.jdt.core.tests.builder/pom.xml b/org.eclipse.jdt.core.tests.builder/pom.xml index 13a36c2906..e3f2621036 100644 --- a/org.eclipse.jdt.core.tests.builder/pom.xml +++ b/org.eclipse.jdt.core.tests.builder/pom.xml @@ -19,7 +19,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.core.tests.builder</artifactId> - <version>3.10.900-SNAPSHOT</version> + <version>3.10.1000-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/Bug564905Test.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/Bug564905Test.java new file mode 100644 index 0000000000..86f54d2d5c --- /dev/null +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/Bug564905Test.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2020 Simeon Andreev 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: + * Simeon Andreev - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.builder; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.tests.util.Util; +import junit.framework.Test; + +public class Bug564905Test extends BuilderTests { + + private static final String OUTPUT_FOLDER_NAME = "bin"; + + private String projectName; + private IProject project; + private IPath projectPath; + private IPath src; + private IFolder outputFolder; + private boolean oldAutoBuilding; + + public Bug564905Test(String name) { + super(name); + } + + public static Test suite() { + return buildTestSuite(Bug564905Test.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + this.projectName = "Bug564905Test"; + this.projectPath = env.addProject(this.projectName); + this.project = env.getWorkspace().getRoot().getProject(this.projectName); + env.addExternalJars(this.projectPath, Util.getJavaClassLibs()); + + env.removePackageFragmentRoot(this.projectPath, ""); + String outputFolderPath = "tmp/" + OUTPUT_FOLDER_NAME; + this.src = env.addPackageFragmentRoot(this.projectPath, "src", null, outputFolderPath); + this.outputFolder = env.getWorkspace().getRoot().getFolder(this.projectPath.append(outputFolderPath)); + + this.oldAutoBuilding = env.isAutoBuilding(); + env.setAutoBuilding(true); + waitForAutoBuild(); + } + + @Override + protected void tearDown() throws Exception { + TestBuilderParticipant.PARTICIPANT = null; + env.removeProject(this.projectPath); + env.setAutoBuilding(this.oldAutoBuilding); + waitForAutoBuild(); + + super.tearDown(); + } + + /** + * Test for Bug 564905, with option {@code org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder} enabled. + * + * When the output folder of a project is removed in file system, on refresh we expect a build. + */ + public void testBug564905_recreateModifiedClassFileInOutputFolder_enabled() throws Exception { + enableOption_recreateModifiedClassFileInOutputFolder(); + assertOutputFolderEmpty(); + + addSourceAndBuild(); + assertOutputFolderNotEmpty(); + + deleteOutputFolderAndWaitForAutoBuild(); + // we enabled "recreateModifiedClassFileInOutputFolder", so we expect compile artifacts + assertOutputFolderNotEmpty(); + } + + /** + * Test for Bug 564905, with option {@code org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder} disabled. + * + * When the output folder of a project is removed in file system, on refresh we don't expect a build + * as we don't use the option {@link JavaCore#CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER}. + */ + public void testBug564905_recreateModifiedClassFileInOutputFolder_disabled() throws Exception { + disableOption_recreateModifiedClassFileInOutputFolder(); + assertOutputFolderEmpty(); + + addSourceAndBuild(); + assertOutputFolderNotEmpty(); + + deleteOutputFolderAndWaitForAutoBuild(); + // we disabled "recreateModifiedClassFileInOutputFolder", so we don't expect compile artifacts + assertOutputFolderEmpty(); + } + + private void deleteOutputFolderAndWaitForAutoBuild() throws Exception { + // close the project, since the bug 564905 occurs when build state is read from disk + this.project.close(new NullProgressMonitor()); + waitForAutoBuild(); + URI outputFolderUri = this.outputFolder.getLocationURI(); + // delete the output folder with file system API, so that Eclipse resources API "doesn't notice" + deleteFolderInFileSystem(outputFolderUri); + + // re-open the project, refresh it, then wait for auto-build; expect that something was built + this.project.open(new NullProgressMonitor()); + this.project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); + waitForAutoBuild(); + } + + private void addSourceAndBuild() { + IPath srcPackage = env.addPackage(this.src, "p"); + IFolder srcPackageFolder = env.getWorkspace().getRoot().getFolder(srcPackage); + assertTrue("package in source must exist", srcPackageFolder.exists()); + env.addClass(this.src, "p", "X", "package p;\n public interface X { void foo() { /* we want something compiled, anything works */ } }"); + fullBuild(this.projectPath); + } + + private void enableOption_recreateModifiedClassFileInOutputFolder() throws Exception { + setJavaProjectOption(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER, JavaCore.ENABLED); + } + + private void disableOption_recreateModifiedClassFileInOutputFolder() throws Exception { + setJavaProjectOption(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER, JavaCore.DISABLED); + } + + private void setJavaProjectOption(String optionName, String optionValue) throws Exception { + IJavaProject javaProject = JavaCore.create(this.project); + javaProject.setOption(optionName, optionValue); + this.project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); + waitForAutoBuild(); + } + + private void waitForAutoBuild() throws InterruptedException { + Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, new NullProgressMonitor()); + } + + private static void deleteFolderInFileSystem(URI uri) throws IOException { + Files.walkFileTree(Paths.get(uri), new DeleteVisitor()); + } + + private void assertOutputFolderEmpty() throws CoreException { + assertTrue("output folder must exist", this.outputFolder.exists()); + IResource[] outputFolderContent = this.outputFolder.members(); + assertEquals("output folder must be empty, instead had contents: " + toString(outputFolderContent), 0, outputFolderContent.length); + } + + private void assertOutputFolderNotEmpty() throws CoreException { + assertTrue("output folder must exist", this.outputFolder.exists()); + assertTrue("output folder must not be empty", this.outputFolder.members().length > 0); + } + + private static String toString(IResource[] resources) { + StringBuilder result = new StringBuilder(); + for (IResource resource : resources) { + result.append(resource.getName()); + result.append(System.lineSeparator()); + } + return result.toString(); + } + + static class DeleteVisitor extends SimpleFileVisitor<Path> { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + if (exc != null) { + throw exc; + } + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + } +} diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java index fbb210a593..1938645b43 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java @@ -548,6 +548,7 @@ public class BuilderTests extends TestCase { Bug530366Test.class, Bug531382Test.class, Bug549457Test.class, + Bug564905Test.class, Bug561287Test.class, Bug562420Test.class, LeakTestsBefore9.class, diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/StateTest.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/StateTest.java index f3ddd9a730..fed6380618 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/StateTest.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/StateTest.java @@ -120,6 +120,13 @@ public class StateTest extends BuilderTests { State readState = JavaBuilder.readState(project, new DataInputStream(new ByteArrayInputStream(bytes))); Map<String, ReferenceCollection> readReferences = readState.getReferences(); assertEqualLookupTables(savedState.getReferences(), readReferences); + assertEqualTypeLocators(savedState.typeLocators, readState.typeLocators); + } + + private void assertEqualTypeLocators(Map<String, String> tl1, Map<String, String> tl2) { + assertEquals(tl1.size(), tl2.size()); + assertEquals(tl1.toString(), tl2.toString()); + } private void assertEqualLookupTables(Map<String, ReferenceCollection> expectation, Map<String, ReferenceCollection> actual) { diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF index 1ca65388dd..7d73e06f44 100644 --- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true -Bundle-Version: 3.12.1250.qualifier +Bundle-Version: 3.12.1350.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.jdt.core.tests.compiler, diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml index 16cca4b727..33eb45b740 100644 --- a/org.eclipse.jdt.core.tests.compiler/pom.xml +++ b/org.eclipse.jdt.core.tests.compiler/pom.xml @@ -20,7 +20,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.core.tests.compiler</artifactId> - <version>3.12.1250-SNAPSHOT</version> + <version>3.12.1350-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java index 88aa24d971..41978bdaa4 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java @@ -1986,11 +1986,9 @@ public void test0042() { " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Syntax error on tokens, delete these tokens\n" + "----------\n"; - @SuppressWarnings("unused") String expected14ProblemLog = expected13ProblemLog; - @SuppressWarnings("unused") String expected15ProblemLog = "----------\n" + "1. ERROR in X.java (at line 1)\n" + 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 e2eac64583..9cfdd0fde1 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 @@ -1261,6 +1261,7 @@ public void test011_problem_categories() { expectedProblemAttributes.put("RecordComponentsCannotHaveModifiers", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("RecordIllegalParameterNameInCanonicalConstructor", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("RecordIllegalExplicitFinalFieldAssignInCompactConstructor", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); + expectedProblemAttributes.put("RecordMissingExplicitConstructorCallInNonCanonicalConstructor", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("SealedMissingClassModifier", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("SealedDisAllowedNonSealedModifierInClass", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); expectedProblemAttributes.put("SealedSuperClassDoesNotPermit", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED)); @@ -2305,6 +2306,7 @@ public void test012_compiler_problems_tuning() { expectedProblemAttributes.put("RecordIllegalVararg", SKIP); expectedProblemAttributes.put("RecordStaticReferenceToOuterLocalVariable",SKIP); expectedProblemAttributes.put("RecordCannotDefineRecordInLocalType",SKIP); + expectedProblemAttributes.put("RecordMissingExplicitConstructorCallInNonCanonicalConstructor",SKIP); expectedProblemAttributes.put("RecordComponentsCannotHaveModifiers",SKIP); expectedProblemAttributes.put("RecordIllegalParameterNameInCanonicalConstructor",SKIP); expectedProblemAttributes.put("RecordIllegalExplicitFinalFieldAssignInCompactConstructor",SKIP); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java index e25b8f4420..da7dc30c9e 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 @@ -1288,12 +1288,7 @@ public class RecordsRestrictedClassTest extends AbstractRegressionTest { "2. ERROR in X.java (at line 12)\n" + " public Point(Integer myInt) {}\n" + " ^^^^^^^^^^^^^^^^^^^^\n" + - "The blank final field myInt may not have been initialized\n" + - "----------\n" + - "3. ERROR in X.java (at line 12)\n" + - " public Point(Integer myInt) {}\n" + - " ^^^^^^^^^^^^^^^^^^^^\n" + - "The blank final field myZ may not have been initialized\n" + + "A non-canonical constructor must start with an explicit invocation to a constructor\n" + "----------\n"); } public void testBug553152_016() { @@ -4525,4 +4520,130 @@ public void testBug562637_001() { " 0 aload_0 [this]\n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X$R.class", ClassFileBytesDisassembler.SYSTEM); } + public void testBug564146_001() { + this.runNegativeTest( + new String[] { + "X.java", + "public record X(int i) {\n"+ + " public X() {\n"+ + " this.i = 10;\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 2)\n" + + " public X() {\n" + + " ^^^\n" + + "A non-canonical constructor must start with an explicit invocation to a constructor\n" + + "----------\n"); + } + public void testBug564146_002() { + this.runNegativeTest( + new String[] { + "X.java", + "public record X(int i) {\n"+ + " public X() {\n"+ + " super();\n"+ + " this.i = 10;\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 2)\n" + + " public X() {\n" + + " ^^^\n" + + "A non-canonical constructor must start with an explicit invocation to a constructor\n" + + "----------\n"); + } + public void testBug564146_003() { + this.runNegativeTest( + new String[] { + "X.java", + "public record X(int i) {\n"+ + " public X(int i) {\n"+ + " this.i = 10;\n"+ + " Zork();\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + " Zork();\n" + + " ^^^^\n" + + "The method Zork() is undefined for the type X\n" + + "----------\n"); + } + public void testBug564146_004() { + runConformTest( + new String[] { + "X.java", + "public record X(int i) {\n"+ + " public X() {\n"+ + " this(10);\n"+ + " }\n"+ + " public static void main(String[] args) {\n"+ + " System.out.println(new X().i());\n"+ + " }\n"+ + "}" + }, + "10"); + } + public void testBug564146_005() { + this.runNegativeTest( + new String[] { + "X.java", + "public record X() {\n"+ + " public X(int i) {\n"+ + " this(10);\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " this(10);\n" + + " ^^^^^^^^^\n" + + "Recursive constructor invocation X(int)\n" + + "----------\n"); + } + public void testBug564146_006() { + this.runNegativeTest( + new String[] { + "X.java", + "public record X() {\n"+ + " public X() {\n"+ + " System.out.println(10);\n"+ + " this(10);\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 4)\n" + + " this(10);\n" + + " ^^^^^^^^^\n" + + "The body of a canonical constructor must not contain an explicit constructor call\n" + + "----------\n" + + "2. ERROR in X.java (at line 4)\n" + + " this(10);\n" + + " ^^^^^^^^^\n" + + "Constructor call must be the first statement in a constructor\n" + + "----------\n"); + } + public void testBug564146_007() { + runConformTest( + new String[] { + "X.java", + "public record X(int i) {\n"+ + " public X() {\n"+ + " this(10);\n"+ + " }\n"+ + " public X(int i, int k) {\n"+ + " this();\n"+ + " }\n"+ + " public static void main(String[] args) {\n"+ + " System.out.println(new X(2, 3).i());\n"+ + " }\n"+ + "}" + }, + "10"); + } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RunComparableTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RunComparableTests.java index 11da6f7037..05806e73c6 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RunComparableTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RunComparableTests.java @@ -33,6 +33,7 @@ public class RunComparableTests extends junit.framework.TestCase { ALL_CLASSES = new ArrayList(); ALL_CLASSES.add(AmbiguousMethodTest.class); ALL_CLASSES.add(AutoBoxingTest.class); + ALL_CLASSES.add(SuppressWarningsTest.class); ALL_CLASSES.add(Compliance_1_5.class); ALL_CLASSES.add(GenericTypeTest.class); ALL_CLASSES.add(GenericsRegressionTest.class); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SuppressWarningsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SuppressWarningsTest.java new file mode 100644 index 0000000000..95d6ff97a2 --- /dev/null +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SuppressWarningsTest.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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 + *******************************************************************************/ +package org.eclipse.jdt.core.tests.compiler.regression; + +import java.io.File; +import java.util.Map; + +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +import junit.framework.Test; + +@SuppressWarnings({ "rawtypes" }) +public class SuppressWarningsTest extends AbstractBatchCompilerTest { + + public SuppressWarningsTest(String name) { + super(name); + } + + public static Test suite() { + return buildMinimalComplianceTestSuite(testClass(), F_1_5); + } + + public static Class testClass() { + return SuppressWarningsTest.class; + } + + @SuppressWarnings("unchecked") + @Override + protected Map getCompilerOptions() { + Map options = super.getCompilerOptions(); + options.put(CompilerOptions.OPTION_SuppressWarnings, CompilerOptions.ENABLED); + options.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.WARNING); + options.put(CompilerOptions.OPTION_ReportAutoboxing, CompilerOptions.WARNING); + return options; + } + + public void testSimpleSuppressWarnings() { + this.runTest(true, + new String[] { + "p/SuppressTest.java", + "package p;\n" + + "public class SuppressTest {\n" + + "@SuppressWarnings(\"boxing\")\n" + + "public Long get(long l) {\n" + + " Long result = l * 2;\n" + + " return result;\n" + + "}\n}\n" + }, + "\"" + OUTPUT_DIR + File.separator + "p/SuppressTest.java\"" + + " -warn:+unused -warn:+boxing " + + " -1.5 -g -preserveAllLocals" + + " -d \"" + OUTPUT_DIR + "\" ", + "", "", true, null); + } + + public void testNestedSuppressWarnings() { + this.runTest(true, + new String[] { + "p/SuppressTest.java", + "package p;\n" + + "@SuppressWarnings(\"unused\")\n" + + "public class SuppressTest {\n" + + "private String unused=\"testUnused\";\n" + + "@SuppressWarnings(\"boxing\")\n" + + "public Long get(long l) {\n" + + " Long result = l * 2;\n" + + " return result;\n" + + "}\n}\n" + }, + "\"" + OUTPUT_DIR + File.separator + "p/SuppressTest.java\"" + + " -warn:+unused -warn:+boxing " + + " -1.5 -g -preserveAllLocals" + + " -d \"" + OUTPUT_DIR + "\" ", + "", "", true, null); + } + + public void testUnrelatedSuppressWarnings() { + this.runTest(true, + new String[] { + "p/SuppressTest.java", + "package p;\n" + + "@SuppressWarnings(\"unused\")\n" + + "public class SuppressTest {\n" + + "private String unused=\"testUnused\";\n" + + "public Long get(long l) {\n" + + " Long result = l * 2;\n" + + " return result;\n" + + "}\n}\n" + }, + "\"" + OUTPUT_DIR + File.separator + "p/SuppressTest.java\"" + + " -warn:+unused -warn:+boxing " + + " -1.5 -g -preserveAllLocals" + + " -d \"" + OUTPUT_DIR + "\" ", + "", + "----------\n" + + "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/SuppressTest.java (at line 6)\n" + + " Long result = l * 2;\n" + + " ^^^^^\n" + + "The expression of type long is boxed into Long\n" + + "----------\n" + + "1 problem (1 warning)\n", + true, null); + } + +} diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java index 1021a161ef..29b91a9510 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java @@ -33,6 +33,7 @@ import org.eclipse.jdt.core.util.ClassFileBytesDisassembler; import org.eclipse.jdt.internal.compiler.Compiler; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; @@ -57,8 +58,8 @@ public class TypeAnnotationTest extends AbstractRegressionTest { // Enables the tests to run individually @Override - protected Map getCompilerOptions() { - Map defaultOptions = super.getCompilerOptions(); + protected Map<String, String> getCompilerOptions() { + Map<String, String> defaultOptions = super.getCompilerOptions(); defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8); defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8); defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8); @@ -6942,5 +6943,25 @@ public class TypeAnnotationTest extends AbstractRegressionTest { assertEquals("Base.Static.@A2 Static2<@B1 Exception>.@A3 Middle1.@A4 Middle2<@B2 Class<@C1 Object @C2 []> @B3 []>.@A5 Middle3.@A6 GenericInner<@B4 String> @A7 [] @A8 []", new String(methods3[0].parameters[0].annotatedDebugName())); } -} + public void testBug594561_ParameterizedTypeAnnotations() { + runConformTest(new String[] { + "p/C.java", + "package p;" + + "@Deprecated\n" + + "abstract class A<T> {}\n" + + "class C extends A<String> {}\n", + }); + + Requestor requestor = new Requestor(false, null, false, false); + Map<String, String> customOptions = getCompilerOptions(); customOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED); + Compiler compiler = new Compiler(getNameEnvironment(new String[0], null), getErrorHandlingPolicy(), new CompilerOptions(customOptions), requestor, getProblemFactory()); + + ReferenceBinding type = compiler.lookupEnvironment.askForType(new char[][] {"p".toCharArray(), "C".toCharArray()}, compiler.lookupEnvironment.UnNamedModule); + assertNotNull(type); + + AnnotationBinding[] annos = type.superclass().getAnnotations(); + assertEquals(1, annos.length); + assertEquals("java.lang.Deprecated", annos[0].getAnnotationType().debugName()); + } +} diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF index 71d7a4813c..3c82a7b86f 100644 --- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true -Bundle-Version: 3.10.1250.qualifier +Bundle-Version: 3.10.1350.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.jdt.core.tests, diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml index 5bf80e6c9e..0ed43fde63 100644 --- a/org.eclipse.jdt.core.tests.model/pom.xml +++ b/org.eclipse.jdt.core.tests.model/pom.xml @@ -20,7 +20,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.core.tests.model</artifactId> - <version>3.10.1250-SNAPSHOT</version> + <version>3.10.1350-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java index 84c132f138..f5df0ae5ef 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java @@ -7952,7 +7952,7 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup { * @bug 149126: IllegalArgumentException in ASTConverter * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=149126" */ - public void _test0652() throws CoreException { + public void test0652() throws CoreException { ASTResult result = this.buildMarkedAST( "/Converter/src/TestCharset.java", "import java.nio.ByteBuffer;\n" + @@ -7987,8 +7987,7 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup { "public class TestCharset extends Charset {\n" + " public CharsetDecoder newDecoder(){\n" + " return new CharsetDecoder(this,2.0,2.0){\n" + - " void CharsetDecoder(){\n" + - " }\n" + + " void CharsetDecoder();\n" + " protected CoderResult decodeLoop( ByteBuffer in, CharBuffer out){\n" + " return null;\n" + " }\n" + @@ -8041,25 +8040,33 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup { "CharsetDecoder cannot be resolved to a type\n" + "10. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + " CharsetDecoder(CharSet\n" + - " ^^^^^^^^^^^^^^^^^^^^^^\n" + - "Syntax error on token(s), misplaced construct(s)\n" + - "11. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + - " CharsetDecoder(CharSet\n" + " ^^^^^^^^^^^^^^^\n" + "Return type for the method is missing\n" + - "12. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + + "11. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + + " CharsetDecoder(CharSet\n" + + " ^^^^^^^\n" + + "Syntax error, insert \"... VariableDeclaratorId\" to complete FormalParameter\n" + + "12. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + + " CharsetDecoder(CharSet\n" + + " ^^^^^^^\n" + + "Syntax error, insert \")\" to complete ConstructorDeclaration\n" + + "13. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + + " CharsetDecoder(CharSet\n" + + " ^^^^^^^\n" + + "Syntax error, insert \";\" to complete ClassBodyDeclarations\n" + + "14. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + " protected CoderResult decodeLoop(ByteBuffer in,\n" + " ^^^^^^^^^^^\n" + "CoderResult cannot be resolved to a type\n" + - "13. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + + "15. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + " protected CoderResult decodeLoop(ByteBuffer in,\n" + " ^^^^^^^^^^\n" + "ByteBuffer cannot be resolved to a type\n" + - "14. ERROR in /Converter/src/TestCharset.java (at line 12)\n" + + "16. ERROR in /Converter/src/TestCharset.java (at line 12)\n" + " CharBuffer out) {\n" + " ^^^^^^^^^^\n" + "CharBuffer cannot be resolved to a type\n" + - "15. ERROR in /Converter/src/TestCharset.java (at line 17)\n" + + "17. ERROR in /Converter/src/TestCharset.java (at line 17)\n" + " public CharsetEncoder newEncoder() {\n" + " ^^^^^^^^^^^^^^\n" + "CharsetEncoder cannot be resolved to a type\n", @@ -8328,10 +8335,11 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup { assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, root.getNodeType()); CompilationUnit unit = (CompilationUnit) root; String errors = - "Syntax error on token(s), misplaced construct(s)\n" + - "Syntax error, insert \";\" to complete BlockStatements\n" + - "Syntax error on token(s), misplaced construct(s)\n" + - "Syntax error, insert \";\" to complete Statement"; + "Syntax error on token(s), misplaced construct(s)\n" + + "Syntax error, insert \";\" to complete BlockStatements\n" + + "Syntax error on token(s), misplaced construct(s)\n" + + "Syntax error, insert \";\" to complete Statement"; + assertProblemsSize(unit, 4, errors); } @@ -9436,12 +9444,12 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup { /* * https://bugs.eclipse.org/bugs/show_bug.cgi?id=169745 */ - public void _test0679() throws JavaModelException { + public void test0679() throws JavaModelException { ICompilationUnit workingCopy = null; try { String contents = "public class X {\n" + - " int i = 1 - 2 + 3 + 4 + 5;\n" + + " int i = 1 - 2 + 3 + 4 * 5;\n" + "}"; workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/); ASTNode node = buildAST( @@ -9459,10 +9467,11 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup { final Expression initializer = fragment.getInitializer(); assertEquals("Not an infix expression", ASTNode.INFIX_EXPRESSION, initializer.getNodeType()); InfixExpression infixExpression = (InfixExpression) initializer; - final Expression leftOperand = infixExpression.getLeftOperand(); - assertEquals("Not a number literal", ASTNode.NUMBER_LITERAL, leftOperand.getNodeType()); - NumberLiteral literal = (NumberLiteral) leftOperand; - assertEquals("Wrong value", "1", literal.getToken()); + final Expression rightOperand = infixExpression.getRightOperand(); + InfixExpression rightOperand2 = (InfixExpression) rightOperand; + assertEquals("Not a number literal", ASTNode.NUMBER_LITERAL, rightOperand2.getRightOperand().getNodeType()); + NumberLiteral literal = (NumberLiteral) rightOperand2.getRightOperand(); + assertEquals("Wrong value", "5", literal.getToken()); } finally { if (workingCopy != null) workingCopy.discardWorkingCopy(); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java index 980ade0880..dd73458de4 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2019 IBM Corporation and others. + * Copyright (c) 2011, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -7949,7 +7949,7 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup { * @bug 149126: IllegalArgumentException in ASTConverter * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=149126" */ - public void _test0652() throws CoreException { + public void test0652() throws CoreException { ASTResult result = this.buildMarkedAST( "/Converter/src/TestCharset.java", "import java.nio.ByteBuffer;\n" + @@ -7984,8 +7984,7 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup { "public class TestCharset extends Charset {\n" + " public CharsetDecoder newDecoder(){\n" + " return new CharsetDecoder(this,2.0,2.0){\n" + - " void CharsetDecoder(){\n" + - " }\n" + + " void CharsetDecoder();\n" + " protected CoderResult decodeLoop( ByteBuffer in, CharBuffer out){\n" + " return null;\n" + " }\n" + @@ -8038,25 +8037,33 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup { "CharsetDecoder cannot be resolved to a type\n" + "10. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + " CharsetDecoder(CharSet\n" + - " ^^^^^^^^^^^^^^^^^^^^^^\n" + - "Syntax error on token(s), misplaced construct(s)\n" + - "11. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + - " CharsetDecoder(CharSet\n" + " ^^^^^^^^^^^^^^^\n" + "Return type for the method is missing\n" + - "12. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + + "11. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + + " CharsetDecoder(CharSet\n" + + " ^^^^^^^\n" + + "Syntax error, insert \"... VariableDeclaratorId\" to complete FormalParameter\n" + + "12. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + + " CharsetDecoder(CharSet\n" + + " ^^^^^^^\n" + + "Syntax error, insert \")\" to complete ConstructorDeclaration\n" + + "13. ERROR in /Converter/src/TestCharset.java (at line 10)\n" + + " CharsetDecoder(CharSet\n" + + " ^^^^^^^\n" + + "Syntax error, insert \";\" to complete ClassBodyDeclarations\n" + + "14. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + " protected CoderResult decodeLoop(ByteBuffer in,\n" + " ^^^^^^^^^^^\n" + "CoderResult cannot be resolved to a type\n" + - "13. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + + "15. ERROR in /Converter/src/TestCharset.java (at line 11)\n" + " protected CoderResult decodeLoop(ByteBuffer in,\n" + " ^^^^^^^^^^\n" + "ByteBuffer cannot be resolved to a type\n" + - "14. ERROR in /Converter/src/TestCharset.java (at line 12)\n" + + "16. ERROR in /Converter/src/TestCharset.java (at line 12)\n" + " CharBuffer out) {\n" + " ^^^^^^^^^^\n" + "CharBuffer cannot be resolved to a type\n" + - "15. ERROR in /Converter/src/TestCharset.java (at line 17)\n" + + "17. ERROR in /Converter/src/TestCharset.java (at line 17)\n" + " public CharsetEncoder newEncoder() {\n" + " ^^^^^^^^^^^^^^\n" + "CharsetEncoder cannot be resolved to a type\n", @@ -9433,12 +9440,12 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup { /* * https://bugs.eclipse.org/bugs/show_bug.cgi?id=169745 */ - public void _test0679() throws JavaModelException { + public void test0679() throws JavaModelException { ICompilationUnit workingCopy = null; try { String contents = "public class X {\n" + - " int i = 1 - 2 + 3 + 4 + 5;\n" + + " int i = 1 - 2 + 3 + 4 * 5;\n" + "}"; workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/); ASTNode node = buildAST( @@ -9456,10 +9463,11 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup { final Expression initializer = fragment.getInitializer(); assertEquals("Not an infix expression", ASTNode.INFIX_EXPRESSION, initializer.getNodeType()); InfixExpression infixExpression = (InfixExpression) initializer; - final Expression leftOperand = infixExpression.getLeftOperand(); - assertEquals("Not a number literal", ASTNode.NUMBER_LITERAL, leftOperand.getNodeType()); - NumberLiteral literal = (NumberLiteral) leftOperand; - assertEquals("Wrong value", "1", literal.getToken()); + final Expression rightOperand = infixExpression.getRightOperand(); + InfixExpression rightOperand2 = (InfixExpression) rightOperand; + assertEquals("Not a number literal", ASTNode.NUMBER_LITERAL, rightOperand2.getRightOperand().getNodeType()); + NumberLiteral literal = (NumberLiteral) rightOperand2.getRightOperand(); + assertEquals("Wrong value", "5", literal.getToken()); } finally { if (workingCopy != null) workingCopy.discardWorkingCopy(); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java index a906d67cac..dbc23b851e 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java @@ -15639,4 +15639,137 @@ public void testBug553155p() throws JavaModelException { formatSource(source, "record Range(int lo, int hi) { public Range { foo(); } }"); } +/** + * https://bugs.eclipse.org/118641 - [formatter] Formatter does not break line on assert statement + * + * Check that assertions are not formatted without enabling the option. + */ +public void testBug118641a() throws JavaModelException { + this.formatterPrefs.alignment_for_assertion_message = Alignment.M_NO_ALIGNMENT; + + String input = + "public class Test {\n" + + "\n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName(FIELD_NAME).getLength() == 1 : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"; + formatSource(input, + "public class Test {\n" + + "\n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName(FIELD_NAME)\n" + + " .getLength() == 1 : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"); +} +/** + * https://bugs.eclipse.org/118641 - [formatter] Formatter does not break line on assert statement + * + * + * Check that an assertion is formatted when it exceeds the page width. + */ +public void testBug118641b() throws JavaModelException { + this.formatterPrefs.wrap_before_assertion_message_operator = true; + + String input = + "public class Test {\n" + + " \n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName( FIELD_NAME ).getLength() == 1 : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"; + formatSource(input, + "public class Test {\n" + + "\n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName(FIELD_NAME).getLength() == 1\n" + + " : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"); +} +/** + * https://bugs.eclipse.org/118641 - [formatter] Formatter does not break line on assert statement + * + * + * Check that an assertion can be broken after the colon separator. + */ +public void testBug118641c() throws JavaModelException { + this.formatterPrefs.wrap_before_assertion_message_operator = false; + + String input = + "public class Test {\n" + + " \n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName( FIELD_NAME ).getLength() == 1 : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"; + formatSource(input, + "public class Test {\n" + + "\n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName(FIELD_NAME).getLength() == 1 :\n" + + " \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"); +} +/** + * https://bugs.eclipse.org/118641 - [formatter] Formatter does not break line on assert statement + * + * Check that assertion messages are formatted when the assertion expression exceeds the page width. + */ +public void testBug118641d() throws JavaModelException { + this.formatterPrefs.page_width = 65; + + String input = + "public class Test {\n" + + " \n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName( FIELD_NAME ).getLength() == 1 : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"; + formatSource(input, + "public class Test {\n" + + "\n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName(FIELD_NAME)\n" + + " .getLength() == 1\n" + + " : \"XML malformed. No attribute name! Please talk to your sysadmin.\";\n" + + " return;\n" + + " }\n" + + "}"); +} +/** + * https://bugs.eclipse.org/118641 - [formatter] Formatter does not break line on assert statement + * + * Check that an assertion message is wrapped when forced to do so. + */ +public void testBug118641e() throws JavaModelException { + this.formatterPrefs.alignment_for_assertion_message = Alignment.M_COMPACT_SPLIT | Alignment.M_FORCE; + + String input = + "public class Test {\n" + + " \n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName( FIELD_NAME ).getLength() == 1 : \"XML malformed. No attribute name!\";\n" + + " return;\n" + + " }\n" + + "}"; + formatSource(input, + "public class Test {\n" + + "\n" + + " public void f(int a, int b) {\n" + + " assert childElement.getElementsByTagName(FIELD_NAME).getLength() == 1\n" + + " : \"XML malformed. No attribute name!\";\n" + + " return;\n" + + " }\n" + + "}"); +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java index fbfef08d21..6eb59dfa22 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java @@ -15,6 +15,7 @@ package org.eclipse.jdt.core.tests.model; import java.util.Arrays; import java.util.Comparator; +import java.util.function.Predicate; import org.eclipse.jdt.core.CompletionContext; import org.eclipse.jdt.core.CompletionProposal; @@ -52,6 +53,8 @@ public class CompletionTestsRequestor2 extends CompletionRequestor { public boolean debug = false; + private Predicate<CompletionProposal> proposalFilter = x -> true; + public CompletionTestsRequestor2() { this(false, false); } @@ -96,6 +99,9 @@ public class CompletionTestsRequestor2 extends CompletionRequestor { this.context = cc; } public void accept(CompletionProposal proposal) { + if (!this.proposalFilter.test(proposal)) + return; + int length = this.proposals.length; if (++this.proposalsPtr== length) { System.arraycopy(this.proposals, 0, this.proposals = new CompletionProposal[length+PROPOSALS_INCREMENT], 0, length); @@ -625,6 +631,9 @@ public class CompletionTestsRequestor2 extends CompletionRequestor { public void setComputeEnclosingElement(boolean computeEnclosingElement) { this.computeEnclosingElement = computeEnclosingElement; } + public void setProposalFilter(Predicate<CompletionProposal> proposalFilter) { + this.proposalFilter = proposalFilter; + } public boolean canUseDiamond(int proposalNo) { if (proposalNo < this.proposals.length && this.proposals[proposalNo] != null) { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java index f6707a225c..0da17e690b 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java @@ -13,6 +13,9 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.model; +import java.util.function.Predicate; + +import org.eclipse.jdt.core.CompletionProposal; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.codeassist.impl.AssistOptions; @@ -53,7 +56,12 @@ public void tearDownSuite() throws Exception { } super.tearDownSuite(); } - +private CompletionTestsRequestor2 createFilteredRequestor() { + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + Predicate<CompletionProposal> javaTypeRef = p -> p.getKind() == CompletionProposal.TYPE_REF && new String(p.getSignature()).startsWith("Ljava."); + requestor.setProposalFilter(javaTypeRef.negate()); + return requestor; +} public void testQualifiedNonStaticMethod() throws JavaModelException { this.workingCopies = new ICompilationUnit[1]; this.workingCopies[0] = getWorkingCopy( @@ -68,7 +76,7 @@ public void testQualifiedNonStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "this.bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -95,7 +103,7 @@ public void testUnqualifiedNonStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -121,7 +129,7 @@ public void testQualifiedStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "Test.bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -146,7 +154,7 @@ public void testUnqualifiedStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "Bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -172,7 +180,7 @@ public void testQualifiedNonStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "this.item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -199,7 +207,7 @@ public void testUnqualifiedNonStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -225,7 +233,7 @@ public void testQualifiedStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "Test.item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -250,7 +258,7 @@ public void testUnqualifiedStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -277,7 +285,7 @@ public void testLocalVariable() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -304,7 +312,7 @@ public void testMethodParamVariable() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -318,48 +326,54 @@ public void testMethodParamVariable() throws JavaModelException { requestor.getResults()); } public void testClassTypeInstantiation() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " {\n" + " Foobar f = new bar\n" + " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "new bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "EvenMoreSpecificFooBar[TYPE_REF]{EvenMoreSpecificFooBar, test, Ltest.EvenMoreSpecificFooBar;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBSTRING) + "}\n" + - "SpecificFooBar[TYPE_REF]{SpecificFooBar, test, Ltest.SpecificFooBar;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBSTRING) + "}\n" + + "EvenMoreSpecificFooBar[TYPE_REF]{EvenMoreSpecificFooBar, test, Ltest.EvenMoreSpecificFooBar;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBSTRING) + "}\n" + + "SpecificFooBar[TYPE_REF]{SpecificFooBar, test, Ltest.SpecificFooBar;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBSTRING) + "}\n" + "Foobar[TYPE_REF]{Foobar, test, Ltest.Foobar;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBSTRING) + "}", requestor.getResults()); } public void testClassTypeFieldDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " public bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -372,20 +386,23 @@ public void testClassTypeFieldDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeParamDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " void setFoo(bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void setFoo(bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -398,22 +415,25 @@ public void testClassTypeParamDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeLocalVarDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " void foo() {\n" + " final bar" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -426,21 +446,24 @@ public void testClassTypeLocalVarDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeThrowsDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + - "class SpecificFooBar implements Foobar extends Exception {}\n" + + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz extends Exception {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " void foo() throws bar {\n" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo() throws bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -452,20 +475,23 @@ public void testClassTypeThrowsDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeExtends() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test extends bar {\n" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public class Test extends bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -477,21 +503,24 @@ public void testClassTypeExtends() throws JavaModelException { requestor.getResults()); } public void testClassTypeImplements() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "interface FoobarExtension extends Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test implements bar {\n" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public class Test implements bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -515,7 +544,7 @@ public void testInnerClassTypeInstantiation() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "t.new bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -535,7 +564,7 @@ public void testInnerClassTypeFieldDeclaration() throws JavaModelException { " public bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -555,7 +584,7 @@ public void testInnerClassTypeParamDeclaration() throws JavaModelException { " void foo(bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo(bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -577,7 +606,7 @@ public void testInnerClassTypeLocalVarDeclaration() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -597,7 +626,7 @@ public void testInnerClassTypeThrowsDeclaration() throws JavaModelException { " void foo() throws bar" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo() throws bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -617,7 +646,7 @@ public void testInnerClassTypeExtends() throws JavaModelException { " class SpecificFooBar extends bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "SpecificFooBar extends bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -637,7 +666,7 @@ public void testInnerClassTypeImplements() throws JavaModelException { " class SpecificFooBar implements bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "class SpecificFooBar implements bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -659,7 +688,7 @@ public void testStaticNestedClassTypeInstantiation() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "new bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -679,7 +708,7 @@ public void testStaticNestedClassTypeFieldDeclaration() throws JavaModelExceptio " public bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -699,7 +728,7 @@ public void testStaticNestedClassTypeParamDeclaration() throws JavaModelExceptio " void foo(bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo(bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -721,7 +750,7 @@ public void testStaticNestedClassTypeLocalVarDeclaration() throws JavaModelExcep " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -741,7 +770,7 @@ public void testStaticNestedClassTypeThrowsDeclaration() throws JavaModelExcepti " void foo() throws bar" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo() throws bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -761,7 +790,7 @@ public void testStaticNestedClassTypeExtends() throws JavaModelException { " class SpecificFooBar extends bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "SpecificFooBar extends bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -781,7 +810,7 @@ public void testStaticNestedClassTypeImplements() throws JavaModelException { " class SpecificFooBar implements bar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "class SpecificFooBar implements bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -803,7 +832,7 @@ public void testLocalClassTypeInstantiation() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "new bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -825,7 +854,7 @@ public void testLocalClassTypeLocalVarDeclaration() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -847,7 +876,7 @@ public void testLocalClassTypeExtends() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "class SpecificFooBar extends bar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -868,7 +897,7 @@ public void testBug488441_1() throws JavaModelException { this.workingCopies[0] = getWorkingCopy( "/Completion/src/test/Test.java", content); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".st"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -898,7 +927,7 @@ public void testBug488441_2() throws JavaModelException { "/Completion/src/test/Test.java", content); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".st"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -928,7 +957,7 @@ public void testBug488441_3() throws JavaModelException { "/Completion/src/test/Test.java", content); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".st"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -958,7 +987,7 @@ public void testBug488441_4() throws JavaModelException { "/Completion/src/test/Test.java", content); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".st"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -990,7 +1019,7 @@ public void testBug488441_5() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".as"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -1023,7 +1052,7 @@ public void testBug488441_6() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".aS"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -1056,7 +1085,7 @@ public void testBug488441_7() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".as"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -1089,7 +1118,7 @@ public void testBug488441_8() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = ".as"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubwordCompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubwordCompletionTests.java index b73ae952d6..d3773047b8 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubwordCompletionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubwordCompletionTests.java @@ -14,7 +14,9 @@ package org.eclipse.jdt.core.tests.model; import java.util.Hashtable; +import java.util.function.Predicate; +import org.eclipse.jdt.core.CompletionProposal; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -55,7 +57,12 @@ public void tearDownSuite() throws Exception { } super.tearDownSuite(); } - +private CompletionTestsRequestor2 createFilteredRequestor() { + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + Predicate<CompletionProposal> javaTypeRef = p -> p.getKind() == CompletionProposal.TYPE_REF && new String(p.getSignature()).startsWith("Ljava."); + requestor.setProposalFilter(javaTypeRef.negate()); + return requestor; +} public void testQualifiedNonStaticMethod() throws JavaModelException { this.workingCopies = new ICompilationUnit[1]; this.workingCopies[0] = getWorkingCopy( @@ -70,7 +77,7 @@ public void testQualifiedNonStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "this.addlistener"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -97,7 +104,7 @@ public void testUnqualifiedNonStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "addlistener"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -123,7 +130,7 @@ public void testQualifiedStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "Test.addlistener"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -148,7 +155,7 @@ public void testUnqualifiedStaticMethod() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "addlistener"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -174,7 +181,7 @@ public void testQualifiedNonStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "this.fitem"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -201,7 +208,7 @@ public void testUnqualifiedNonStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "fitem"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -227,7 +234,7 @@ public void testQualifiedStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "Test.sitem"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -252,7 +259,7 @@ public void testUnqualifiedStaticField() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "sitem"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -279,7 +286,7 @@ public void testLocalVariable() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "tempitem"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -304,7 +311,7 @@ public void testMethodParamVariable() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "item"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -316,47 +323,53 @@ public void testMethodParamVariable() throws JavaModelException { requestor.getResults()); } public void testClassTypeInstantiation() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Map {}\n" + "class LinkedHashMap implements Map {}\n" + "class SpecificLinkedHashMap extends LinkedHashMap {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " {\n" + " Map f = new linkedmap\n" + " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "new linkedmap"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "LinkedHashMap[TYPE_REF]{LinkedHashMap, test, Ltest.LinkedHashMap;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBWORD) + "}\n" + - "SpecificLinkedHashMap[TYPE_REF]{SpecificLinkedHashMap, test, Ltest.SpecificLinkedHashMap;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBWORD) + "}", + "LinkedHashMap[TYPE_REF]{LinkedHashMap, test, Ltest.LinkedHashMap;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBWORD) + "}\n" + + "SpecificLinkedHashMap[TYPE_REF]{SpecificLinkedHashMap, test, Ltest.SpecificLinkedHashMap;, null, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_UNQUALIFIED + R_NON_RESTRICTED + R_SUBWORD) + "}", requestor.getResults()); } public void testClassTypeFieldDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Map {}\n" + "class LinkedHashMap implements Map {}\n" + "class SpecificLinkedHashMap extends LinkedHashMap {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " public linkedmap\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public linkedmap"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -368,20 +381,23 @@ public void testClassTypeFieldDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeParamDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Map {}\n" + "class LinkedHashMap implements Map {}\n" + "class SpecificLinkedHashMap extends LinkedHashMap {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " void setFoo(linkedmap\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void setFoo(linkedmap"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -393,22 +409,25 @@ public void testClassTypeParamDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeLocalVarDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Map {}\n" + "class LinkedHashMap implements Map {}\n" + "class SpecificLinkedHashMap extends LinkedHashMap {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " void foo() {\n" + " final linkedmap" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final linkedmap"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -420,21 +439,24 @@ public void testClassTypeLocalVarDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeThrowsDeclaration() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar extends Exception {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz extends Exception {}\n" + + "class SpecificFooBaz implements Foobaz extends Exception {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test {\n" + " void foo() throws fbar {\n" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo() throws fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -446,20 +468,23 @@ public void testClassTypeThrowsDeclaration() throws JavaModelException { requestor.getResults()); } public void testClassTypeExtends() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface Foobar {}\n" + "class SpecificFooBar implements Foobar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test extends fbar {\n" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public class Test extends fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -471,21 +496,24 @@ public void testClassTypeExtends() throws JavaModelException { requestor.getResults()); } public void testClassTypeImplements() throws JavaModelException { - this.workingCopies = new ICompilationUnit[1]; - this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Test.java", - "package test;"+ + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/Foobar.java", + "package test;\n"+ "interface FooBar {}\n" + "interface FooBarExtension extends FooBar {}\n" + "class SpecificFooBar implements FooBar {}\n" + "class EvenMoreSpecificFooBar extends SpecificFooBar {}\n" + "interface Foobaz {}\n" + - "class SpecificFooBaz implements Foobaz {}\n" + + "class SpecificFooBaz implements Foobaz {}\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Test.java", + "package test;"+ "public class Test implements fbar {\n" + " }" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public class Test implements fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -509,7 +537,7 @@ public void testInnerClassTypeInstantiation() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "t.new fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -529,7 +557,7 @@ public void testInnerClassTypeFieldDeclaration() throws JavaModelException { " public fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -549,7 +577,7 @@ public void testInnerClassTypeParamDeclaration() throws JavaModelException { " void foo(fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo(fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -571,7 +599,7 @@ public void testInnerClassTypeLocalVarDeclaration() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -591,7 +619,7 @@ public void testInnerClassTypeThrowsDeclaration() throws JavaModelException { " void foo() throws fbar" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo() throws fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -611,7 +639,7 @@ public void testInnerClassTypeExtends() throws JavaModelException { " class SpecificFooBar extends fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "SpecificFooBar extends fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -631,7 +659,7 @@ public void testInnerClassTypeImplements() throws JavaModelException { " class SpecificFooBar implements fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "class SpecificFooBar implements fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -653,7 +681,7 @@ public void testStaticNestedClassTypeInstantiation() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "new fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -673,7 +701,7 @@ public void testStaticNestedClassTypeFieldDeclaration() throws JavaModelExceptio " public fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "public fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -693,7 +721,7 @@ public void testStaticNestedClassTypeParamDeclaration() throws JavaModelExceptio " void foo(fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo(fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -715,7 +743,7 @@ public void testStaticNestedClassTypeLocalVarDeclaration() throws JavaModelExcep " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -735,7 +763,7 @@ public void testStaticNestedClassTypeThrowsDeclaration() throws JavaModelExcepti " void foo() throws fbar" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "void foo() throws fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -755,7 +783,7 @@ public void testStaticNestedClassTypeExtends() throws JavaModelException { " class SpecificFooBar extends fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "SpecificFooBar extends fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -775,7 +803,7 @@ public void testStaticNestedClassTypeImplements() throws JavaModelException { " class SpecificFooBar implements fbar\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "class SpecificFooBar implements fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -797,7 +825,7 @@ public void testLocalClassTypeInstantiation() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "new fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -819,7 +847,7 @@ public void testLocalClassTypeLocalVarDeclaration() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "final fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -841,7 +869,7 @@ public void testLocalClassTypeExtends() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "class SpecificFooBar extends fbar"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); @@ -862,7 +890,7 @@ public void testDontPreventInsertionOfExactMatch() throws JavaModelException { " }\n" + "}\n"); - CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + CompletionTestsRequestor2 requestor = createFilteredRequestor(); String str = this.workingCopies[0].getSource(); String completeBehind = "map.put("; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java new file mode 100644 index 0000000000..475b2058fc --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java @@ -0,0 +1,1217 @@ +/******************************************************************************* +* 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/ +* +* This is an implementation of an early-draft specification developed under the Java +* Community Process (JCP) and is made available for testing and evaluation purposes +* only. The code is not compatible with any specification of the JCP. +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* IBM Corporation - initial API and implementation +*******************************************************************************/ +package org.eclipse.jdt.core.tests.rewrite.describing; + +import java.util.List; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.Block; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.Javadoc; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.QualifiedName; +import org.eclipse.jdt.core.dom.RecordDeclaration; +import org.eclipse.jdt.core.dom.ReturnStatement; +import org.eclipse.jdt.core.dom.SimpleType; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.TagElement; +import org.eclipse.jdt.core.dom.TextElement; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.TypeParameter; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ListRewrite; + +import junit.framework.Test; + +public class ASTRewritingRecordDeclarationTest extends ASTRewritingTest { + + public ASTRewritingRecordDeclarationTest(String name) { + super(name, 15); + } + + public ASTRewritingRecordDeclarationTest(String name, int apiLevel) { + super(name, apiLevel); + } + + public static Test suite() { + return createSuite(ASTRewritingRecordDeclarationTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + if (this.apiLevel == AST.JLS15 ) { + this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_15); + this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_15); + this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_15); + this.project1.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED); + } + } + + @SuppressWarnings("deprecation") + private boolean checkAPILevel() { + if (this.apiLevel != 15) { + System.err.println("Test "+getName()+" requires a JRE 15"); + return true; + } + return false; + } + + @SuppressWarnings("rawtypes") + public void testRecord_001() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + MethodDeclaration methodDecl= findMethodDeclaration(record, "C"); + assertTrue("Not a compact constructor", methodDecl.isCompactConstructor()); + Block block= methodDecl.getBody(); + List blockStatements= block.statements(); + assertTrue("Number of statements not 1", blockStatements.size() == 1); + { // add record component + List recordComponents = record.recordComponents(); + assertTrue("must be 0 parameters", recordComponents.size() == 0); + SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration(); + newParam.setType(ast.newPrimitiveType(PrimitiveType.INT)); + newParam.setName(ast.newSimpleName("param1")); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.RECORD_COMPONENTS_PROPERTY); + listRewrite.insertFirst(newParam, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int param1) {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void testRecord_002() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + MethodDeclaration methodDecl= findMethodDeclaration(record, "C"); + Block block= methodDecl.getBody(); + List blockStatements= block.statements(); + assertTrue("Number of statements not 1", blockStatements.size() == 1); + { // add new constructor with parameter + MethodDeclaration methodDecl1 = ast.newMethodDeclaration(); + methodDecl1.setConstructor(true); + methodDecl1.setName(ast.newSimpleName("C")); + methodDecl1.modifiers().addAll(ast.newModifiers( Modifier.PUBLIC)); + List parameters = methodDecl1.parameters(); + SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration(); + newParam.setType(ast.newPrimitiveType(PrimitiveType.INT)); + newParam.setName(ast.newSimpleName("param1")); + parameters.add(newParam); + Block body= ast.newBlock(); + methodDecl1.setBody(body); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + listRewrite.insertLast(methodDecl1, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n\n"); + buf.append(" public C(int param1) {\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_003() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int age) {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // rename first param & last throw statement + MethodDeclaration methodDecl1 = ast.newMethodDeclaration(); + methodDecl1.setName(ast.newSimpleName("age")); + methodDecl1.modifiers().addAll(ast.newModifiers( Modifier.PUBLIC)); + methodDecl1.setReturnType2(ast.newPrimitiveType(PrimitiveType.INT)); + Block body= ast.newBlock(); + ReturnStatement returnStatement = ast.newReturnStatement(); + returnStatement.setExpression(ast.newSimpleName("age")); + body.statements().add(returnStatement); + methodDecl1.setBody(body); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + listRewrite.insertLast(methodDecl1, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int age) {\n\n"); + buf.append(" public int age() {\n"); + buf.append(" return age;\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_004() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(){\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + SimpleType newInterface= ast.newSimpleType(ast.newSimpleName("A")); + listRewrite.insertLast(newInterface, null); + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() implements A{\n"); + buf.append("\n"); + buf.append("}\n"); + assertEqualString(preview, buf.toString()); + } + + public void testRecord_005() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() implements A{\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + SimpleType newInterface= ast.newSimpleType(ast.newSimpleName("B")); + listRewrite.insertLast(newInterface, null); + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() implements A, B{\n"); + buf.append("\n"); + buf.append("}\n"); + assertEqualString(preview, buf.toString()); + } + + @SuppressWarnings("rawtypes") + public void testRecord_006() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int param1){\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // remove record component + List recordComponents = record.recordComponents(); + assertTrue("must be 1 parameters", recordComponents.size() == 1); + rewrite.remove((ASTNode)recordComponents.get(0), null); + + } + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(){\n"); + buf.append("\n"); + buf.append("}\n"); + assertEqualString(preview, buf.toString()); + } + + @SuppressWarnings("rawtypes") + public void testRecord_007() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int param1){\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // rename record component + List recordComponents = record.recordComponents(); + assertTrue("must be 1 parameters", recordComponents.size() == 1); + SingleVariableDeclaration newParam= astRoot.getAST().newSingleVariableDeclaration(); + newParam.setType(astRoot.getAST().newPrimitiveType(PrimitiveType.INT)); + newParam.setName(astRoot.getAST().newSimpleName("param2")); + rewrite.replace((SingleVariableDeclaration)recordComponents.get(0), newParam, null); + + } + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int param2){\n"); + buf.append("\n"); + buf.append("}\n"); + assertEqualString(preview, buf.toString()); + } + + public void testRecord_008() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + { // change record name + rewrite.set(type, RecordDeclaration.NAME_PROPERTY, ast.newSimpleName("X"), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record X() {\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_009() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + { // add java doc + Javadoc javadoc= ast.newJavadoc(); + TextElement textElem= ast.newTextElement(); + textElem.setText("Hello"); + TagElement tagElement= ast.newTagElement(); + tagElement.fragments().add(textElem); + javadoc.tags().add(tagElement); + rewrite.set(type, RecordDeclaration.JAVADOC_PROPERTY, javadoc, null); + } + + { // change modifier to private + rewrite.remove((ASTNode) type.modifiers().get(0), null); + ListRewrite listRewrite= rewrite.getListRewrite(type, RecordDeclaration.MODIFIERS2_PROPERTY); + listRewrite.insertFirst(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("/**\n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("private record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_010() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("/** javadoc comment */\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + { // remove java doc + rewrite.remove(type.getJavadoc(), null); + } + + { // remove modifier + rewrite.remove((ASTNode) type.modifiers().get(0), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_011() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("/** javadoc comment */\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + { // replace java doc + Javadoc javadoc= ast.newJavadoc(); + TextElement textElem= ast.newTextElement(); + textElem.setText("Hello"); + TagElement tagElement= ast.newTagElement(); + tagElement.fragments().add(textElem); + javadoc.tags().add(tagElement); + rewrite.replace(type.getJavadoc(), javadoc, null); + } + + { // add modifier + ListRewrite listRewrite= rewrite.getListRewrite(type, RecordDeclaration.MODIFIERS2_PROPERTY); + listRewrite.insertLast(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("/**\n"); + buf.append(" * Hello\n"); + buf.append(" */\n"); + buf.append("public final record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_012() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class C {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + TypeDeclaration type= findTypeDeclaration(astRoot, "C"); + ListRewrite declarations= rewrite.getListRewrite(type, TypeDeclaration.BODY_DECLARATIONS_PROPERTY); + { // add record in class + RecordDeclaration record = ast.newRecordDeclaration(); + record.setName(ast.newSimpleName("X")); + declarations.insertFirst(record, null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class C {\n"); + buf.append("\n"); + buf.append(" record X() {\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_013() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + ListRewrite declarations= rewrite.getListRewrite(type, RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + { // add record in record + RecordDeclaration record = ast.newRecordDeclaration(); + record.setName(ast.newSimpleName("X")); + declarations.insertFirst(record, null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append(" record X() {\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + + assertEqualString(preview, buf.toString()); + + } + + @SuppressWarnings("rawtypes") + public void testRecord_015() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append(" record X() {\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + ListRewrite declarations= rewrite.getListRewrite(type, RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + { // remove record from record + List types = (List)type.getStructuralProperty(RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + declarations.remove((RecordDeclaration)types.get(0), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + + @SuppressWarnings("rawtypes") + public void testRecord_0015() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int param1) {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // add record component + List recordComponents = record.recordComponents(); + assertTrue("must be 1 parameter", recordComponents.size() == 1); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.RECORD_COMPONENTS_PROPERTY); + listRewrite.remove((SingleVariableDeclaration)recordComponents.get(0), null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_016() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + MethodDeclaration methodDecl= findMethodDeclaration(record, "C"); + { // replace compact constructor + MethodDeclaration methodDecl1 = ast.newMethodDeclaration(); + methodDecl1.setName(ast.newSimpleName("C")); + SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration(); + newParam.setType(ast.newPrimitiveType(PrimitiveType.INT)); + newParam.setName(ast.newSimpleName("param1")); + methodDecl1.parameters().add(newParam); + methodDecl1.setConstructor(Boolean.TRUE); + methodDecl1.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD)); + Block body= ast.newBlock(); + MethodInvocation methodInvocation = ast.newMethodInvocation(); + QualifiedName name = + ast.newQualifiedName( + ast.newSimpleName("System"),//$NON-NLS-1$ + ast.newSimpleName("out"));//$NON-NLS-1$ + methodInvocation.setExpression(name); + methodInvocation.setName(ast.newSimpleName("println")); //$NON-NLS-1$ + StringLiteral literal = ast.newStringLiteral(); + literal.setLiteralValue("Hello world");//$NON-NLS-1$ + methodInvocation.arguments().add(literal); + ExpressionStatement expressionStatement = ast.newExpressionStatement(methodInvocation); + body.statements().add(expressionStatement); + methodDecl1.setBody(body); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + listRewrite.replace(methodDecl, methodDecl1, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C(int param1) {\n"); + buf.append(" System.out.println(\"Hello world\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + @SuppressWarnings("rawtypes") + public void testRecord_0016() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() implements A{\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + + { + // Remove interface + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + List interfaces = record.superInterfaceTypes(); + listRewrite.remove((Type)interfaces.get(0), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(){\n"); + buf.append("\n"); + buf.append("}\n"); + assertEqualString(preview, buf.toString()); + } + + @SuppressWarnings("rawtypes") + public void testRecord_0017() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() implements A{\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + + { + // change interface + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.SUPER_INTERFACE_TYPES_PROPERTY); + List interfaces = record.superInterfaceTypes(); + SimpleType newInterface= astRoot.getAST().newSimpleType(astRoot.getAST().newSimpleName("B")); + listRewrite.replace((SimpleType)interfaces.get(0), newInterface, null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() implements B{\n"); + buf.append("\n"); + buf.append("}\n"); + assertEqualString(preview, buf.toString()); + } + + public void testRecord_0018() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // add var arg property for record component + SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration(); + newParam.setType(ast.newPrimitiveType(PrimitiveType.INT)); + newParam.setName(ast.newSimpleName("param1")); + newParam.setVarargs(Boolean.TRUE); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.RECORD_COMPONENTS_PROPERTY); + listRewrite.insertFirst(newParam, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int... param1) {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_0019() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int... param) {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // remove var arg property of record component + rewrite.set((SingleVariableDeclaration) record.recordComponents().get(0), SingleVariableDeclaration.VARARGS_PROPERTY, Boolean.FALSE, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int param) {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_0020() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C(int... param) {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // remove record component with var arg + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.RECORD_COMPONENTS_PROPERTY); + listRewrite.remove((SingleVariableDeclaration)record.recordComponents().get(0), null); + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_0021() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // add parameter type + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.TYPE_PARAMETERS_PROPERTY); + TypeParameter typeParameter= ast.newTypeParameter(); + typeParameter.setName(ast.newSimpleName("X")); + listRewrite.insertFirst(typeParameter, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C<X>() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_0022() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C<X>() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // remove parameter type + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.TYPE_PARAMETERS_PROPERTY); + listRewrite.remove((TypeParameter)record.typeParameters().get(0), null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C () {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_023() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C<X>() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast = astRoot.getAST(); + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // change parameter type + //rewrite.set((TypeParameter) record.typeParameters().get(0), TypeParameter.NAME_PROPERTY, astRoot.getAST().newSimpleName("Y"), null); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.TYPE_PARAMETERS_PROPERTY); + TypeParameter typeParameter= ast.newTypeParameter(); + typeParameter.setName(ast.newSimpleName("Y")); + listRewrite.replace((TypeParameter)record.typeParameters().get(0), typeParameter, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C<Y>() {\n"); + buf.append(" public C {\n"); + buf.append(" System.out.println(\"error\");\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + public void testRecord_024() throws Exception { + if (checkAPILevel()) { + return; + } + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + CompilationUnit astRoot= createAST(cu); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + + AST ast= astRoot.getAST(); + + assertTrue("Parse errors", (astRoot.getFlags() & ASTNode.MALFORMED) == 0); + AbstractTypeDeclaration type= findAbstractTypeDeclaration(astRoot, "C"); + assertTrue("Not a record", type instanceof RecordDeclaration); + RecordDeclaration record = (RecordDeclaration)type; + { // add compact constructor + MethodDeclaration methodDecl1 = ast.newMethodDeclaration(); + methodDecl1.setName(ast.newSimpleName("C")); + methodDecl1.setConstructor(Boolean.TRUE); + methodDecl1.setCompactConstructor(Boolean.TRUE); + Block body= ast.newBlock(); + methodDecl1.setBody(body); + methodDecl1.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD)); + ListRewrite listRewrite= rewrite.getListRewrite(record, RecordDeclaration.BODY_DECLARATIONS_PROPERTY); + listRewrite.insertFirst(methodDecl1, null); + + } + + String preview= evaluateRewrite(cu, rewrite); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public record C() {\n"); + buf.append("\n"); + buf.append(" public C{}\n"); + buf.append("\n"); + buf.append("}\n"); + + assertEqualString(preview, buf.toString()); + + } + + +} + diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java index 43125fe74a..86f5ce3b38 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.RecordDeclaration; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; @@ -146,9 +147,11 @@ public class ASTRewritingTest extends AbstractJavaModelTests { suite.addTest(ASTRewritingPackageDeclTest.suite()); suite.addTest(ASTRewritingLambdaExpressionTest.suite()); suite.addTest(ASTRewritingReferenceExpressionTest.suite()); + suite.addTest(ASTRewritingRecordDeclarationTest.suite()); suite.addTest(SourceModifierTest.suite()); suite.addTest(ImportRewriteTest.suite()); suite.addTest(ImportRewrite18Test.suite()); + suite.addTest(ImportRewrite14Test.suite()); return suite; } @@ -301,6 +304,16 @@ public class ASTRewritingTest extends AbstractJavaModelTests { return null; } + public static MethodDeclaration findMethodDeclaration(RecordDeclaration typeDecl, String methodName) { + MethodDeclaration[] methods= typeDecl.getMethods(); + for (int i= 0; i < methods.length; i++) { + if (methodName.equals(methods[i].getName().getIdentifier())) { + return methods[i]; + } + } + return null; + } + protected static SingleVariableDeclaration createNewParam(AST ast, String name) { SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration(); newParam.setType(ast.newPrimitiveType(PrimitiveType.FLOAT)); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite14Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite14Test.java index cf167b079a..242cd04f11 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite14Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite14Test.java @@ -29,6 +29,7 @@ import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.RecordDeclaration; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.jdt.core.tests.model.AbstractJavaModelTests; @@ -67,13 +68,13 @@ public class ImportRewrite14Test extends AbstractJavaModelTests { protected void setUp() throws Exception { super.setUp(); - IJavaProject proj= createJavaProject(PROJECT, new String[] {"src"}, new String[] {"JCL_LIB"}, "bin", "14"); + IJavaProject proj= createJavaProject(PROJECT, new String[] {"src"}, new String[] {"JCL_LIB"}, "bin", "15"); proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE); proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4"); - proj.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_14); + proj.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_15); proj.setOption(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR); - proj.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_14); - proj.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_14); + proj.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_15); + proj.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_15); proj.setOption(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE, String.valueOf(99)); proj.setOption(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS, String.valueOf(1)); @@ -88,8 +89,8 @@ public class ImportRewrite14Test extends AbstractJavaModelTests { /** * @deprecated uses deprecated AST level */ - protected static int getJLS14() { - return AST.JLS14; + protected static int getJLS15() { + return AST.JLS15; } @Override protected void tearDown() throws Exception { @@ -100,7 +101,7 @@ public class ImportRewrite14Test extends AbstractJavaModelTests { /* * typeBinding shows "int value" rather than "@MyAnnotation int value" */ - public void _test001() throws Exception { + public void test001() throws Exception { String contents = "package pack1;\n" + "import pack2.MyAnnotation;\n" + "public record X(@MyAnnotation int value){\n" + @@ -112,7 +113,7 @@ public class ImportRewrite14Test extends AbstractJavaModelTests { createFolder("/" + PROJECT + "/src/pack2"); createFile("/" + PROJECT + "/src/pack2/MyAnnotation.java", contents); - ASTParser parser = ASTParser.newParser(getJLS14()); + ASTParser parser = ASTParser.newParser(getJLS15()); parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack2/MyAnnotation.java")); parser.setResolveBindings(true); parser.setStatementsRecovery(true); @@ -138,14 +139,52 @@ public class ImportRewrite14Test extends AbstractJavaModelTests { assertTrue(actualType.isPrimitiveType()); apply(rewrite); String contentsA = "package pack1;\n" + - "\n" + "import pack2.MyAnnotation;\n" + - "\n" + "public record X(@MyAnnotation int value){\n"+ "}\n"; assertEqualStringIgnoreDelim(cu.getSource(), contentsA); } + /* + * Import should not be added in the default package + */ + public void testBug563375_2() throws Exception { + String contents = ""+ + "public class X {\n" + + " public static void main(String[] args) {\n" + + " var i_S = i_s();\n" + + " System.out.println(i_S.i + i_S.s);\n" + + " }\n" + + " \n" + + " static record I_S(int i, String s) {}\n" + + " \n" + + " private static I_S i_s() {\n" + + " return new I_S(1, \"abc\");\n" + + " }\n" + + "}"; + createFile("/" + PROJECT + "/src/X.java", contents); + + ICompilationUnit cu= getCompilationUnit("/" + PROJECT + "/src/X.java"); + ASTParser parser = ASTParser.newParser(getJLS15()); + parser.setSource(cu); + parser.setResolveBindings(true); + parser.setStatementsRecovery(true); + CompilationUnit astRoot = (CompilationUnit) parser.createAST(null); + + + TypeDeclaration clazz= (TypeDeclaration) astRoot.types().get(0); + ITypeBinding binding= clazz.resolveBinding(); + ITypeBinding recBinding= binding.getDeclaredTypes()[0]; + assertNotNull(recBinding); + ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true); + cu = getCompilationUnit("/" + PROJECT + "/src/X.java"); + rewrite = newImportsRewrite(cu, new String[0], 99, 99, true); + String actualType = rewrite.addImport(recBinding); + assertEquals("X.I_S", actualType); + apply(rewrite); + assertEquals(0, cu.getImports().length); + } + protected void assertEqualStringIgnoreDelim(String actual, String expected) throws IOException { StringAsserts.assertEqualStringIgnoreDelim(actual, expected); } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java index ede8cd2628..632e7e6faf 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 IBM Corporation and others. + * Copyright (c) 2014, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -847,4 +847,43 @@ public class ImportRewrite18Test extends AbstractJavaModelTests { Type actualType = runTest426094andGetType(0, true); assertEquals(this.bug426094TestInput[0][1], actualType.toString()); } + + /* + * Import should not be added in the default package + */ + public void testBug563375() throws Exception { + String contents = ""+ + "public class X {\n" + + " public static void main(String[] args) {\n" + + " var i_S = i_s();\n" + + " System.out.println(i_S.toString());\n" + + " }\n" + + " \n" + + " static class I_S {}\n" + + " \n" + + " private static I_S i_s() {\n" + + " return new I_S();\n" + + " }\n" + + "}"; + createFile("/" + PROJECT + "/src/X.java", contents); + + ICompilationUnit cu= getCompilationUnit("/" + PROJECT + "/src/X.java"); + ASTParser parser = ASTParser.newParser(getJLS8()); + parser.setSource(cu); + parser.setResolveBindings(true); + parser.setStatementsRecovery(true); + CompilationUnit astRoot = (CompilationUnit) parser.createAST(null); + + TypeDeclaration clazz= (TypeDeclaration) astRoot.types().get(0); + ITypeBinding binding= clazz.resolveBinding(); + ITypeBinding iBinding= binding.getDeclaredTypes()[0]; + assertNotNull(iBinding); + ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true); + cu = getCompilationUnit("/" + PROJECT + "/src/X.java"); + rewrite = newImportsRewrite(cu, new String[0], 99, 99, true); + String actualType = rewrite.addImport(iBinding); + assertEquals("X.I_S", actualType); + apply(rewrite); + assertEquals(0, cu.getImports().length); + } } diff --git a/org.eclipse.jdt.core/.settings/.api_filters b/org.eclipse.jdt.core/.settings/.api_filters index 3f3b891d4e..beedb4796d 100644 --- a/org.eclipse.jdt.core/.settings/.api_filters +++ b/org.eclipse.jdt.core/.settings/.api_filters @@ -1,13 +1,5 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <component id="org.eclipse.jdt.core" version="2"> - <resource path="META-INF/MANIFEST.MF"> - <filter id="924844039"> - <message_arguments> - <message_argument value="3.22.100"/> - <message_argument value="3.22.0"/> - </message_arguments> - </filter> - </resource> <resource path="compiler/org/eclipse/jdt/core/compiler/CategorizedProblem.java" type="org.eclipse.jdt.core.compiler.CategorizedProblem"> <filter comment="Java 14" id="576725006"> <message_arguments> @@ -30,13 +22,6 @@ <message_argument value="RecordCanonicalConstructorShouldBePublic"/> </message_arguments> </filter> - <filter id="1209008130"> - <message_arguments> - <message_argument value="3.23 BETA_JAVA15"/> - <message_argument value="3.22 BETA_JAVA15"/> - <message_argument value="FeatureNotSupported"/> - </message_arguments> - </filter> </resource> <resource path="dom/org/eclipse/jdt/core/dom/Annotation.java" type="org.eclipse.jdt.core.dom.Annotation"> <filter id="576725006"> @@ -192,6 +177,14 @@ </message_arguments> </filter> </resource> + <resource path="dom/org/eclipse/jdt/core/dom/RecordDeclaration.java" type="org.eclipse.jdt.core.dom.RecordDeclaration"> + <filter comment="method not needed" id="338792546"> + <message_arguments> + <message_argument value="org.eclipse.jdt.core.dom.RecordDeclaration"/> + <message_argument value="getTypes()"/> + </message_arguments> + </filter> + </resource> <resource path="dom/org/eclipse/jdt/core/dom/SimpleName.java" type="org.eclipse.jdt.core.dom.SimpleName"> <filter id="576778288"> <message_arguments> diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF index ba284241e1..a9d73c5e62 100644 --- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Main-Class: org.eclipse.jdt.internal.compiler.batch.Main Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true -Bundle-Version: 3.22.100.qualifier +Bundle-Version: 3.23.100.qualifier Bundle-Activator: org.eclipse.jdt.core.JavaCore Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java index ca7cf663cd..afffe434a9 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java @@ -8266,7 +8266,7 @@ public final class CompletionEngine this.nameEnvironment.findTypes( importName, findMembers, - this.options.camelCaseMatch, + getTypesMatchRule(), IJavaSearchConstants.TYPE, this, this.monitor); @@ -11295,7 +11295,7 @@ public final class CompletionEngine this.foundConstructorsCount = 0; this.nameEnvironment.findConstructorDeclarations( token, - this.options.camelCaseMatch, + getTypesMatchRule(), this, this.monitor); acceptConstructors(scope); @@ -11329,7 +11329,7 @@ public final class CompletionEngine this.nameEnvironment.findTypes( token, proposeAllMemberTypes, - this.options.camelCaseMatch, + getTypesMatchRule(), searchFor, this, this.monitor); @@ -11344,6 +11344,17 @@ public final class CompletionEngine } } + private int getTypesMatchRule() { + int matchRule = SearchPattern.R_PREFIX_MATCH; + if (this.options.camelCaseMatch) + matchRule |= SearchPattern.R_CAMELCASE_MATCH; + if (this.options.substringMatch) + matchRule |= SearchPattern.R_SUBSTRING_MATCH; + if (this.options.subwordMatch) + matchRule |= SearchPattern.R_SUBWORD_MATCH; + return matchRule; + } + private void findTypesAndSubpackages( char[] token, PackageBinding packageBinding, @@ -11487,7 +11498,7 @@ public final class CompletionEngine this.foundConstructorsCount = 0; this.nameEnvironment.findConstructorDeclarations( qualifiedName, - this.options.camelCaseMatch, + getTypesMatchRule(), this, this.monitor); acceptConstructors(scope); @@ -11511,7 +11522,7 @@ public final class CompletionEngine this.nameEnvironment.findTypes( qualifiedName, false, - this.options.camelCaseMatch, + getTypesMatchRule(), searchFor, this, this.monitor); 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 b97b5cda45..4b115573be 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 @@ -2277,7 +2277,7 @@ void setSourceStart(int sourceStart); /** @since 3.22 * @noreference preview feature error */ int RecordCanonicalConstructorHasThrowsClause = PreviewRelated + 1735; - /** @since 3.22 + /** @since 3.23 * @noreference preview feature error */ int RecordCanonicalConstructorVisibilityReduced = PreviewRelated + 1736; /** @since 3.22 @@ -2340,15 +2340,18 @@ void setSourceStart(int sourceStart); /** @since 3.22 * @noreference preview feature error */ int RecordCannotDefineRecordInLocalType= PreviewRelated + 1756; - /** @since 3.22 + /** @since 3.23 * @noreference preview feature error */ int RecordComponentsCannotHaveModifiers= PreviewRelated + 1757; - /** @since 3.22 + /** @since 3.23 * @noreference preview feature error */ int RecordIllegalParameterNameInCanonicalConstructor = PreviewRelated + 1758; - /** @since 3.22 + /** @since 3.23 * @noreference preview feature error */ int RecordIllegalExplicitFinalFieldAssignInCompactConstructor = PreviewRelated + 1759; + /** @since 3.23 + * @noreference preview feature error */ + int RecordMissingExplicitConstructorCallInNonCanonicalConstructor= PreviewRelated + 1760; /* records - end */ /* instanceof pattern: */ /** @since 3.22 @@ -2356,58 +2359,58 @@ void setSourceStart(int sourceStart); int PatternVariableNotInScope = PreviewRelated + 1780; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedMissingClassModifier = PreviewRelated + 1850; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedDisAllowedNonSealedModifierInClass = PreviewRelated + 1851; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedSuperClassDoesNotPermit = PreviewRelated + 1852; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedSuperInterfaceDoesNotPermit = PreviewRelated + 1853; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedMissingSealedModifier = PreviewRelated + 1854; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedMissingInterfaceModifier = PreviewRelated + 1855; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedDuplicateTypeInPermits = PreviewRelated + 1856; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedNotDirectSuperClass = PreviewRelated + 1857; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedPermittedTypeOutsideOfModule = PreviewRelated + 1858; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedPermittedTypeOutsideOfPackage = PreviewRelated + 1859; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedSealedTypeMissingPermits = PreviewRelated + 1860; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedInterfaceIsSealedAndNonSealed = PreviewRelated + 1861; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedDisAllowedNonSealedModifierInInterface = PreviewRelated + 1862; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedNotDirectSuperInterface = PreviewRelated + 1863; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedLocalDirectSuperTypeSealed = PreviewRelated + 1864; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedAnonymousClassCannotExtendSealedType = PreviewRelated + 1865; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedPermitsIsReservedTypeName = PreviewRelated + 1866; - /** @since 3.22 BETA_JAVA15 + /** @since 3.23 BETA_JAVA15 * @noreference preview feature error */ int SealedSealedIsReservedTypeName = PreviewRelated + 1867; /* Java15 errors - end */ 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 4f66bfa6f8..2cc929fba4 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 @@ -441,6 +441,10 @@ public abstract class AbstractMethodDeclaration return false; } + public boolean isCanonicalConstructor() { + + return false; + } public boolean isDefaultConstructor() { return false; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index 4c3c0c33dc..bfc5cb05fe 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -46,7 +46,6 @@ import org.eclipse.jdt.internal.compiler.parser.NLSTag; import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; import org.eclipse.jdt.internal.compiler.problem.AbortType; -import org.eclipse.jdt.internal.compiler.problem.DefaultProblem; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.HashSetOfInt; @@ -275,9 +274,6 @@ public void finalizeProblems() { if (start < startSuppress) continue nextSuppress; if (end > endSuppress) continue nextSuppress; if (!this.suppressWarningIrritants[iSuppress].isSet(irritant)) { - if (problem instanceof DefaultProblem) { - ((DefaultProblem) problem).reportError(); - } continue nextSuppress; } // discard suppressed warning 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 0ebc717715..9027be4a37 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 @@ -534,6 +534,11 @@ public boolean isConstructor() { } @Override +public boolean isCanonicalConstructor() { + return (this.bits & ASTNode.IsCanonicalConstructor) != 0; +} + +@Override public boolean isDefaultConstructor() { return (this.bits & ASTNode.IsDefaultConstructor) != 0; } @@ -650,7 +655,14 @@ public void resolveStatements() { this.scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall); } this.constructorCall = null; - } else { + } else if (sourceType.isRecord() && + !(this instanceof CompactConstructorDeclaration) && // compact constr should be marked as canonical? + (this.binding != null && (this.binding.tagBits & TagBits.IsCanonicalConstructor) == 0) && + this.constructorCall.accessMode != ExplicitConstructorCall.This) { + this.scope.problemReporter().recordMissingExplicitConstructorCallInNonCanonicalConstructor(this); + this.constructorCall = null; + } + else { this.constructorCall.resolve(this.scope); } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java index 783e2f9c1b..1c0cb5f2ac 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java @@ -31,6 +31,7 @@ public interface ExtraCompilerModifiers { // modifier constant final int AccJustFlag = 0xFFFF;// 16 lower bits final int AccDefaultMethod = ASTNode.Bit17; + final int AccCompactConstructor = ASTNode.Bit24; // bit18 - use by ClassFileConstants.AccAnnotationDefault final int AccRestrictedAccess = ASTNode.Bit19; final int AccFromClassFile = ASTNode.Bit20; 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 20b3cf7ec4..6f86e09694 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 @@ -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 @@ -803,6 +803,12 @@ public final boolean isConstructor() { return this.selector == TypeConstants.INIT; } +/* Answer true if the receiver is a compact constructor +*/ +public final boolean isCompactConstructor() { + return (this.modifiers & ExtraCompilerModifiers.AccCompactConstructor) != 0; +} + /* Answer true if the receiver has default visibility */ public final boolean isDefault() { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java index 8a3d74fe86..2eaa03ca90 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java @@ -661,9 +661,11 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi return this.genericTypeSignature; } - /** - * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getAnnotationTagBits() - */ + @Override + public AnnotationBinding[] getAnnotations() { + return this.type.getAnnotations(); + } + @Override public long getAnnotationTagBits() { return this.type.getAnnotationTagBits(); 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 087e934c91..99d6ddb00b 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 @@ -3114,6 +3114,7 @@ private void populateCompactConstructor(CompactConstructorDeclaration ccd) { //modifiers ccd.declarationSourceStart = this.intStack[this.intPtr--]; ccd.modifiers = this.intStack[this.intPtr--]; + ccd.modifiers |= ExtraCompilerModifiers.AccCompactConstructor; // consume annotations int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { 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 c3600fe068..1534011a12 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 @@ -11846,6 +11846,14 @@ public void recordIllegalExplicitFinalFieldAssignInCompactConstructor(FieldBindi fieldRef.sourceStart, fieldRef.sourceEnd); } +public void recordMissingExplicitConstructorCallInNonCanonicalConstructor(ASTNode location) { + this.handle( + IProblem.RecordMissingExplicitConstructorCallInNonCanonicalConstructor, + NoArgument, + NoArgument, + location.sourceStart, + location.sourceEnd); +} private void sealedMissingModifier(int problem, SourceTypeBinding type, TypeDeclaration typeDecl, TypeBinding superTypeBinding) { if (!this.options.enablePreviewFeatures) return; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index 8f3a4b0f94..ace7465881 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 @@ -1058,6 +1058,7 @@ 1757 = A record component {0} cannot have modifiers 1758 = Illegal parameter name {0} in canonical constructor, expected {1}, the corresponding component name 1759 = Illegal explicit assignment of a final field {0} in compact constructor +1760 = A non-canonical constructor must start with an explicit invocation to a constructor 1780 = The pattern variable {0} is not in scope in this location 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 index 2dc554db41..d0dc2c96f7 100644 --- 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 @@ -38,8 +38,8 @@ import java.util.concurrent.ConcurrentHashMap; * <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). + * directories inside the file are somehow related to the Java release number, encoded as single digit or letter (single + * digits for releases 7 to 9, capital letters for 10 and higher). * <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. @@ -77,6 +77,11 @@ import java.util.concurrent.ConcurrentHashMap; */ public class CtSym { + /** + * 'B' is code for Java 11, see {@link #getReleaseCode(String)}. + */ + private static final char JAVA_11 = 'B'; + public static final boolean DISABLE_CACHE = Boolean.getBoolean("org.eclipse.jdt.disable_CTSYM_cache"); //$NON-NLS-1$ static boolean VERBOSE = false; @@ -97,14 +102,14 @@ public class CtSym { 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, + * Paths of all root directories, per release (versions encoded). 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 + * All paths that exist in all release root directories, per release (versions encoded). The first key is release + * code. 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<>(); @@ -166,28 +171,23 @@ public class CtSym { } /** - * @param releaseInHex - * major JDK version segment as hex number (8, 9, A, etc) + * @param releaseCode + * major JDK version segment as version code (8, 9, A, etc) * @return set with all root paths related to given release in ct.sym file */ - public List<Path> releaseRoots(String releaseInHex) { - List<Path> list = this.releaseRootPaths.computeIfAbsent(releaseInHex, x -> { + public List<Path> releaseRoots(String releaseCode) { + List<Path> list = this.releaseRootPaths.computeIfAbsent(releaseCode, 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 + // Ignore META-INF etc. We are only interested in A-Z 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)) { + if (rel.contains(releaseCode)) { rootDirs.add(subdir); } else { continue; @@ -212,21 +212,21 @@ public class CtSym { * <p> * java/io/Reader.sig -> /8769/java/io/Reader.sig * - * @param releaseInHex release number in hex + * @param releaseCode release number encoded (7,8,9,A,B...) * @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) { + public Path getFullPath(String releaseCode, String qualifiedSignatureFileName, String moduleName) { String sep = this.fs.getSeparator(); if (DISABLE_CACHE) { - List<Path> releaseRoots = releaseRoots(releaseInHex); + List<Path> releaseRoots = releaseRoots(releaseCode); for (Path rroot : releaseRoots) { // Calculate file path Path p = null; if (isJRE12Plus()) { if (moduleName == null) { - moduleName = getModuleInJre12plus(releaseInHex, qualifiedSignatureFileName); + moduleName = getModuleInJre12plus(releaseCode, qualifiedSignatureFileName); } p = rroot.resolve(moduleName + sep + qualifiedSignatureFileName); } else { @@ -246,14 +246,14 @@ public class CtSym { } return null; } - Map<String, Path> releasePaths = getCachedReleasePaths(releaseInHex); + Map<String, Path> releasePaths = getCachedReleasePaths(releaseCode); 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$ + if(path == null && !this.isJRE12Plus() && "A".equals(releaseCode)){ //$NON-NLS-1$ path = releasePaths.get(qualifiedSignatureFileName); } } else { @@ -269,11 +269,11 @@ public class CtSym { return path; } - private String getModuleInJre12plus(String releaseInHex, String qualifiedSignatureFileName) { + private String getModuleInJre12plus(String releaseCode, String qualifiedSignatureFileName) { if (DISABLE_CACHE) { - return findModuleForFileInJre12plus(releaseInHex, qualifiedSignatureFileName); + return findModuleForFileInJre12plus(releaseCode, qualifiedSignatureFileName); } - Map<String, Path> releasePaths = getCachedReleasePaths(releaseInHex); + Map<String, Path> releasePaths = getCachedReleasePaths(releaseCode); Path path = releasePaths.get(qualifiedSignatureFileName); if (path != null && path.getNameCount() > 2) { // First segment is release, second: module @@ -282,8 +282,8 @@ public class CtSym { return null; } - private String findModuleForFileInJre12plus(String releaseInHex, String qualifiedSignatureFileName) { - for (Path rroot : releaseRoots(releaseInHex)) { + private String findModuleForFileInJre12plus(String releaseCode, String qualifiedSignatureFileName) { + for (Path rroot : releaseRoots(releaseCode)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(rroot)) { for (final Path subdir : stream) { Path p = subdir.resolve(qualifiedSignatureFileName); @@ -313,9 +313,9 @@ public class CtSym { * <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); + private Map<String, Path> getCachedReleasePaths(String releaseCode) { + Map<String, Path> result = this.allReleasesPaths.computeIfAbsent(releaseCode, x -> { + List<Path> roots = releaseRoots(releaseCode); Map<String, Path> allReleaseFiles = new HashMap<>(4999); for (Path start : roots) { try { @@ -361,17 +361,18 @@ public class CtSym { } private boolean isCurrentRelease12plus() throws IOException { - try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root)) { + // ignore everything that is not one character (Java release code is one character plus separator) + try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root, p -> p.toString().length() == 2)) { for (final Path subdir : stream) { String rel = JRTUtil.sanitizedFileName(subdir); - if (rel.contains("-")) { //$NON-NLS-1$ + if (rel.length() != 1) { continue; } try { - int version = Integer.parseInt(rel, 16); + char releaseCode = rel.charAt(0); // 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$ + if (releaseCode > JAVA_11 && Files.exists(this.fs.getPath(rel, "system-modules"))) { //$NON-NLS-1$ return true; } } catch (NumberFormatException e) { @@ -409,4 +410,24 @@ public class CtSym { sb.append("]"); //$NON-NLS-1$ return sb.toString(); } + + /** + * Tries to translate numeric Java version to the corresponding release "code". + * <ul> + * <li>7, 8 and 9 are just returned "as is" + * <li>versions up from 10 are returned as upper letters starting with "A", so 10 is "A", 11 is "B" and so on. + * </ul> + * + * @param release + * release version as number (8, 9, 10, ...) + * @return the "code" used by ct.sym for given Java version + */ + public static String getReleaseCode(String release) { + int numericVersion = Integer.parseInt(release); + if(numericVersion < 10) { + return String.valueOf(numericVersion); + } + return String.valueOf((char) ('A' + (numericVersion - 10))); + } + }
\ 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 789ec9e0ff..58e0d5b409 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 @@ -231,7 +231,6 @@ public class JRTUtil { class JrtFileSystemWithOlderRelease extends JrtFileSystem { final String release; - String releaseInHex; private List<Path> releaseRoots = Collections.emptyList(); protected Path modulePath; private CtSym ctSym; @@ -259,14 +258,14 @@ class JrtFileSystemWithOlderRelease extends JrtFileSystem { private void initialize(File jdk, String rel) throws IOException { 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(); + String releaseCode = CtSym.getReleaseCode(this.release); this.ctSym = JRTUtil.getCtSym(Paths.get(this.jdkHome)); 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$ + if (!Files.exists(this.fs.getPath(releaseCode)) + || Files.exists(this.fs.getPath(releaseCode, "system-modules"))) { //$NON-NLS-1$ this.fs = null; } - this.releaseRoots = this.ctSym.releaseRoots(this.releaseInHex); + this.releaseRoots = this.ctSym.releaseRoots(releaseCode); } @Override diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java index a64eeff843..013732a518 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java @@ -361,7 +361,7 @@ public final class AST { * up to and including Java SE 15(aka JDK 15). * </p> * - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 */ public static final int JLS15 = 15; @@ -2647,6 +2647,20 @@ public final class AST { } /** + * Creates an unparented record declaration node owned by this AST. + * The name of the class is an unspecified, but legal, name; + * no modifiers; no doc comment; no superclass or superinterfaces; + * and an empty record body. + * + * @return a new unparented type declaration node + * @exception UnsupportedOperationException if this operation is used in an AST with level less than JLS14 + * @since 3.23 + */ + public RecordDeclaration newRecordDeclaration() { + RecordDeclaration result = new RecordDeclaration(this); + return result; + } + /** * Creates and returns a new unparented requires directive * node for an unspecified, but legal, name; * 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 de6d32b6f6..818342cc78 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 @@ -4820,8 +4820,11 @@ class ASTConverter { } if (currentNode instanceof TypeDeclaration || currentNode instanceof EnumDeclaration - || currentNode instanceof AnnotationTypeDeclaration) { - org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode); + || currentNode instanceof AnnotationTypeDeclaration + || currentNode instanceof RecordDeclaration) { + org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDecl = + (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) + this.ast.getBindingResolver().getCorrespondingNode(currentNode); if ((initializer.getModifiers() & Modifier.STATIC) != 0) { return typeDecl.staticInitializerScope; } else { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java index 3b01fb8d30..7473ca9bfe 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.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 @@ -48,6 +48,35 @@ public interface IMethodBinding extends IBinding { public boolean isConstructor(); /** + * Returns whether this binding is for a compact constructor or not. + * + * <p> + * This method returns <code>true</code> for: + * </p> + * <ul> + * <li>compact constructors where the binding + * information was obtained from a Java source file containing a compact constructor + * declaration</li> + * </ul> + * + * <p> + * This method returns <code>false</code> for: + * </p> + * <ul> + * <li>methods</li> + * <li>constructors</li> + * <li>constructors where the binding information was obtained from a Java class file (it + * is not possible to determine from a class file whether a constructor is a + * compact constructor or not</li> + * </ul> + * + * @return <code>true</code> if this is the binding for a compact constructor + * in a source file and and <code>false</code> otherwise + * @noreference + */ + public boolean isCompactConstructor(); + + /** * Returns whether this binding is known to be a compiler-generated * default constructor. * <p> diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java index 16b33c0552..fbc2bac346 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.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 @@ -73,6 +73,14 @@ class MethodBinding implements IMethodBinding { } /** + * @see IMethodBinding#isCompactConstructor() + */ + @Override + public boolean isCompactConstructor() { + return this.binding.isCompactConstructor(); + } + + /** * @see IMethodBinding#isDefaultConstructor() * @since 3.0 */ diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java index d2b3afa510..b419043777 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java @@ -112,12 +112,12 @@ public final class Modifier extends ASTNode implements IExtendedModifier { public static final ModifierKeyword DEFAULT_KEYWORD = new ModifierKeyword("default", DEFAULT);//$NON-NLS-1$ /** - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static final ModifierKeyword SEALED_KEYWORD = new ModifierKeyword("sealed", SEALED);//$NON-NLS-1$ /** - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static final ModifierKeyword NON_SEALED_KEYWORD = new ModifierKeyword("non-sealed", NON_SEALED);//$NON-NLS-1$ @@ -332,14 +332,14 @@ public final class Modifier extends ASTNode implements IExtendedModifier { /** * "sealed" modifier constant (bit mask). * Applicable only to types. - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static final int SEALED = 0x0200; /** * "non-sealed" modifier constant (bit mask). * Applicable only to types. - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static final int NON_SEALED = 0x1000; @@ -524,7 +524,7 @@ public final class Modifier extends ASTNode implements IExtendedModifier { * @param flags the modifier flags * @return <code>true</code> if the <code>SEALED</code> bit is set * and <code>false</code> otherwise - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static boolean isSealed(int flags) { return (flags & SEALED) != 0; @@ -537,7 +537,7 @@ public final class Modifier extends ASTNode implements IExtendedModifier { * @param flags the modifier flags * @return <code>true</code> if the <code>NON_SEALED</code> bit is set * and <code>false</code> otherwise - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static boolean isNonSealed(int flags) { return (flags & NON_SEALED) != 0; @@ -766,7 +766,7 @@ public final class Modifier extends ASTNode implements IExtendedModifier { * Answer true if the receiver is the sealed modifier, false otherwise. * * @return true if the receiver is the sealed modifier, false otherwise - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public boolean isSealed() { return this.modifierKeyword == ModifierKeyword.SEALED_KEYWORD; @@ -776,7 +776,7 @@ public final class Modifier extends ASTNode implements IExtendedModifier { * Answer true if the receiver is the non-sealed modifier, false otherwise. * * @return true if the receiver is the non-sealed modifier, false otherwise - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public boolean isNonSealed() { return this.modifierKeyword == ModifierKeyword.NON_SEALED_KEYWORD; diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java index 8fb12387e6..f1c49b0d9a 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecordDeclaration.java @@ -271,12 +271,12 @@ public class RecordDeclaration extends AbstractTypeDeclaration { if (property == TYPE_PARAMETERS_PROPERTY) { return typeParameters(); } - if (property == SUPER_INTERFACE_TYPES_PROPERTY) { - return superInterfaceTypes(); - } if (property == RECORD_COMPONENTS_PROPERTY) { return recordComponents(); } + if (property == SUPER_INTERFACE_TYPES_PROPERTY) { + return superInterfaceTypes(); + } if (property == BODY_DECLARATIONS_PROPERTY) { return bodyDeclarations(); } @@ -320,10 +320,10 @@ public class RecordDeclaration extends AbstractTypeDeclaration { result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers())); result.typeParameters().addAll( ASTNode.copySubtrees(target, typeParameters())); - result.superInterfaceTypes().addAll( - ASTNode.copySubtrees(target, superInterfaceTypes())); result.recordComponents().addAll( ASTNode.copySubtrees(target, recordComponents())); + result.superInterfaceTypes().addAll( + ASTNode.copySubtrees(target, superInterfaceTypes())); result.bodyDeclarations().addAll( ASTNode.copySubtrees(target, bodyDeclarations())); return result; @@ -344,8 +344,8 @@ public class RecordDeclaration extends AbstractTypeDeclaration { acceptChildren(visitor, this.modifiers); acceptChild(visitor, getName()); acceptChildren(visitor, this.typeParameters); - acceptChildren(visitor, this.superInterfaceTypes); acceptChildren(visitor, this.recordComponents); + acceptChildren(visitor, this.superInterfaceTypes); acceptChildren(visitor, this.bodyDeclarations); } visitor.endVisit(this); @@ -452,36 +452,6 @@ public class RecordDeclaration extends AbstractTypeDeclaration { return methods; } - /** - * Returns the ordered list of member type declarations of this type - * declaration. - * <p> - * This convenience method returns this node's body declarations - * with non-types filtered out. Unlike <code>bodyDeclarations</code>, - * this method does not return a live result. - * </p> - * - * @return the (possibly empty) list of member type declarations - */ - public RecordDeclaration[] getTypes() { - List bd = bodyDeclarations(); - int typeCount = 0; - for (Iterator it = bd.listIterator(); it.hasNext(); ) { - if (it.next() instanceof RecordDeclaration) { - typeCount++; - } - } - RecordDeclaration[] memberTypes = new RecordDeclaration[typeCount]; - int next = 0; - for (Iterator it = bd.listIterator(); it.hasNext(); ) { - Object decl = it.next(); - if (decl instanceof RecordDeclaration) { - memberTypes[next++] = (RecordDeclaration) decl; - } - } - return memberTypes; - } - @Override ITypeBinding internalResolveBinding() { return this.ast.getBindingResolver().resolveType(this); diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java index 2f57c18acf..e2320e2817 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java @@ -67,7 +67,7 @@ public class TextBlock extends Expression { * @return a list of property descriptors (element type: * {@link StructuralPropertyDescriptor}) - * @since 3.22 + * @since 3.23 */ public static List propertyDescriptors(int apiLevel) { return PROPERTY_DESCRIPTORS; @@ -146,7 +146,7 @@ public class TextBlock extends Expression { * * @return the string literal token, including enclosing double * quotes and embedded escapes - * @since 3.22 + * @since 3.23 */ public String getEscapedValue() { return this.escapedValue; @@ -166,7 +166,7 @@ public class TextBlock extends Expression { * @param token the string literal token, including enclosing double * quotes and embedded escapes * @exception IllegalArgumentException if the argument is incorrect - * @since 3.22 + * @since 3.23 */ public void setEscapedValue(String token) { // update internalSetEscapedValue(String) if this is changed @@ -218,7 +218,7 @@ public class TextBlock extends Expression { * * @return the string value without enclosing triple quotes * @exception IllegalArgumentException if the literal value cannot be converted - * @since 3.22 + * @since 3.23 */ public String getLiteralValue() { char[] escaped = getEscapedValue().toCharArray(); diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java index 5dded0beee..260bca3d43 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java @@ -144,7 +144,7 @@ public class TypeDeclaration extends AbstractTypeDeclaration { /** * The "permitsTypes" structural property of this node type (element type: {@link Type}) (added in JLS15 API). - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public static final ChildListPropertyDescriptor PERMITS_TYPES_PROPERTY = new ChildListPropertyDescriptor(TypeDeclaration.class, "permitsTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$ @@ -755,7 +755,7 @@ public class TypeDeclaration extends AbstractTypeDeclaration { * @return the live list of types * (element type: {@link Type}) * @exception UnsupportedOperationException if this operation is not used with Java 15 and preview enabled - * @since 3.22 BETA_JAVA + * @since 3.23 BETA_JAVA15 */ public List permittedTypes() { // more efficient than just calling unsupportedIn2() to check diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java index 003abc59cf..c330b62155 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java @@ -53,6 +53,7 @@ import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMemberValuePairBinding; import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.IPackageBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.ImportDeclaration; @@ -773,7 +774,7 @@ public final class ImportRewrite { String erasureName= Signature.toString(erasureSig); if (erasureSig.charAt(0) == Signature.C_RESOLVED) { - erasureName= internalAddImport(erasureName, context); + erasureName= internalAddImport(erasureName, context, false); } Type baseType= ast.newSimpleType(ast.newName(erasureName)); String[] typeArguments= Signature.getTypeArguments(typeSig); @@ -883,7 +884,7 @@ public final class ImportRewrite { String qualifiedName= getRawQualifiedName(normalizedBinding); if (qualifiedName.length() > 0) { - String str= internalAddImport(qualifiedName, context); + String str= internalAddImport(qualifiedName, context, isTypeInUnnamedPackage(normalizedBinding)); ITypeBinding[] typeArguments= normalizedBinding.getTypeArguments(); if (typeArguments.length > 0) { @@ -1053,13 +1054,13 @@ public final class ImportRewrite { public String addImport(String qualifiedTypeName, ImportRewriteContext context) { int angleBracketOffset= qualifiedTypeName.indexOf('<'); if (angleBracketOffset != -1) { - return internalAddImport(qualifiedTypeName.substring(0, angleBracketOffset), context) + qualifiedTypeName.substring(angleBracketOffset); + return internalAddImport(qualifiedTypeName.substring(0, angleBracketOffset), context, false) + qualifiedTypeName.substring(angleBracketOffset); } int bracketOffset= qualifiedTypeName.indexOf('['); if (bracketOffset != -1) { - return internalAddImport(qualifiedTypeName.substring(0, bracketOffset), context) + qualifiedTypeName.substring(bracketOffset); + return internalAddImport(qualifiedTypeName.substring(0, bracketOffset), context, false) + qualifiedTypeName.substring(bracketOffset); } - return internalAddImport(qualifiedTypeName, context); + return internalAddImport(qualifiedTypeName, context, false); } /** @@ -1198,7 +1199,7 @@ public final class ImportRewrite { return simpleName; } - private String internalAddImport(String fullTypeName, ImportRewriteContext context) { + private String internalAddImport(String fullTypeName, ImportRewriteContext context, boolean isTypeInUnnamedPackage) { int idx= fullTypeName.lastIndexOf('.'); String typeContainerName, typeName; if (idx != -1) { @@ -1217,7 +1218,8 @@ public final class ImportRewrite { context= this.defaultContext; int res= context.findInContext(typeContainerName, typeName, ImportRewriteContext.KIND_TYPE); - if (res == ImportRewriteContext.RES_NAME_CONFLICT) { + if (res == ImportRewriteContext.RES_NAME_CONFLICT + || isTypeInUnnamedPackage) { return fullTypeName; } if (res == ImportRewriteContext.RES_NAME_UNKNOWN) { @@ -1518,7 +1520,7 @@ public final class ImportRewrite { boolean annotsPresent = annotationBinding != null && annotationBinding.length > 0; String qualifiedName= getRawQualifiedName(normalizedBinding); - String res = qualifiedName.length() > 0 ? internalAddImport(qualifiedName, context) : getRawName(normalizedBinding); + String res = qualifiedName.length() > 0 ? internalAddImport(qualifiedName, context, isTypeInUnnamedPackage(normalizedBinding)) : getRawName(normalizedBinding); if (annotsPresent) { int dotIndex = res != null ? res.lastIndexOf('.') : -1; @@ -1662,4 +1664,15 @@ public final class ImportRewrite { return null; } } + + private static boolean isTypeInUnnamedPackage(ITypeBinding binding) { + boolean isInUnnamedPackage= false; + if (binding != null) { + IPackageBinding pBinding= binding.getPackage(); + if (pBinding != null) { + isInUnnamedPackage= pBinding.isUnnamed(); + } + } + return isInUnnamedPackage; + } } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java index 3dab3c150d..f02b089307 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java @@ -1419,6 +1419,17 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { } /* + * Next token is a right parenthesis. Returns the offset after the parenthesis. For incomplete code, return the start offset. + */ + private int getPosAfterRightParenthesis(int pos) { + try { + return getPosAfterToken(pos, TerminalTokens.TokenNameRPAREN); + } catch (IllegalArgumentException e) { + return pos; + } + } + + /* * Next token is try keyword. Returns the offset after 'try' keyword. For incomplete code, return the start offset. */ private int getPosAfterTry(int pos) { @@ -2253,8 +2264,21 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { pos= rewriteOptionalTypeParameters(node, RecordDeclaration.TYPE_PARAMETERS_PROPERTY, pos, Util.EMPTY_STRING, false, true); + try { + pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, pos); + }catch(CoreException ex) { + //ignore + } + + pos= rewriteNodeList(node, RecordDeclaration.RECORD_COMPONENTS_PROPERTY, pos, Util.EMPTY_STRING, ", "); //$NON-NLS-1$ + try { + pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos); + }catch(CoreException ex) { + //ignore + } + // extended interfaces ChildListPropertyDescriptor superInterfaceProperty= RecordDeclaration.SUPER_INTERFACE_TYPES_PROPERTY; @@ -2268,9 +2292,11 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { // type members // startPos : find position after left brace of type, be aware that bracket might be missing + int startIndent= getIndent(node.getStartPosition()) + 1; - int startPos= getPosAfterLeftBrace(pos); - rewriteParagraphList(node, RecordDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2); + pos = getPosAfterRightParenthesis(pos); + pos= getPosAfterLeftBrace(pos); + rewriteParagraphList(node, RecordDeclaration.BODY_DECLARATIONS_PROPERTY, pos, startIndent, -1, 2); return false; } diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java index 7f0a169627..14b018e558 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java @@ -205,6 +205,17 @@ public class DefaultCodeFormatterConstants { public static final String FORMATTER_ALIGNMENT_FOR_ASSIGNMENT = JavaCore.PLUGIN_ID + ".formatter.alignment_for_assignment"; //$NON-NLS-1$ /** * <pre> + * FORMATTER / Option for alignment of assertion message separator (:) + * - option id: "org.eclipse.jdt.core.formatter.alignment_for_assertion_message" + * - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call + * - default: createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT) + * </pre> + * @see #createAlignmentValue(boolean, int, int) + * @since 3.23 + */ + public static final String FORMATTER_ALIGNMENT_FOR_ASSERTION_MESSAGE = JavaCore.PLUGIN_ID + ".formatter.alignment_for_assertion_message"; //$NON-NLS-1$ + /** + * <pre> * FORMATTER / Option for alignment of expressions with multiplicative operators (*, /, %) * - option id: "org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" * - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call @@ -5112,6 +5123,18 @@ public class DefaultCodeFormatterConstants { public static final String FORMATTER_WRAP_BEFORE_ADDITIVE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.wrap_before_additive_operator"; //$NON-NLS-1$ /** * <pre> + * FORMATTER / Option to wrap before the assertion message operator + * - option id: "org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" + * - possible values: { TRUE, FALSE } + * - default: FALSE + * </pre> + * @see #TRUE + * @see #FALSE + * @since 3.23 + */ + public static final String FORMATTER_WRAP_BEFORE_ASSERTION_MESSAGE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.wrap_before_assertion_message_operator"; //$NON-NLS-1$ + /** + * <pre> * FORMATTER / Option to wrap before the string concatenation operator * - option id: "org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" * - possible values: { TRUE, FALSE } diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java index 0cb87ac5f9..6eb0ed3bd6 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java @@ -125,6 +125,7 @@ public class DefaultCodeFormatterOptions { public int alignment_for_arguments_in_explicit_constructor_call; public int alignment_for_arguments_in_method_invocation; public int alignment_for_arguments_in_qualified_allocation_expression; + public int alignment_for_assertion_message; public int alignment_for_assignment; public int alignment_for_multiplicative_operator; public int alignment_for_additive_operator; @@ -500,6 +501,7 @@ public class DefaultCodeFormatterOptions { public int text_block_indentation; public boolean wrap_before_multiplicative_operator; public boolean wrap_before_additive_operator; + public boolean wrap_before_assertion_message_operator; public boolean wrap_before_string_concatenation; public boolean wrap_before_shift_operator; public boolean wrap_before_relational_operator; @@ -556,6 +558,7 @@ public class DefaultCodeFormatterOptions { options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_EXPLICIT_CONSTRUCTOR_CALL, getAlignment(this.alignment_for_arguments_in_explicit_constructor_call)); options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION, getAlignment(this.alignment_for_arguments_in_method_invocation)); options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_QUALIFIED_ALLOCATION_EXPRESSION, getAlignment(this.alignment_for_arguments_in_qualified_allocation_expression)); + options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ASSERTION_MESSAGE, getAlignment(this.alignment_for_assertion_message)); options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ASSIGNMENT, getAlignment(this.alignment_for_assignment)); options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLICATIVE_OPERATOR ,getAlignment(this.alignment_for_multiplicative_operator)); options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ADDITIVE_OPERATOR ,getAlignment(this.alignment_for_additive_operator)); @@ -942,6 +945,7 @@ public class DefaultCodeFormatterOptions { options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_MULTIPLICATIVE_OPERATOR, this.wrap_before_multiplicative_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_ADDITIVE_OPERATOR, this.wrap_before_additive_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); + options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_ASSERTION_MESSAGE_OPERATOR, this.wrap_before_assertion_message_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_STRING_CONCATENATION, this.wrap_before_string_concatenation ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_SHIFT_OPERATOR, this.wrap_before_shift_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_RELATIONAL_OPERATOR, this.wrap_before_relational_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); @@ -1006,6 +1010,8 @@ public class DefaultCodeFormatterOptions { this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT; } } + setInt(settings, DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ASSERTION_MESSAGE, + v -> this.alignment_for_assertion_message = v); final Object alignmentForAssignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ASSIGNMENT); if (alignmentForAssignmentOption != null) { try { @@ -2491,6 +2497,8 @@ public class DefaultCodeFormatterOptions { } setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_MULTIPLICATIVE_OPERATOR, DefaultCodeFormatterConstants.TRUE, v -> this.wrap_before_multiplicative_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_ASSERTION_MESSAGE_OPERATOR, DefaultCodeFormatterConstants.TRUE, + v -> this.wrap_before_assertion_message_operator = v); setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_ADDITIVE_OPERATOR, DefaultCodeFormatterConstants.TRUE, v -> this.wrap_before_additive_operator = v); setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_STRING_CONCATENATION, DefaultCodeFormatterConstants.TRUE, @@ -2882,6 +2890,7 @@ public class DefaultCodeFormatterOptions { this.alignment_for_arguments_in_explicit_constructor_call = Alignment.M_COMPACT_SPLIT; this.alignment_for_arguments_in_method_invocation = Alignment.M_COMPACT_SPLIT; this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT; + this.alignment_for_assertion_message = Alignment.M_COMPACT_SPLIT; this.alignment_for_assignment = Alignment.M_NO_ALIGNMENT; this.alignment_for_multiplicative_operator = Alignment.M_COMPACT_SPLIT; this.alignment_for_additive_operator = Alignment.M_COMPACT_SPLIT; @@ -3237,6 +3246,7 @@ public class DefaultCodeFormatterOptions { this.text_block_indentation = Alignment.M_INDENT_DEFAULT; this.wrap_before_multiplicative_operator = true; this.wrap_before_additive_operator = true; + this.wrap_before_assertion_message_operator = true; this.wrap_before_string_concatenation = true; this.wrap_before_shift_operator = true; this.wrap_before_relational_operator = true; @@ -3264,6 +3274,7 @@ public class DefaultCodeFormatterOptions { this.alignment_for_arguments_in_explicit_constructor_call = Alignment.M_COMPACT_SPLIT; this.alignment_for_arguments_in_method_invocation = Alignment.M_COMPACT_SPLIT; this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT; + this.alignment_for_assertion_message = Alignment.M_COMPACT_SPLIT; this.alignment_for_assignment = Alignment.M_NO_ALIGNMENT; this.alignment_for_multiplicative_operator = Alignment.M_COMPACT_SPLIT; this.alignment_for_additive_operator = Alignment.M_COMPACT_SPLIT; @@ -3619,6 +3630,7 @@ public class DefaultCodeFormatterOptions { this.text_block_indentation = Alignment.M_INDENT_DEFAULT; this.wrap_before_multiplicative_operator = true; this.wrap_before_additive_operator = true; + this.wrap_before_assertion_message_operator = true; this.wrap_before_string_concatenation = true; this.wrap_before_shift_operator = true; this.wrap_before_relational_operator = true; diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java index 83ef7dc53f..558fa885fe 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java @@ -56,6 +56,7 @@ import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.ArrayInitializer; +import org.eclipse.jdt.core.dom.AssertStatement; import org.eclipse.jdt.core.dom.Assignment; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.CatchClause; @@ -1088,6 +1089,26 @@ public class WrapPreparator extends ASTVisitor { return true; } + @Override + public boolean visit(AssertStatement node) { + Expression message = node.getMessage(); + if (message != null) { + int atColon = this.tm.firstIndexBefore(message, TokenNameCOLON); + int afterColon = this.tm.firstIndexIn(message, -1); + if (this.options.wrap_before_assertion_message_operator) { + this.wrapIndexes.add(atColon); + this.secondaryWrapIndexes.add(afterColon); + } else { + this.wrapIndexes.add(afterColon); + this.secondaryWrapIndexes.add(atColon); + } + this.wrapParentIndex = this.tm.firstIndexIn(node, -1); + this.wrapGroupEnd = this.tm.lastIndexIn(node, -1); + handleWrap(this.options.alignment_for_assertion_message); + } + return true; + } + /** * Makes sure all new lines within given node will have wrap policy so that * wrap executor will fix their indentation if necessary. diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java index 3d97ca1ede..c03eb13fd8 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java @@ -297,6 +297,7 @@ public class CorrectionEngine { try { Hashtable options = new Hashtable(oldOptions); options.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.DISABLED); + options.put(JavaCore.CODEASSIST_SUBWORD_MATCH, JavaCore.DISABLED); JavaCore.setOptions(options); this.compilationUnit.codeComplete( diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java index c94474f2fe..72c03e0dfb 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java @@ -203,7 +203,7 @@ public final class Flags { * Note that this flag's value is internal and is not defined in the * Virtual Machine specification. * </p> - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 * @noreference This field is not intended to be referenced by clients as it is a part of Java preview feature. */ public static final int AccSealed = ExtraCompilerModifiers.AccSealed; @@ -213,7 +213,7 @@ public final class Flags { * Note that this flag's value is internal and is not defined in the * Virtual Machine specification. * </p> - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 * @noreference This field is not intended to be referenced by clients as it is a part of Java preview feature. */ public static final int AccNonSealed = ExtraCompilerModifiers.AccNonSealed; 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 1574fa1b63..58a6dd0768 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 @@ -484,7 +484,7 @@ public final class JavaConventions { * @see JavaCore#VERSION_1_7 * @see JavaCore#VERSION_1_8 * @see JavaCore#VERSION_9 - * @deprecated + * @deprecated Use {@link #validateJavaTypeName(String id, String sourceLevel, String complianceLevel, String previewEnabled)} instead */ public static IStatus validateJavaTypeName(String name, String sourceLevel, String complianceLevel) { return internalValidateJavaTypeName(name, sourceLevel, complianceLevel, null); @@ -500,7 +500,7 @@ public final class JavaConventions { * {@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. + * <p>The preview flag should be one of {@link JavaCore#ENABLED}, {@link JavaCore#DISABLED} or null. * When null is passed, the preview is considered to be disabled. * </p> * diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java index f72fab403a..d3deeb925f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java @@ -3124,7 +3124,7 @@ public final class JavaCore extends Plugin { public static final String VERSION_14 = "14"; //$NON-NLS-1$ /** * Configurable option value: {@value}. - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 * @category OptionValue */ public static final String VERSION_15 = "15"; //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java index 1ca267b522..e18e985775 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java @@ -213,7 +213,7 @@ public interface IAttributeNamesConstants { char[] RECORD = "Record".toCharArray(); //$NON-NLS-1$ /** * "PermittedSubclasses" attribute (JVMS 15). - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 */ char[] PERMITTED_SUBCLASSES = "PermittedSubclasses".toCharArray(); //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java index 2fb65fc6a4..3c9fd5efa0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java @@ -144,7 +144,7 @@ public interface IClassFileReader { * Answer back the permitted subclasses attribute of this .class file, null if none. * * @return the permitted subclasses attribute of this .class file, null if none - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 */ default IPermittedSubclassesAttribute getPermittedSubclassesAttribute() { return null; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java index 5cd9e3d40f..91abceb56a 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttribute.java @@ -21,7 +21,7 @@ package org.eclipse.jdt.core.util; * Description of permitted subclasses attribute as described in the JVM * specifications. * - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 */ public interface IPermittedSubclassesAttribute extends IClassFileAttribute { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java index e0c39beab7..986060c87b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IPermittedSubclassesAttributeEntry.java @@ -21,7 +21,7 @@ package org.eclipse.jdt.core.util; * Description of permitted subclasses attribute as described in the JVM * specifications. * - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 */ public interface IPermittedSubclassesAttributeEntry { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java index fa12a481c4..be24056aac 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java @@ -63,9 +63,9 @@ public class CancelableNameEnvironment extends SearchableEnvironment implements return findType(typeName, packageName, moduleName); } @Override - public void findTypes(char[] prefix, boolean findMembers, boolean camelCaseMatch, int searchFor, ISearchRequestor storage, IProgressMonitor progressMonitor) { + public void findTypes(char[] prefix, boolean findMembers, int matchRule, int searchFor, ISearchRequestor storage, IProgressMonitor progressMonitor) { checkCanceled(); - super.findTypes(prefix, findMembers, camelCaseMatch, searchFor, storage, progressMonitor); + super.findTypes(prefix, findMembers, matchRule, searchFor, storage, progressMonitor); } @Override diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java index 1fe4af8f9a..706b2740d8 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java @@ -497,7 +497,7 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I * types are found relative to their enclosing type. */ public void findTypes(char[] prefix, final boolean findMembers, boolean camelCaseMatch, int searchFor, final ISearchRequestor storage) { - findTypes(prefix, findMembers, camelCaseMatch, searchFor, storage, null); + findTypes(prefix, findMembers, camelCaseMatch ? SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CAMELCASE_MATCH : SearchPattern.R_PREFIX_MATCH, searchFor, storage, null); } /** * Must be used only by CompletionEngine. @@ -517,8 +517,8 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I * This method can not be used to find member types... member * types are found relative to their enclosing type. */ - public void findTypes(char[] prefix, final boolean findMembers, boolean camelCaseMatch, int searchFor, final ISearchRequestor storage, IProgressMonitor monitor) { - + public void findTypes(char[] prefix, final boolean findMembers, int matchRule, int searchFor, final ISearchRequestor storage, IProgressMonitor monitor) { + boolean camelCaseMatch = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0; /* if (true){ findTypes(new String(prefix), storage, NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES); @@ -606,8 +606,6 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I } }; - int matchRule = SearchPattern.R_PREFIX_MATCH; - if (camelCaseMatch) matchRule |= SearchPattern.R_CAMELCASE_MATCH; if (monitor != null) { IndexManager indexManager = JavaModelManager.getIndexManager(); if (indexManager.awaitingJobsCount() == 0) { @@ -638,7 +636,7 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I qualification, SearchPattern.R_EXACT_MATCH, simpleName, - matchRule, // not case sensitive + matchRule, searchFor, getSearchScope(), typeRequestor, @@ -691,7 +689,7 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I * The constructors found are passed to one of the following methods: * ISearchRequestor.acceptConstructor(...) */ - public void findConstructorDeclarations(char[] prefix, boolean camelCaseMatch, final ISearchRequestor storage, IProgressMonitor monitor) { + public void findConstructorDeclarations(char[] prefix, int matchRule, final ISearchRequestor storage, IProgressMonitor monitor) { try { final String excludePath; if (this.unitToSkip != null && this.unitToSkip instanceof IJavaElement) { @@ -701,6 +699,7 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I } int lastDotIndex = CharOperation.lastIndexOf('.', prefix); + boolean camelCaseMatch = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0; char[] qualification, simpleName; if (lastDotIndex < 0) { qualification = null; @@ -788,8 +787,6 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I } }; - int matchRule = SearchPattern.R_PREFIX_MATCH; - if (camelCaseMatch) matchRule |= SearchPattern.R_CAMELCASE_MATCH; if (monitor != null) { IndexManager indexManager = JavaModelManager.getIndexManager(); // Wait for the end of indexing or a cancel diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java index 58e39ac6d9..989d03fa68 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.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 @@ -98,6 +98,7 @@ public void acceptModule(IModuleDescription module) { /** * @see IJavaElementRequestor */ +@SuppressWarnings("unlikely-arg-type") @Override public void acceptType(IType type) { try { 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 ecf140fc60..e1f16f002b 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 @@ -49,7 +49,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { static String MODULE_INFO = "module-info.sig"; //$NON-NLS-1$ final String release; - String releaseInHex; + String releaseCode; /** * Null for releases without ct.sym file or for releases matching current one */ @@ -106,25 +106,24 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { * @see CtSym */ protected void initialize() throws CoreException { - this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase(); + this.releaseCode = CtSym.getReleaseCode(this.release); 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$ + Path modPath = this.fs.getPath(this.releaseCode + (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$ } - if (!Files.exists(this.releasePath.resolve(this.releaseInHex))) { + if (!Files.exists(this.releasePath.resolve(this.releaseCode))) { Exception e = new IllegalArgumentException("release " + this.release + " is not found in the system"); //$NON-NLS-1$//$NON-NLS-2$ 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$ + if (Files.exists(this.fs.getPath(this.releaseCode, "system-modules"))) { //$NON-NLS-1$ this.fs = null; // Fallback to default version, all classes are on jrt fs, not here. } } - 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 @@ -181,7 +180,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { } HashMap<String, IModule> cache = ModulesCache.get(this.modPathString); if (cache == null) { - List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseInHex); + List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseCode); for (Path root : releaseRoots) { try { Files.walkFileTree(root, Collections.EMPTY_SET, 2, new FileVisitor<java.nio.file.Path>() { @@ -238,7 +237,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { if (!isPackage(qualifiedPackageName, moduleName)) { return null; // most common case } - List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseInHex); + List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseCode); try { IBinaryType reader = null; byte[] content = null; @@ -246,7 +245,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length); if (!releaseRoots.isEmpty()) { qualifiedBinaryFileName = qualifiedBinaryFileName.replace(".class", ".sig"); //$NON-NLS-1$ //$NON-NLS-2$ - Path fullPath = this.ctSym.getFullPath(this.releaseInHex, qualifiedBinaryFileName, moduleName); + Path fullPath = this.ctSym.getFullPath(this.releaseCode, qualifiedBinaryFileName, moduleName); // If file is known, read it from ct.sym if (fullPath != null) { content = this.ctSym.getFileBytes(fullPath); 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 737ad74602..4447a90877 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 @@ -153,7 +153,7 @@ public boolean isKnownPackage(String qualifiedPackageName) { 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 + String packageName = entry.getKey(); // 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)) { @@ -756,7 +756,7 @@ void write(DataOutputStream out) throws IOException { String value = entry.getValue(); if (key != null) { length--; - out.writeUTF(value); + out.writeUTF(key); Integer index = (Integer) internedTypeLocators.get(value); out.writeInt(index.intValue()); } diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml index 437afd0c6d..951b4d30b2 100644 --- a/org.eclipse.jdt.core/pom.xml +++ b/org.eclipse.jdt.core/pom.xml @@ -18,7 +18,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.core</artifactId> - <version>3.22.100-SNAPSHOT</version> + <version>3.23.100-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java index d721a579e3..f41baff5b7 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java @@ -502,7 +502,7 @@ public interface IJavaSearchConstants { * When this flag is set, only {@link TypeReferenceMatch} matches will be * returned. *</p> - * @since 3.22 BETA_JAVA15 + * @since 3.23 BETA_JAVA15 * @noreference permit type reference * @category limitTo */ diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java index f2d7a63c37..fa58477485 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java @@ -257,7 +257,9 @@ public abstract class SearchPattern { | R_PATTERN_MATCH | R_REGEXP_MATCH | R_CAMELCASE_MATCH - | R_CAMELCASE_SAME_PART_COUNT_MATCH; + | R_CAMELCASE_SAME_PART_COUNT_MATCH + | R_SUBSTRING_MATCH + | R_SUBWORD_MATCH; private int matchRule; @@ -2534,6 +2536,18 @@ public boolean matchesName(char[] pattern, char[] name) { boolean sameLength = pattern.length == name.length; boolean canBePrefix = name.length >= pattern.length; boolean matchFirstChar = !isCaseSensitive || emptyPattern || (name.length > 0 && pattern[0] == name[0]); + + if ((matchMode & R_SUBSTRING_MATCH) != 0) { + if (CharOperation.substringMatch(pattern, name)) + return true; + matchMode &= ~R_SUBSTRING_MATCH; + } + if ((matchMode & SearchPattern.R_SUBWORD_MATCH) != 0) { + if (CharOperation.subWordMatch(pattern, name)) + return true; + matchMode &= ~SearchPattern.R_SUBWORD_MATCH; + } + switch (matchMode) { case R_EXACT_MATCH : if (sameLength && matchFirstChar) { diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java index 7a333cb356..93cb3e7850 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java @@ -52,7 +52,9 @@ static final int MATCH_RULE_INDEX_MASK = SearchPattern.R_REGEXP_MATCH | SearchPattern.R_CASE_SENSITIVE | SearchPattern.R_CAMELCASE_MATCH | - SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH; + SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH | + SearchPattern.R_SUBSTRING_MATCH | + SearchPattern.R_SUBWORD_MATCH; public static boolean isMatch(char[] pattern, char[] word, int matchRule) { if (pattern == null) return true; @@ -61,6 +63,17 @@ public static boolean isMatch(char[] pattern, char[] word, int matchRule) { if (patternLength == 0) return matchRule != SearchPattern.R_EXACT_MATCH; if (wordLength == 0) return (matchRule & SearchPattern.R_PATTERN_MATCH) != 0 && patternLength == 1 && pattern[0] == '*'; + if ((matchRule & SearchPattern.R_SUBSTRING_MATCH) != 0) { + if (CharOperation.substringMatch(pattern, word)) + return true; + matchRule &= ~SearchPattern.R_SUBSTRING_MATCH; + } + if ((matchRule & SearchPattern.R_SUBWORD_MATCH) != 0) { + if (CharOperation.subWordMatch(pattern, word)) + return true; + matchRule &= ~SearchPattern.R_SUBWORD_MATCH; + } + // need to mask some bits of pattern rule (bug 79790) switch(matchRule & MATCH_RULE_INDEX_MASK) { case SearchPattern.R_EXACT_MATCH : diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java index ea1f5e69ea..d351cf2dae 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java @@ -492,6 +492,12 @@ public class BasicSearchEngine { boolean isCaseSensitive = (matchRuleType & SearchPattern.R_CASE_SENSITIVE) != 0; if (patternTypeName != null) { boolean isCamelCase = (matchRuleType & (SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH)) != 0; + + if ((matchRuleType & SearchPattern.R_SUBSTRING_MATCH) != 0 && CharOperation.substringMatch(patternTypeName, typeName)) + return true; + if ((matchRuleType & SearchPattern.R_SUBWORD_MATCH) != 0 && CharOperation.subWordMatch(patternTypeName, typeName)) + return true; + int matchMode = matchRuleType & JavaSearchPattern.MATCH_MODE_MASK; if (!isCaseSensitive && !isCamelCase) { patternTypeName = CharOperation.toLowerCase(patternTypeName); |