diff options
author | Manoj Palat | 2019-02-05 09:16:01 +0000 |
---|---|---|
committer | Manoj Palat | 2019-02-05 09:16:01 +0000 |
commit | bea7ce71afb7673b638922f4f0689b6bcdc614cf (patch) | |
tree | 2956e2e36d420b34494449fdfb8f905fd4744c32 | |
parent | 3d00de0bddc2b0d1c6a82db101dc7fdf733db143 (diff) | |
parent | 705bf0beff6f458ef068964094f5fecf359aec3c (diff) | |
download | eclipse.jdt.core-bea7ce71afb7673b638922f4f0689b6bcdc614cf.tar.gz eclipse.jdt.core-bea7ce71afb7673b638922f4f0689b6bcdc614cf.tar.xz eclipse.jdt.core-bea7ce71afb7673b638922f4f0689b6bcdc614cf.zip |
Merge branch 'master' into BETA_JAVA_12
83 files changed, 2692 insertions, 549 deletions
diff --git a/org.eclipse.jdt.apt.pluggable.tests/resources/targets/filer02b/Parent02.java b/org.eclipse.jdt.apt.pluggable.tests/resources/targets/filer02b/Parent02.java index 829e805213..a4699710ad 100644 --- a/org.eclipse.jdt.apt.pluggable.tests/resources/targets/filer02b/Parent02.java +++ b/org.eclipse.jdt.apt.pluggable.tests/resources/targets/filer02b/Parent02.java @@ -1,12 +1,9 @@ /******************************************************************************* * Copyright (c) 2007 BEA Systems, Inc. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 + * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * wharley@bea.com - initial API and implementation diff --git a/org.eclipse.jdt.compiler.apt.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.compiler.apt.tests/META-INF/MANIFEST.MF index 1d5b03bd5f..cd2f132a06 100644 --- a/org.eclipse.jdt.compiler.apt.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.compiler.apt.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.apt.tests;singleton:=true -Bundle-Version: 1.1.600.qualifier +Bundle-Version: 1.1.700.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar Binary files differindex 1865ddef1a..363e26f2b8 100644 --- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar +++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar diff --git a/org.eclipse.jdt.compiler.apt.tests/pom.xml b/org.eclipse.jdt.compiler.apt.tests/pom.xml index e622916c78..1bd9a1ade3 100644 --- a/org.eclipse.jdt.compiler.apt.tests/pom.xml +++ b/org.eclipse.jdt.compiler.apt.tests/pom.xml @@ -20,7 +20,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.compiler.apt.tests</artifactId> - <version>1.1.600-SNAPSHOT</version> + <version>1.1.700-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java index 50925490a4..0b400a7fd5 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java @@ -415,7 +415,7 @@ public class Java9ElementProcessor extends BaseProcessor { assertNotNull("java.base module null", base); List<? extends Directive> directives = base.getDirectives(); List<Directive> filterDirective = filterDirective(directives, DirectiveKind.EXPORTS); - assertEquals("incorrect no of exports", this.isJre11 ? 108 : (this.isJre10 ? 102 : 108) , filterDirective.size()); + assertEquals("incorrect no of exports", this.isJre11 ? 107 : (this.isJre10 ? 102 : 108) , filterDirective.size()); ExportsDirective pack = null; for (Directive directive : filterDirective) { ModuleElement.ExportsDirective exports = (ExportsDirective) directive; @@ -476,7 +476,7 @@ public class Java9ElementProcessor extends BaseProcessor { assertNotNull("java.base module null", base); List<? extends Directive> directives = base.getDirectives(); List<Directive> filterDirective = filterDirective(directives, DirectiveKind.USES); - assertEquals("incorrect no of uses", 34 , filterDirective.size()); + assertEquals("incorrect no of uses", this.isJre11? 33 : 34, filterDirective.size()); } /* * Test java.base module can be loaded and verify its 'provides' attributes diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java index b51cb094af..030258c7ef 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2018 IBM Corporation and others. + * Copyright (c) 2006, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -934,8 +934,10 @@ public class EclipseFileManager implements StandardJavaFileManager { for (Iterator<? extends File> iterator = iterable2.iterator(); iterator.hasNext(); ) { list.add(iterator.next()); } - for (Iterator<? extends File> iterator = iterable.iterator(); iterator.hasNext(); ) { - list.add(iterator.next()); + if (iterable != null) { + for (Iterator<? extends File> iterator = iterable.iterator(); iterator.hasNext(); ) { + list.add(iterator.next()); + } } return list; } 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 63fd006b66..eb56b0df36 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.400.qualifier +Bundle-Version: 1.2.500.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/org.eclipse.jdt.compiler.tool.tests/build.properties b/org.eclipse.jdt.compiler.tool.tests/build.properties index db7b35025c..c7599cfabc 100644 --- a/org.eclipse.jdt.compiler.tool.tests/build.properties +++ b/org.eclipse.jdt.compiler.tool.tests/build.properties @@ -17,7 +17,7 @@ bin.includes = META-INF/,\ plugin.properties,\ test.xml,\ lib/java10api.jar,\ - . + resources/ src.includes = about.html source.. = src/ output.. = bin/ diff --git a/org.eclipse.jdt.compiler.tool.tests/pom.xml b/org.eclipse.jdt.compiler.tool.tests/pom.xml index c239078490..d76b504180 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.400-SNAPSHOT</version> + <version>1.2.500-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/CompilerToolJava9Tests.java b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java index 94a4a53fe8..2cf201b571 100644 --- a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java +++ b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java @@ -16,7 +16,6 @@ package org.eclipse.jdt.compiler.tool.tests; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; @@ -24,6 +23,7 @@ import java.io.StringWriter; import java.io.Writer; import java.net.URL; import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -54,9 +54,12 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import junit.framework.TestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class CompilerToolJava9Tests extends TestCase { private static final boolean DEBUG = false; private static final String RESOURCES_DIR = "resources"; @@ -82,10 +85,8 @@ public class CompilerToolJava9Tests extends TestCase { return; this.compilers = new JavaCompiler[2]; this.compilerNames = new String[2]; - ServiceLoader<JavaCompiler> javaCompilerLoader = ServiceLoader.load(JavaCompiler.class); - int compilerCounter = 0; + ServiceLoader<JavaCompiler> javaCompilerLoader = ServiceLoader.load(JavaCompiler.class, EclipseCompiler.class.getClassLoader()); for (JavaCompiler compiler : javaCompilerLoader) { - compilerCounter++; if (compiler instanceof EclipseCompiler) { this.compilers[1] = compiler; this.compilerNames[1] = "Eclipse Compiler"; @@ -93,37 +94,45 @@ public class CompilerToolJava9Tests extends TestCase { } this.compilerNames[0] = "System compiler"; this.compilers[0] = ToolProvider.getSystemJavaCompiler(); - assertEquals("Only one compiler available: " + Arrays.toString(compilers), 2, compilerCounter); assertNotNull("System compiler unavailable", this.compilers[0]); assertNotNull("Eclipse compiler unavailable", this.compilers[1]); initializeLocations(); } - protected void initializeLocations() { - _tmpFolder = System.getProperty("java.io.tmpdir"); - if (_tmpFolder.endsWith(File.separator)) { - _tmpFolder += "eclipse-temp"; - } else { - _tmpFolder += (File.separator + "eclipse-temp"); + @Override + protected void tearDown() throws Exception { + if (isJREBelow9) { + return; } + deleteTree(new File(_tmpFolder)); + super.tearDown(); + } + protected void initializeLocations() throws IOException { + Path tempDirectory = Files.createTempDirectory("eclipse-temp"); + _tmpFolder = tempDirectory.toString(); _tmpBinFolderName = _tmpFolder + File.separator + "bin"; _tmpBinDir = new File(_tmpBinFolderName); deleteTree(_tmpBinDir); // remove existing contents - _tmpBinDir.mkdirs(); - assert _tmpBinDir.exists() : "couldn't mkdirs " + _tmpBinFolderName; + Files.createDirectories(_tmpBinDir.toPath()); + assertTrue("couldn't mkdirs " + _tmpBinFolderName, _tmpBinDir.exists()); _tmpGenFolderName = _tmpFolder + File.separator + "gen-src"; _tmpGenDir = new File(_tmpGenFolderName); deleteTree(_tmpGenDir); // remove existing contents - _tmpGenDir.mkdirs(); - assert _tmpGenDir.exists() : "couldn't mkdirs " + _tmpGenFolderName; + Files.createDirectories(_tmpGenDir.toPath()); + assertTrue("couldn't mkdirs " + _tmpGenFolderName, _tmpGenDir.exists()); _tmpSrcFolderName = _tmpFolder + File.separator + "src"; _tmpSrcDir = new File(_tmpSrcFolderName); deleteTree(_tmpSrcDir); // remove existing contents - _tmpSrcDir.mkdirs(); - assert _tmpSrcDir.exists() : "couldn't mkdirs " + _tmpSrcFolderName; + Files.createDirectories(_tmpSrcDir.toPath()); + assertTrue("couldn't mkdirs " + _tmpSrcFolderName, _tmpSrcDir.exists()); modules_directory = getPluginDirectoryPath() + File.separator + "resources" + File.separator + "module_locations"; + + Path moduleInfo = Paths.get(modules_directory, "source", "SimpleModules", "module.one", "module-info.java"); + assertTrue("File should exist: " + moduleInfo, Files.isReadable(moduleInfo)); + moduleInfo = Paths.get(modules_directory, "source", "SimpleModules", "module.two", "module-info.java"); + assertTrue("File should exist: " + moduleInfo, Files.isReadable(moduleInfo)); } public void testGetLocationForModule1() { if (this.isJREBelow9) return; @@ -177,7 +186,9 @@ public class CompilerToolJava9Tests extends TestCase { manager.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, Arrays.asList(path)); try { JavaFileManager.Location location = manager.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, "module.two"); - assertNotNull(cName + ":module path location should not be null", location); + Path moduleInfo = path.resolve("module.two" + File.separator + "module-info.java"); + assertTrue("File should exist: " + moduleInfo, Files.isReadable(moduleInfo)); + assertNotNull(cName + ": module path location should not be null for path " + path, location); } catch (UnsupportedOperationException ex) { fail(cName + ":Should support getLocationForModule()"); } @@ -196,35 +207,23 @@ public class CompilerToolJava9Tests extends TestCase { manager.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, Arrays.asList(path)); try { JavaFileManager.Location location = manager.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, "module.one"); - assertNotNull(cName + ":module path location should not be null", location); + Path moduleInfo = path.resolve("module.one" + File.separator + "module-info.java"); + assertTrue("File should exist: " + moduleInfo, Files.isReadable(moduleInfo)); + assertNotNull(cName + ": module path location should not be null for path " + path, location); } catch (UnsupportedOperationException ex) { fail(cName + ":Should support getLocationForModule()"); } } } - public void testOptionRelease1() { + public void testOptionRelease1() throws IOException { if (this.isJREBelow9) return; JavaCompiler compiler = this.compilers[1]; - String tmpFolder = System.getProperty("java.io.tmpdir"); + String tmpFolder = _tmpFolder; File inputFile = new File(tmpFolder, "X.java"); - BufferedWriter writer = null; - try { - writer = new BufferedWriter(new FileWriter(inputFile)); + try (Writer writer = new BufferedWriter(new FileWriter(inputFile))) { writer.write( "package p;\n" + "public class X {}"); - writer.flush(); - writer.close(); - } catch (IOException e) { - // ignore - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - // ignore - } - } } StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset()); @@ -307,29 +306,15 @@ public class CompilerToolJava9Tests extends TestCase { // check that the .class file exist for X assertTrue("delete failed", inputFile.delete()); } - public void testOptionRelease2() { + public void testOptionRelease2() throws IOException { if (this.isJREBelow9) return; JavaCompiler compiler = this.compilers[1]; - String tmpFolder = System.getProperty("java.io.tmpdir"); + String tmpFolder = _tmpFolder; File inputFile = new File(tmpFolder, "X.java"); - BufferedWriter writer = null; - try { - writer = new BufferedWriter(new FileWriter(inputFile)); + try (Writer writer = new BufferedWriter(new FileWriter(inputFile))){ writer.write( "package p;\n" + "public class X {}"); - writer.flush(); - writer.close(); - } catch (IOException e) { - // ignore - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - // ignore - } - } } StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset()); @@ -412,29 +397,15 @@ public class CompilerToolJava9Tests extends TestCase { // check that the .class file exist for X assertTrue("delete failed", inputFile.delete()); } - public void testOptionRelease3() { + public void testOptionRelease3() throws IOException { if (this.isJREBelow9) return; JavaCompiler compiler = this.compilers[1]; - String tmpFolder = System.getProperty("java.io.tmpdir"); + String tmpFolder = _tmpFolder; File inputFile = new File(tmpFolder, "X.java"); - BufferedWriter writer = null; - try { - writer = new BufferedWriter(new FileWriter(inputFile)); + try (Writer writer = new BufferedWriter(new FileWriter(inputFile))){ writer.write( "package p;\n" + "public class X {}"); - writer.flush(); - writer.close(); - } catch (IOException e) { - // ignore - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - // ignore - } - } } StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset()); @@ -598,7 +569,7 @@ public class CompilerToolJava9Tests extends TestCase { /*-- Code for testing bug 533830 --*/ - public void testBug533830_1() { + public void testBug533830_1() throws IOException { if (this.isJREBelow9) return; File src = createClassSource( @@ -641,7 +612,7 @@ public class CompilerToolJava9Tests extends TestCase { } public void compile() { - String tmpFolder = System.getProperty("java.io.tmpdir"); + String tmpFolder = _tmpFolder; StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset()); Iterable<? extends JavaFileObject> units = manager.getJavaFileObjectsFromFiles(files); @@ -735,25 +706,12 @@ public class CompilerToolJava9Tests extends TestCase { } } - private File createClassSource(String source) { - String tmpFolder = System.getProperty("java.io.tmpdir"); + private File createClassSource(String source) throws IOException { + String tmpFolder = _tmpFolder; File inputFile = new File(tmpFolder, "X.java"); - Writer writer = null; - try { - writer = new FileWriter(inputFile); + try (Writer writer = new FileWriter(inputFile)){ writer.write(source); - writer.close(); return inputFile; - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - // ignore - } - } } } @@ -764,8 +722,9 @@ public class CompilerToolJava9Tests extends TestCase { * This is not optimized to handle very large or deep directory trees efficiently. * @param f is either a normal file (which will be deleted) or a directory * (which will be emptied and then deleted). + * @throws IOException */ - public static void deleteTree(File f) + public static void deleteTree(File f) throws IOException { if (null == f) { return; @@ -778,7 +737,7 @@ public class CompilerToolJava9Tests extends TestCase { } } // At this point f is either a normal file or an empty directory - f.delete(); + Files.deleteIfExists(f.toPath()); } /** * Copy a file from one location to another, unless the destination file already exists and has @@ -812,24 +771,10 @@ public class CompilerToolJava9Tests extends TestCase { } public static void writeFile(File dest, byte[] srcBytes) throws IOException { - File destFolder = dest.getParentFile(); - if (!destFolder.exists()) { - if (!destFolder.mkdirs()) { - throw new IOException("Unable to create directory " + destFolder); - } - } + Files.createDirectories(destFolder.toPath()); // write bytes to dest - FileOutputStream out = null; - try { - out = new FileOutputStream(dest); - out.write(srcBytes); - out.flush(); - } finally { - if (out != null) { - out.close(); - } - } + Files.write(dest.toPath(), srcBytes); } /** @@ -896,17 +841,12 @@ public class CompilerToolJava9Tests extends TestCase { } } } - protected static String getPluginDirectoryPath() { - try { - if (Platform.isRunning()) { - URL platformURL = Platform.getBundle("org.eclipse.jdt.compiler.tool.tests").getEntry("/"); - return new File(FileLocator.toFileURL(platformURL).getFile()).getAbsolutePath(); - } - return new File(System.getProperty("user.dir")).getAbsolutePath(); - } catch (IOException e) { - e.printStackTrace(); + protected static String getPluginDirectoryPath() throws IOException { + if (Platform.isRunning()) { + URL platformURL = Platform.getBundle("org.eclipse.jdt.compiler.tool.tests").getEntry("/"); + return new File(FileLocator.toFileURL(platformURL).getFile()).getAbsolutePath(); } - return null; + return new File(System.getProperty("user.dir")).getAbsolutePath(); } /** * @return true if this file's end-of-line delimiters should be replaced with @@ -916,23 +856,7 @@ public class CompilerToolJava9Tests extends TestCase { return file.getName().endsWith(".java"); } public static byte[] read(java.io.File file) throws java.io.IOException { - int fileLength; - byte[] fileBytes = new byte[fileLength = (int) file.length()]; - java.io.FileInputStream stream = null; - try { - stream = new java.io.FileInputStream(file); - int bytesRead = 0; - int lastReadSize = 0; - while ((lastReadSize != -1) && (bytesRead != fileLength)) { - lastReadSize = stream.read(fileBytes, bytesRead, fileLength - bytesRead); - bytesRead += lastReadSize; - } - } finally { - if (stream != null) { - stream.close(); - } - } - return fileBytes; + return Files.readAllBytes(file.toPath()); } public static String convertToIndependentLineDelimiter(String source) { diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java index 8bd79d34b0..05b2908229 100644 --- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java +++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2018 IBM Corporation and others. + * Copyright (c) 2006, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -959,8 +959,10 @@ public class EclipseFileManager implements StandardJavaFileManager { for (Iterator<? extends File> iterator = iterable2.iterator(); iterator.hasNext(); ) { list.add(iterator.next()); } - for (Iterator<? extends File> iterator = iterable.iterator(); iterator.hasNext(); ) { - list.add(iterator.next()); + if (iterable != null) { + for (Iterator<? extends File> iterator = iterable.iterator(); iterator.hasNext(); ) { + list.add(iterator.next()); + } } return list; } diff --git a/org.eclipse.jdt.core.tests.builder/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jdt.core.tests.builder/.settings/org.eclipse.jdt.ui.prefs index fe50d63691..ab1a682988 100644 --- a/org.eclipse.jdt.core.tests.builder/.settings/org.eclipse.jdt.ui.prefs +++ b/org.eclipse.jdt.core.tests.builder/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,3 @@ -#Thu Nov 04 13:38:23 EDT 2010 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true sp_cleanup.add_default_serial_version_id=true @@ -14,10 +13,12 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false sp_cleanup.convert_to_enhanced_for_loop=false sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=false sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false sp_cleanup.make_local_variable_final=false sp_cleanup.make_parameters_final=false sp_cleanup.make_private_fields_final=true @@ -33,12 +34,15 @@ sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class= sp_cleanup.qualify_static_member_accesses_with_declaring_class=false sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=false +sp_cleanup.remove_redundant_modifiers=false +sp_cleanup.remove_redundant_semicolons=true +sp_cleanup.remove_redundant_type_arguments=true +sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -47,8 +51,10 @@ sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false sp_cleanup.update_ibm_copyright_to_current_year=true +sp_cleanup.use_anonymous_class_creation=false sp_cleanup.use_blocks=false sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true diff --git a/org.eclipse.jdt.core.tests.builder/pom.xml b/org.eclipse.jdt.core.tests.builder/pom.xml index 3f429fc2d8..a29d9bf91f 100644 --- a/org.eclipse.jdt.core.tests.builder/pom.xml +++ b/org.eclipse.jdt.core.tests.builder/pom.xml @@ -5,7 +5,7 @@ are made available under the terms of the Eclipse Distribution License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/org/documents/edl-v10.php - + Contributors: Igor Fedorenko - initial implementation --> @@ -26,4 +26,116 @@ <testClass>org.eclipse.jdt.core.tests.builder.BuilderTests</testClass> <testSuite>${project.artifactId}</testSuite> </properties> + + <build> + <plugins> + <plugin> + <groupId>org.eclipse.tycho</groupId> + <artifactId>tycho-surefire-plugin</artifactId> + <version>${tycho.version}</version> + <configuration> + <includes> + <include>org/eclipse/jdt/core/tests/builder/BuilderTests.class</include> + </includes> + <argLine>${tycho.surefire.argLine}</argLine> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>test-on-javase-9</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-toolchains-plugin</artifactId> + <version>1.1</version> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>toolchain</goal> + </goals> + </execution> + </executions> + <configuration> + <toolchains> + <jdk> + <id>JavaSE-9</id> + </jdk> + </toolchains> + </configuration> + </plugin> + </plugins> + </build> + <properties> + <tycho.surefire.argLine>--add-modules ALL-SYSTEM</tycho.surefire.argLine> + </properties> + </profile> + <profile> + <id>test-on-javase-10</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-toolchains-plugin</artifactId> + <version>1.1</version> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>toolchain</goal> + </goals> + </execution> + </executions> + <configuration> + <toolchains> + <jdk> + <id>JavaSE-10</id> + </jdk> + </toolchains> + </configuration> + </plugin> + </plugins> + </build> + <properties> + <!-- Overridden in https://ci.eclipse.org/jdt/job/eclipse.jdt.core-run.javac-10/configure --> + <tycho.surefire.argLine>--add-modules ALL-SYSTEM -Dcompliance=1.4,1.7,1.8,10</tycho.surefire.argLine> + </properties> + </profile> + <profile> + <id>test-on-javase-11</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-toolchains-plugin</artifactId> + <version>1.1</version> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>toolchain</goal> + </goals> + </execution> + </executions> + <configuration> + <toolchains> + <jdk> + <id>JavaSE-11</id> + </jdk> + </toolchains> + </configuration> + </plugin> + </plugins> + </build> + <properties> + <!-- Overridden in https://ci.eclipse.org/jdt/job/eclipse.jdt.core-run.javac-11/configure --> + <tycho.surefire.argLine>--add-modules ALL-SYSTEM -Dcompliance=1.4,1.7,1.8,11</tycho.surefire.argLine> + </properties> + </profile> + </profiles> + </project> diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/AbstractLeakTest.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/AbstractLeakTest.java new file mode 100644 index 0000000000..f851fd1696 --- /dev/null +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/AbstractLeakTest.java @@ -0,0 +1,210 @@ +/******************************************************************************* + * Copyright (c) 2019 Andrey Loskutov and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Andrey Loskutov - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.builder; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.tests.util.Util; + +/** + * Base class for testing builder related opened file leak tests, see bug 543506 + */ +public abstract class AbstractLeakTest extends BuilderTests { + + static boolean WINDOWS; + static boolean LINUX; + static boolean MAC; + static { + String os = System.getProperty("os.name").toLowerCase(); + WINDOWS = os.contains("windows"); + LINUX = os.contains("linux"); + MAC = os.contains("mac"); + } + + public AbstractLeakTest(String name) { + super(name); + } + + protected void testLeaksOnIncrementalBuild() throws Exception { + if(MAC) { + return; + } + internalTestUsedLibraryLeaks(IncrementalProjectBuilder.INCREMENTAL_BUILD); + } + + protected void testLeaksOnCleanBuild() throws Exception { + if(MAC) { + return; + } + internalTestUsedLibraryLeaks(IncrementalProjectBuilder.CLEAN_BUILD); + } + + protected void testLeaksOnFullBuild() throws Exception { + if(MAC) { + return; + } + internalTestUsedLibraryLeaks(IncrementalProjectBuilder.FULL_BUILD); + } + + private void internalTestUsedLibraryLeaks(int kind) throws Exception { + String projectName = getName(); + IPath projectPath = env.addProject(projectName, getCompatibilityLevel()); + env.setOutputFolder(projectPath, ""); + env.addExternalJars(projectPath, Util.getJavaClassLibs()); + IPath internalJar = addInternalJar(projectPath); + + createJavaFile(projectPath); + + switch (kind) { + case IncrementalProjectBuilder.CLEAN_BUILD: + cleanBuild(projectName); + assertNotLeaked(internalJar); + break; + case IncrementalProjectBuilder.FULL_BUILD: + fullBuild(projectPath); + assertNotLeaked(internalJar); + break; + case IncrementalProjectBuilder.INCREMENTAL_BUILD: + incrementalBuild(projectPath); + changeJavaFile(projectPath); + incrementalBuild(projectPath); + assertNotLeaked(internalJar); + break; + default: + fail("Unexpected build kind: " + kind); + } + } + + abstract String getCompatibilityLevel(); + + private IPath addInternalJar(IPath projectPath) throws IOException, JavaModelException { + IPath internalJar = addEmptyInternalJar(projectPath, "test.jar"); + return internalJar; + } + + private void createJavaFile(IPath projectPath) { + IPath path = env.addClass(projectPath, "a", "Other", + "package a;\n" + + "public class Other {\n" + + "}" + ); + IFile file = env.getWorkspace().getRoot().getFile(path); + assertTrue("File should exists: " + path, file.exists()); + } + + private void changeJavaFile(IPath projectPath) throws Exception { + IPath path = env.addClass(projectPath, "a", "Other", + "package a;\n" + + "public class Other {\n" + + " // an extra comment \n" + + "}" + ); + IFile file = env.getWorkspace().getRoot().getFile(path); + assertTrue("FIle should exists: " + path, file.exists()); + } + + private void assertNotLeaked(IPath path) throws Exception { + expectingNoProblems(); + IFile file = env.getWorkspace().getRoot().getFile(path); + assertTrue("FIle should exists: " + path, file.exists()); + if(WINDOWS) { + tryRemoveFile(file); + } else if (LINUX) { + checkOpenDescriptors(file); + } + } + + private void tryRemoveFile(IFile file) { + // Note: this is a lame attempt to check for leaked file descriptor + // This works on Windows only, because windows does not allow to delete + // files opened for reading. + // On Linux we need something like lsof -p <my_process_id> | grep file name + try { + file.delete(true, null); + } catch (CoreException e) { + try { + // second attempt to avoid delays on teardown + Files.deleteIfExists(file.getLocation().toFile().toPath()); + } catch (Exception e2) { + file.getLocation().toFile().delete(); + // ignore + } + throw new IllegalStateException("File leaked during build: " + file, e); + } + assertFalse("File should be deleted: " + file, file.exists()); + } + + private void checkOpenDescriptors(IFile file) throws Exception { + List<String> openDescriptors = getOpenDescriptors(); + assertFalse("Failed to read opened file descriptors", openDescriptors.isEmpty()); + if(openDescriptors.contains(file.getLocation().toOSString())) { + throw new IllegalStateException("File leaked during build: " + file); + } + } + + private static List<String> getOpenDescriptors() throws Exception { + int pid = getPid(); + if (pid > 0) { + // -F n : to print only name column (note: all lines start with "n") + // -a : to "and" all following options + // -b :to avoid blocking calls + // -p <pid>: to select process with opened files + List<String> lines = readLsofLines("lsof -F n -a -p " + pid + " / -b ", true); + return lines; + } + return Collections.emptyList(); + } + + private static int getPid() throws Exception { + try (BufferedReader rdr = new BufferedReader(new FileReader("/proc/self/stat"));) { + return Integer.parseInt(new StringTokenizer(rdr.readLine()).nextToken()); + } + } + + private static List<String> readLsofLines(String cmd, boolean skipFirst) throws Exception { + List<String> lines = new ArrayList<>(); + Process process = Runtime.getRuntime().exec(cmd); + try (BufferedReader rdr = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + if (skipFirst) { + rdr.readLine(); + } + String line; + while((line = rdr.readLine())!= null) { + // remove "n" prefix from lsof output + if(line.startsWith("n")) { + line = line.substring(1); + } + if(line.trim().length() > 1) { + lines.add(line); + } + } + } + lines.sort(null); + return lines; + } + +}
\ No newline at end of file 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 e2451de87e..0c45e7ed5a 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 @@ -13,23 +13,31 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.builder; +import static org.eclipse.jdt.core.tests.util.AbstractCompilerTest.*; + +import java.io.FileInputStream; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import java.util.Vector; -import junit.framework.*; - +import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; -import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.tests.junit.extension.TestCase; -import org.eclipse.jdt.core.tests.util.AbstractCompilerTest; import org.eclipse.jdt.core.tests.util.TestVerifier; import org.eclipse.jdt.core.tests.util.Util; import org.eclipse.jdt.internal.compiler.Compiler; -import org.eclipse.jdt.core.compiler.CharOperation; + +import junit.framework.Test; +import junit.framework.TestSuite; /** * Base class for Java image builder tests @@ -50,7 +58,7 @@ public class BuilderTests extends TestCase { env.cleanBuild(); this.debugRequestor.deactivate(); } - + protected void cleanBuild(String name) { this.debugRequestor.clearResult(); this.debugRequestor.activate(); @@ -536,18 +544,25 @@ public class BuilderTests extends TestCase { TestAttributeBuilderTests.class, Bug530366Test.class, Bug531382Test.class, - ParallelBuildTests.class + ParallelBuildTests.class, + LeakTestsBefore9.class, }; - - if ((AbstractCompilerTest.getPossibleComplianceLevels() & AbstractCompilerTest.F_1_5) != 0) { - int length = classes.length; - System.arraycopy(classes, 0, classes = new Class[length+4], 0, length); - classes[length++] = Java50Tests.class; - classes[length++] = PackageInfoTest.class; - classes[length++] = ParticipantBuildTests.class; - classes[length++] = AnnotationDependencyTests.class; + List<Class<?>> list = new ArrayList<>(Arrays.asList(classes)); + if (matchesCompliance(F_1_5)) { + list.add(Java50Tests.class); + list.add(PackageInfoTest.class); + list.add(ParticipantBuildTests.class); + list.add(AnnotationDependencyTests.class); } - return classes; + if (matchesCompliance(F_9)) { + list.add(LeakTestsAfter9.class); + } + return list.toArray(new Class[0]); + } + + static boolean matchesCompliance(int level) { + int complianceLevels = getPossibleComplianceLevels(); + return complianceLevels >= level; } public static Test buildTestSuite(Class evaluationTestClass, long ordering) { @@ -602,4 +617,18 @@ public class BuilderTests extends TestCase { return suite; } + + static IPath addEmptyInternalJar(IPath projectPath, String jarName) throws IOException, JavaModelException { + IProject project = env.getProject(projectPath); + String jarFile = project.getLocation().append(jarName).toOSString(); + Util.createEmptyJar(jarFile, JavaCore.VERSION_1_4); + IPath jarPath = null; + try (FileInputStream fis = new FileInputStream(jarFile)) { + int length = fis.available(); + byte[] jarContent = new byte[length]; + fis.read(jarContent); + jarPath = env.addInternalJar(projectPath, jarName, jarContent); + } + return jarPath; + } } diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java index 642f785b51..3f2e5dd2f2 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java @@ -13,25 +13,35 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.builder; -import junit.framework.*; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.preferences.IEclipsePreferences; -import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.tests.util.AbstractCompilerTest; import org.eclipse.jdt.core.tests.util.Util; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.core.*; +import org.eclipse.jdt.internal.core.JavaModel; +import org.eclipse.jdt.internal.core.JavaModelManager; +import org.eclipse.jdt.internal.core.JavaProject; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.*; +import junit.framework.Test; @SuppressWarnings({"unchecked", "rawtypes"}) public class BuildpathTests extends BuilderTests { @@ -115,27 +125,8 @@ public void testClasspathFileChange() throws JavaModelException { public void testClosedProject() throws JavaModelException, IOException { IPath project1Path = env.addProject("CP1"); //$NON-NLS-1$ - IProject project1 = ResourcesPlugin.getWorkspace().getRoot().getProject("CP1"); env.addExternalJars(project1Path, Util.getJavaClassLibs()); - - String jarFile = project1.getLocation().toOSString() + File.separator + "temp.jar"; - - org.eclipse.jdt.core.tests.util.Util.createEmptyJar( - jarFile, - JavaCore.VERSION_1_4); - - IPath jarPath = null; - FileInputStream fis = null; - try { - fis = new FileInputStream(jarFile); - int length = fis.available(); - byte[] jarContent = new byte[length]; - fis.read(jarContent); - jarPath = env.addInternalJar(project1Path, "temp.jar", jarContent); //$NON-NLS-1$ - } - finally { - if (fis != null) fis.close(); - } + IPath jarPath = addEmptyInternalJar(project1Path, "temp.jar"); IPath project2Path = env.addProject("CP2"); //$NON-NLS-1$ env.addExternalJars(project2Path, Util.getJavaClassLibs()); diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/LeakTestsAfter9.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/LeakTestsAfter9.java new file mode 100644 index 0000000000..826becf9bd --- /dev/null +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/LeakTestsAfter9.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2019 Andrey Loskutov and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Andrey Loskutov - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.builder; + +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +import junit.framework.Test; + +public class LeakTestsAfter9 extends AbstractLeakTest { + + public LeakTestsAfter9(String name) { + super(name); + } + + public static Test suite() { + return buildTestSuite(LeakTestsAfter9.class); + } + + String getCompatibilityLevel() { + return CompilerOptions.VERSION_9; + } + + @Override + public void testLeaksOnCleanBuild() throws Exception { + super.testLeaksOnCleanBuild(); + } + + @Override + public void testLeaksOnFullBuild() throws Exception { + super.testLeaksOnFullBuild(); + } + + @Override + public void testLeaksOnIncrementalBuild() throws Exception { + super.testLeaksOnIncrementalBuild(); + } +} diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/LeakTestsBefore9.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/LeakTestsBefore9.java new file mode 100644 index 0000000000..b275096b5b --- /dev/null +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/LeakTestsBefore9.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2019 Andrey Loskutov and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Andrey Loskutov - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.builder; + +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +import junit.framework.Test; + +public class LeakTestsBefore9 extends AbstractLeakTest { + + public LeakTestsBefore9(String name) { + super(name); + } + + public static Test suite() { + return buildTestSuite(LeakTestsBefore9.class); + } + + String getCompatibilityLevel() { + return CompilerOptions.VERSION_1_4; + } + + @Override + public void testLeaksOnCleanBuild() throws Exception { + super.testLeaksOnCleanBuild(); + } + + @Override + public void testLeaksOnFullBuild() throws Exception { + super.testLeaksOnFullBuild(); + } + + @Override + public void testLeaksOnIncrementalBuild() throws Exception { + super.testLeaksOnIncrementalBuild(); + } +} diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java index 97ec40e04b..49cdf411bb 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java @@ -138,7 +138,7 @@ public void addClassFolder(IPath projectPath, IPath classFolderPath, boolean isE } public IPath addPackageFragmentRoot(IPath projectPath, String sourceFolderName) throws JavaModelException { - return addPackageFragmentRoot(projectPath, sourceFolderName, null, null); //$NON-NLS-1$ + return addPackageFragmentRoot(projectPath, sourceFolderName, null, null); } public IPath addTestPackageFragmentRoot(IPath projectPath, String sourceFolderName) throws JavaModelException { @@ -214,6 +214,14 @@ public void addClassFolder(IPath projectPath, IPath classFolderPath, boolean isE requiredComplianceFlag = AbstractCompilerTest.F_9; compilerVersion = CompilerOptions.VERSION_9; } + else if ("10".equals(compliance)) { + requiredComplianceFlag = AbstractCompilerTest.F_10; + compilerVersion = CompilerOptions.VERSION_10; + } + else if ("11".equals(compliance)) { + requiredComplianceFlag = AbstractCompilerTest.F_11; + compilerVersion = CompilerOptions.VERSION_11; + } else if (!"1.4".equals(compliance) && !"1.3".equals(compliance)) { throw new UnsupportedOperationException("Test framework doesn't support compliance level: " + compliance); } @@ -501,7 +509,7 @@ public void cleanBuild(String projectName) { } return project; } - + /** * Safely delete the given resource. */ diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractComparableTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractComparableTest.java index a62c336c5b..c0e95a3c06 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractComparableTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractComparableTest.java @@ -14,6 +14,8 @@ * bug 376590 - Private fields with @Inject are ignored by unused field validation * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for * bug 386692 - Missing "unused" warning on "autowired" fields + * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for + * bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -68,6 +70,21 @@ public class AbstractComparableTest extends AbstractRegressionTest { "\n" + "}"; + protected static final String JUNIT_METHODSOURCE_NAME = "org/junit/jupiter/params/provider/MethodSource.java"; + protected static final String JUNIT_METHODSOURCE_CONTENT = + "package org.junit.jupiter.params.provider;\n" + + "import java.lang.annotation.ElementType;\n" + + "import java.lang.annotation.Retention;\n" + + "import java.lang.annotation.RetentionPolicy;\n" + + "import java.lang.annotation.Target;\n" + + "@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "public @interface MethodSource {\n" + + "\n" + + " String[] value() default \"\";\n" + + "\n" + + "}"; + public static Test buildComparableTestSuite(Class evaluationTestClass) { Test suite = buildMinimalComplianceTestSuite(evaluationTestClass, F_1_5); TESTS_COUNTERS.put(evaluationTestClass.getName(), Integer.valueOf(suite.countTestCases())); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java index ec6f7a7b42..01f318f6a7 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -748,8 +748,6 @@ protected static class JavacTestOptions { } // WORK consider adding reversed pivots } : null, - EclipseBug112433 = RUN_JAVAC ? // https://bugs.eclipse.org/bugs/show_bug.cgi?id=112433 - new EclipseJustification(MismatchType.JavacErrorsEclipseNone) : null, EclipseBug126712 = RUN_JAVAC ? // https://bugs.eclipse.org/bugs/show_bug.cgi?id=126712 & http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6342411 new EclipseJustification(MismatchType.StandardOutputMismatch) { Excuse excuseFor(JavacCompiler compiler) { @@ -802,8 +800,12 @@ protected static class JavacTestOptions { new EclipseJustification(MismatchType.StandardOutputMismatch) : null; public static final EclipseJustification EclipseJustification0001 = RUN_JAVAC ? - new EclipseJustification(MismatchType.EclipseErrorsJavacNone) : null; - /* javac properly detects duplicate attributes in annotations in the + new EclipseJustification(MismatchType.EclipseErrorsJavacNone) { + Excuse excuseFor(JavacCompiler compiler) { + return compiler.compliance < ClassFileConstants.JDK1_7 ? this : null; + } + } : null; + /* javac 1.6- properly detects duplicate attributes in annotations in the * simplest case (AnnotationTest#18b) but fails on a slightly more * complex one where the duplicate is within an embedded annotation; * there seems to be no reason for not reporting the error @@ -928,11 +930,13 @@ protected static class JavacTestOptions { JavacBug8144673 = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8144673 new JavacHasABug(MismatchType.JavacErrorsEclipseNone, ClassFileConstants.JDK9, 0100) : null, JavacBug8204534 = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8204534 - new JavacHasABug(MismatchType.EclipseErrorsJavacNone, ((long)55)<<16, 0000) : null, // FIXME: use JDK11 + new JavacHasABug(MismatchType.EclipseErrorsJavacNone, ClassFileConstants.JDK11, 0000) : null, JavacBug8207032 = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8207032 new JavacHasABug(MismatchType.EclipseErrorsJavacNone) : null, JavacBug8044196 = RUN_JAVAC ? // likely https://bugs.openjdk.java.net/browse/JDK-8044196, intermittently masked by https://bugs.openjdk.java.net/browse/JDK-8029161 - new JavacHasABug(MismatchType.EclipseErrorsJavacNone, ClassFileConstants.JDK9, 0000, true) : null; + new JavacHasABug(MismatchType.EclipseErrorsJavacNone, ClassFileConstants.JDK9, 0000, true) : null, + JavacBug6337964 = RUN_JAVAC ? // https://bugs.eclipse.org/bugs/show_bug.cgi?id=112433 + new JavacHasABug(MismatchType.JavacErrorsEclipseNone, ClassFileConstants.JDK1_6, 1045/*guessed*/, true) : null; // bugs that have been fixed but that we've not identified public static JavacHasABug @@ -2330,10 +2334,7 @@ protected void runJavac( // potentially holding indications regarding the failure if (expectedErrorString != null /* null skips error test */ && mismatch == 0) { err = adjustErrorOutput(stderr.toString().trim()); - if (!expectedErrorString.equals(err) && // special case: command-line java does not like missing main methods - !(expectedErrorString.length() == 0 && - (err.indexOf("java.lang.NoSuchMethodError: main") != -1) - || err.indexOf("Error: Main method not found in class") != -1)) { + if (!errorStringMatch(expectedErrorString, err)) { mismatch = JavacTestOptions.MismatchType.ErrorOutputMismatch; } } @@ -2352,6 +2353,28 @@ protected void runJavac( } } } +private boolean errorStringMatch(String expectedErrorStringStart, String actualError) { + /* + * From TestVerifier.checkBuffers(): + * This is an opportunistic heuristic for error strings comparison: + * - null means skip test; + * - empty means exactly empty; + * - other means starts with. + * If this became insufficient, we could envision using specific + * matchers for specific needs. + */ + if (expectedErrorStringStart == null) + return true; + // special case: command-line java does not like missing main methods ... + if (actualError.indexOf("java.lang.NoSuchMethodError: main") != -1 + || actualError.indexOf("Error: Main method not found in class") != -1) + return true; // ... ignore this. + if (expectedErrorStringStart.length() == 0) + return expectedErrorStringStart.equals(actualError); + if (actualError.startsWith(expectedErrorStringStart)) + return true; + return false; +} /** Hook for AbstractRegressionTest9 */ protected String expandFileNameForJavac(String fileName) { return fileName; @@ -3030,8 +3053,7 @@ protected void runNegativeTest(boolean skipJavac, JavacTestOptions javacTestOpti // non-javac part if (shouldFlushOutputDirectory) Util.flushDirectoryContent(new File(OUTPUT_DIR)); - // complain early in RUN_JAVAC mode (avoid to do it else until we've fixed all tests) - if (RUN_JAVAC && testFiles != null && (testFiles.length % 2) != 0) { + if (testFiles != null && (testFiles.length % 2) != 0) { fail("odd number of strings in testFiles"); } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java index 51d8632e93..f967c52489 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java @@ -25,6 +25,8 @@ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for * bug 386692 - Missing "unused" warning on "autowired" fields + * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for + * bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -5010,9 +5012,10 @@ public void test143() { } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=99009 public void test157() { - Map options = getCompilerOptions(); - options.put(CompilerOptions.OPTION_ReportHiddenCatchBlock, CompilerOptions.WARNING); - this.runNegativeTest( + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportHiddenCatchBlock, CompilerOptions.WARNING); + runner.testFiles = new String[] { "X.java", "public class X {\n" + @@ -5029,12 +5032,39 @@ public void test143() { "class AX extends Exception {}\n" + "@SuppressWarnings({\"serial\"})\n" + "class BX extends AX {}\n" - }, - "", - null, - true, - options - ); + }; + runner.javacTestOptions = JavacTestOptions.SKIP; // javac doesn't support @SW("hiding") here, see test157b + runner.runConformTest(); + } + public void test157b() { + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportHiddenCatchBlock, CompilerOptions.WARNING); + runner.testFiles = + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String[] args) {\n" + + " try {\n" + + " throw new BX();\n" + + " } catch(BX e) {\n" + + " } catch(AX e) {\n" + + " }\n" + + " }\n" + + "} \n" + + "@SuppressWarnings({\"serial\"})\n" + + "class AX extends Exception {}\n" + + "@SuppressWarnings({\"serial\"})\n" + + "class BX extends AX {}\n" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. WARNING in X.java (at line 6)\n" + + " } catch(AX e) {\n" + + " ^^\n" + + "Unreachable catch block for AX. Only more specific exceptions are thrown and they are handled by previous catch block(s).\n" + + "----------\n"; + runner.runWarningTest(); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=99009 public void test158() { @@ -5064,9 +5094,10 @@ public void test143() { } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=99009 public void test159() { - Map options = getCompilerOptions(); - options.put(CompilerOptions.OPTION_ReportIndirectStaticAccess, CompilerOptions.WARNING); - this.runNegativeTest( + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportIndirectStaticAccess, CompilerOptions.WARNING); + runner.testFiles = new String[] { "X.java", "@SuppressWarnings({\"static-access\"})\n" + @@ -5090,18 +5121,16 @@ public void test143() { "}\n" + "class XZ extends XY {\n" + "}" - }, - "", - null, - true, - options - ); + }; + runner.javacTestOptions = JavacTestOptions.SKIP; // only testing Eclipse-specific @SW + runner.runConformTest(); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=99009 public void test160() { - Map options = getCompilerOptions(); - options.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.WARNING); - this.runNegativeTest( + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.WARNING); + runner.testFiles = new String[] { "X.java", "@SuppressWarnings(\"static-access\")\n" + @@ -5113,12 +5142,9 @@ public void test143() { "class XY {\n" + " static int S = 10;\n" + "}" - }, - "", - null, - true, - options - ); + }; + runner.javacTestOptions = JavacTestOptions.SKIP; // only testing Eclipse-specific @SW + runner.runConformTest(); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=99009 public void test161() { @@ -5659,8 +5685,8 @@ public void test143() { "public class X extends Exception {\n" + " @SuppressWarnings(\"nls\")\n" + " String s = \"Hello\"; \n" + - " @SuppressWarnings(\"serial\")\n" + - " String s2 = \"Hello2\"; \n" + + " @SuppressWarnings(\"serial\")\n" + // no nls-warning here + " String s2 = \"Hello2\"; \n" + // but an nls-warning here "}" }, null, customOptions, @@ -5680,7 +5706,7 @@ public void test143() { " ^^^^^^^^\n" + "Non-externalized string literal; it should be followed by //$NON-NLS-<n>$\n" + "----------\n", - null, null, JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings); + null, null, JavacTestOptions.SKIP); // nls-warnings are specific to Eclipse - special-casing this special case is irrelevant for javac } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=97220 - variation public void test172() { @@ -5749,7 +5775,7 @@ public void test143() { " ^^^^^^^^\n" + "Non-externalized string literal; it should be followed by //$NON-NLS-<n>$\n" + "----------\n", - null, null, JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings); + null, null, JavacTestOptions.SKIP); // nls-warnings are specific to Eclipse - special-casing this special case is irrelevant for javac } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=97220 - variation public void test174() { @@ -5923,7 +5949,7 @@ public void test143() { "", "", null, - JavacTestOptions.EclipseJustification.EclipseBug112433); + JavacTestOptions.JavacHasABug.JavacBug6337964); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=116028 public void test180() { @@ -6656,7 +6682,7 @@ public void test199() { "", "", null, - JavacTestOptions.EclipseJustification.EclipseBug112433); + JavacTestOptions.JavacHasABug.JavacBug6337964); } // JLS 3 - 9.6: cannot override Object's methods public void test200() { @@ -9367,8 +9393,7 @@ public void test278() { "----------\n"; this.runNegativeTest( testString, - expectedOutput, - JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); + expectedOutput); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=301683 public void test279() { @@ -9392,8 +9417,7 @@ public void test279() { "----------\n"; this.runNegativeTest( testString, - expectedOutput, - JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); + expectedOutput); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=295551 public void test280() { @@ -9869,15 +9893,16 @@ public void test296() { } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=343621 public void test297() { - Map customOptions = getCompilerOptions(); - customOptions.put(CompilerOptions.OPTION_SuppressWarnings, CompilerOptions.ENABLED); - customOptions.put(CompilerOptions.OPTION_ReportUnhandledWarningToken, CompilerOptions.WARNING); - customOptions.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED); - customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING); - customOptions.put(CompilerOptions.OPTION_ReportComparingIdentical, CompilerOptions.ERROR); - customOptions.put(CompilerOptions.OPTION_ReportUncheckedTypeOperation, CompilerOptions.ERROR); + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_SuppressWarnings, CompilerOptions.ENABLED); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnhandledWarningToken, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_ReportComparingIdentical, CompilerOptions.ERROR); + runner.customOptions.put(CompilerOptions.OPTION_ReportUncheckedTypeOperation, CompilerOptions.ERROR); - String expectedErrors = + runner.expectedCompilerLog = "----------\n" + "1. ERROR in A.java (at line 15)\n" + " return i == i;\n" + @@ -9886,7 +9911,7 @@ public void test297() { "----------\n"; if (this.complianceLevel >= ClassFileConstants.JDK1_7) { - expectedErrors = + runner.expectedCompilerLog = "----------\n" + "1. ERROR in A.java (at line 10)\n" + " public final Object build(Class<? super Object>... objects) {\n" + @@ -9899,7 +9924,7 @@ public void test297() { "Comparing identical expressions\n" + "----------\n"; } - String testFiles [] = new String[] { + runner.testFiles = new String[] { "A.java", "public class A {\n" + " public void one() {\n" + @@ -9919,12 +9944,8 @@ public void test297() { " }\n" + "}" }; - runNegativeTest( - testFiles, - expectedErrors, - null, - true, - customOptions); + runner.javacTestOptions = JavacTestOptions.Excuse.EclipseWarningConfiguredAsError; + runner.runNegativeTest(); } // Bug 366003 - CCE in ASTNode.resolveAnnotations(ASTNode.java:639) // many syntax errors fixed, does not trigger CCE @@ -10327,7 +10348,7 @@ public void testBug365437b() { null, customOptions, expectedErrorString, - JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); + isJRE9Plus ? JavacTestOptions.SKIP : JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); // javac9+ cannot access javax.annotation } finally { this.javaClassLib = save; } @@ -10906,7 +10927,8 @@ public void testBug386356_2() { " return null;\n" + " }\n" + "}" - }); + }, + isJRE9Plus ? JavacTestOptions.SKIP : JavacTestOptions.DEFAULT); // javac9+ cannot access javax.xml.bind } finally { this.javaClassLib = save; } @@ -11719,11 +11741,12 @@ public void testBug506888a() throws Exception { if (this.complianceLevel <= ClassFileConstants.JDK1_5) { return; } - Map options = getCompilerOptions(); - options.put(CompilerOptions.OPTION_ReportUnusedWarningToken, CompilerOptions.ERROR); - options.put(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, CompilerOptions.IGNORE); - options.put(CompilerOptions.OPTION_ReportMissingDefaultCase, CompilerOptions.WARNING); - this.runNegativeTest( + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnusedWarningToken, CompilerOptions.ERROR); + runner.customOptions.put(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, CompilerOptions.IGNORE); + runner.customOptions.put(CompilerOptions.OPTION_ReportMissingDefaultCase, CompilerOptions.WARNING); + runner.testFiles = new String[] { "X.java", "public class X {\n" + @@ -11732,14 +11755,16 @@ public void testBug506888a() throws Exception { " void foo() {\n" + " }\n" + "} \n", - }, + }; + runner.expectedCompilerLog = "----------\n" + "1. INFO in X.java (at line 3)\n" + " @SuppressWarnings({\"incomplete-switch\"})\n" + " ^^^^^^^^^^^^^^^^^^^\n" + "At least one of the problems in category \'incomplete-switch\' is not analysed due to a compiler option being ignored\n" + - "----------\n", - null, true, options); + "----------\n"; + runner.javacTestOptions = JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings; + runner.runWarningTest(); } public void testBug506888b() throws Exception { if (this.complianceLevel <= ClassFileConstants.JDK1_5) { @@ -11768,12 +11793,13 @@ public void testBug506888c() throws Exception { if (this.complianceLevel <= ClassFileConstants.JDK1_5) { return; } - Map options = getCompilerOptions(); - options.put(CompilerOptions.OPTION_ReportUnusedWarningToken, CompilerOptions.WARNING); - options.put(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, CompilerOptions.WARNING); - options.put(CompilerOptions.OPTION_ReportMissingDefaultCase, CompilerOptions.WARNING); - options.put(CompilerOptions.OPTION_ReportUncheckedTypeOperation, CompilerOptions.WARNING); - this.runNegativeTest( + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnusedWarningToken, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_ReportMissingDefaultCase, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_ReportUncheckedTypeOperation, CompilerOptions.WARNING); + runner.testFiles = new String[] { "X.java", "public class X {\n" + @@ -11785,14 +11811,16 @@ public void testBug506888c() throws Exception { " }\n" + " enum Color { BLUE, RED; } \n" + "} \n", - }, + }; + runner.expectedCompilerLog = "----------\n" + "1. WARNING in X.java (at line 3)\n" + " @SuppressWarnings({\"incomplete-switch\", \"unchecked\"})\n" + " ^^^^^^^^^^^\n" + "Unnecessary @SuppressWarnings(\"unchecked\")\n" + - "----------\n", - null, true, options); + "----------\n"; + runner.javacTestOptions = JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings; + runner.runWarningTest(); } public void testBug506888d() throws Exception { if (this.complianceLevel <= ClassFileConstants.JDK1_5) { @@ -11882,7 +11910,7 @@ public void testBug506888f() throws Exception { null /* vmArguments */, options, new Requestor(true, requestor, false, true), - JavacTestOptions.DEFAULT); + JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings); assertNotNull(requestor.problemArguments); assertEquals(1, requestor.problemArguments.length); assertEquals(JavaCore.COMPILER_PB_UNUSED_PARAMETER, requestor.problemArguments[0]); @@ -11978,4 +12006,114 @@ public void testBug537593_001() { JavacTestOptions.DEFAULT); assertNull(requestor.problemArguments); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=542520 - [JUnit 5] Warning The method xxx from the type X +// is never used locally is shown when using MethodSource - common case +public void testBug542520a() throws Exception { + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR); + runner.testFiles = + new String[] { + JUNIT_METHODSOURCE_NAME, + JUNIT_METHODSOURCE_CONTENT, + "ExampleTest.java", + "import java.util.Arrays;\n" + + "import java.util.List;\n" + + "import org.junit.jupiter.params.provider.MethodSource;\n" + + "public class ExampleTest {\n" + + "\n" + + " @MethodSource(\"getIntegers\")\n" + + " void testIntegers(Integer integer) {}\n" + + " \n" + + " private static List<Integer> getIntegers() {\n" + + " return Arrays.asList(0, 5, 1);\n" + + " }\n" + + "}\n", + }; + runner.runConformTest(); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=542520 - [JUnit 5] Warning The method xxx from the type X +// is never used locally is shown when using MethodSource - variation with fully qualified annotation +public void testBug542520b() throws Exception { + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR); + runner.testFiles = + new String[] { + JUNIT_METHODSOURCE_NAME, + JUNIT_METHODSOURCE_CONTENT, + "ExampleTest.java", + "import java.util.Arrays;\n" + + "import java.util.List;\n" + + "public class ExampleTest {\n" + + "\n" + + " @org.junit.jupiter.params.provider.MethodSource(\"getIntegers\")\n" + + " void testIntegers(Integer integer) {}\n" + + " \n" + + " private static List<Integer> getIntegers() {\n" + + " return Arrays.asList(0, 5, 1);\n" + + " }\n" + + "}\n", + }; + runner.runConformTest(); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=542520 - [JUnit 5] Warning The method xxx from the type X +// is never used locally is shown when using MethodSource - marker annotation +public void testBug542520c() throws Exception { + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR); + runner.testFiles = + new String[] { + JUNIT_METHODSOURCE_NAME, + JUNIT_METHODSOURCE_CONTENT, + "ExampleTest.java", + "import java.util.Arrays;\n" + + "import java.util.List;\n" + + "import org.junit.jupiter.params.provider.MethodSource;\n" + + "public class ExampleTest {\n" + + "\n" + + " @MethodSource\n" + + " void testIntegers(Integer integer) {}\n" + + " \n" + + " private static List<Integer> testIntegers() {\n" + + " return Arrays.asList(0, 5, 1);\n" + + " }\n" + + "}\n", + }; + runner.runConformTest(); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=542520 - [JUnit 5] Warning The method xxx from the type X +// is never used locally is shown when using MethodSource - missing no-args method source +public void testBug542520d() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR); + this.runNegativeTest( + true, + new String[] { + JUNIT_METHODSOURCE_NAME, + JUNIT_METHODSOURCE_CONTENT, + "ExampleTest.java", + "import java.util.Arrays;\n" + + "import java.util.List;\n" + + "import org.junit.jupiter.params.provider.MethodSource;\n" + + "public class ExampleTest {\n" + + "\n" + + " @MethodSource(\"getIntegers\")\n" + + " void testIntegers(Integer integer) {}\n" + + " \n" + + " private static List<Integer> getIntegers(int i) {\n" + + " return Arrays.asList(0, 5, 1);\n" + + " }\n" + + "}\n", + }, + null, customOptions, + "----------\n" + + "1. ERROR in ExampleTest.java (at line 9)\n" + + " private static List<Integer> getIntegers(int i) {\n" + + " ^^^^^^^^^^^^^^^^^^\n" + + "The method getIntegers(int) from the type ExampleTest is never used locally\n" + + "----------\n", + JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); +} } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java index 99da258d2d..ca24f35d93 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -6476,5 +6476,36 @@ public void testBug478708() { "----------\n"; runner.runNegativeTest(); } +public void testBug543526() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "C.java", + "class C {\n" + + " <T extends CharSequence & java.util.List<T>> boolean m(T x) {\n" + + " return x instanceof String;\n" + + " }\n" + + "}\n" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. ERROR in C.java (at line 3)\n" + + " return x instanceof String;\n" + + " ^^^^^^^^^^^^^^^^^^^\n" + + "Incompatible conditional operand types T and String\n" + + "----------\n"; + runner.runNegativeTest(); +} +public void testBug543526b() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "C.java", + "class C {\n" + + " <T extends CharSequence & java.util.List<T>> boolean m(T x) {\n" + + " return x instanceof Comparable<?>;\n" + // no problem casting to an interface + " }\n" + + "}\n" + }; + runner.runConformTest(); +} } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java index 8e40010f9d..1979b4bbdd 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2018 GK Software AG, and others. + * Copyright (c) 2013, 2019 GK Software AG, and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -9472,4 +9472,17 @@ public void testBug508834_comment0() { }; runner.runConformTest(); } + public void testBug543820() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "A.java", + "import java.util.concurrent.atomic.AtomicReference;\n" + + "import java.util.Optional;\n" + + "public class A {\n" + + " private final ThreadLocal<AtomicReference<Optional<Long>>> var =\n" + + " ThreadLocal.withInitial(() -> new AtomicReference<>(Optional.empty()));" + + "}\n" + }; + runner.runConformTest(); + } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JEP323VarLambdaParamsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JEP323VarLambdaParamsTest.java index 5bc4f6e811..1b6fc30645 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JEP323VarLambdaParamsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JEP323VarLambdaParamsTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 IBM Corporation and others. + * Copyright (c) 2018, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -316,4 +316,29 @@ public void testBug536159_04() throws IOException { "\'var\' is not allowed as an element type of an array\n" + "----------\n"); } +public void testBug541532_01() throws IOException { + runConformTest(new String[] { + "X.java", + "import java.util.Arrays;\n" + + "import java.util.List;\n" + + "\n" + + "public class X {\n" + + "\n" + + " public static void foo(List<String> list) {\n" + + " list.stream()\n" + + " .map((var s) -> s.toLowerCase())\n" + + " .forEach(System.out::println);\n" + + "\n" + + " list.stream()\n" + + " .filter((var s) -> s.length() == 1)\n" + + " .forEach(System.out::println);\n" + + " }\n" + + " public static void main(String[] args) {\n" + + " String[] greetings = {\"hello\", \"world\"};\n" + + " X.foo(Arrays.asList(greetings));\n" + + " }\n" + + "}\n" + }, + "hello\nworld"); +} }
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java index 74b75a5444..65587be739 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2018 IBM Corporation and others. + * Copyright (c) 2016, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -383,8 +383,8 @@ public class ModuleCompilationTests extends AbstractBatchCompilerTest { "----------\n" + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 4)\n" + " java.sql.Connection con = null;\n" + - " ^^^^^^^^\n" + - "java.sql cannot be resolved to a type\n" + + " ^^^^^^^^^^^^^^^^^^^\n" + + "The type java.sql.Connection is not accessible\n" + "----------\n" + "1 problem (1 error)\n", true, @@ -1959,8 +1959,8 @@ public class ModuleCompilationTests extends AbstractBatchCompilerTest { "----------\n" + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p/X.java (at line 2)\n" + " public class X extends a.A {\n" + - " ^\n" + - "a cannot be resolved to a type\n" + + " ^^^\n" + + "The type a.A is not accessible\n" + "----------\n" + "1 problem (1 error)\n", false, @@ -2017,8 +2017,8 @@ public class ModuleCompilationTests extends AbstractBatchCompilerTest { "----------\n" + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p/X.java (at line 2)\n" + " public class X extends a.A {\n" + - " ^\n" + - "a cannot be resolved to a type\n" + + " ^^^\n" + + "The type a.A is not accessible\n" + "----------\n" + "1 problem (1 error)\n", false, diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java index 751faf0133..cc7fc5fb1a 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2017 IBM Corporation and others. + * Copyright (c) 2005, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -3072,6 +3072,40 @@ public void test526911a() { }; this.runConformTest(sourceFiles, "1 11", options); } +public void testBug533475() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + runConformTest( + new String[] { + "SwitchBug.java", + "public class SwitchBug {\n" + + " static class MyClass {\n" + + " private static final Object C = \"\";\n" + + "\n" + + " public enum State {\n" + + " ENABLED(C); // pass null constant\n" + + "\n" + + " State(Object value) {\n" + + " } // value can be ignored\n" + + " }\n" + + "\n" + + " /* unused method with switch statement IN SAME CLASS */\n" + + " private void unusedMethod() {\n" + + " switch (State.ENABLED) {\n" + + " case ENABLED:\n" + + " break;\n" + + " }\n" + + " }\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " // access enum values from an other class\n" + + " MyClass.State.values();\n" + + " System.out.println(\"It runs.\");\n" + + " }\n" + + "}\n" + }); +} public static Class testClass() { return SwitchTest.class; } 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 a0a017510e..b44a618319 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.700.qualifier +Bundle-Version: 3.10.800.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 535cfb65b9..1acae5cc9a 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.700-SNAPSHOT</version> + <version>3.10.800-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java index 7372b2b857..298ae13dc1 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java @@ -12938,4 +12938,25 @@ public void testBug542625() { "}"; formatSource(source); } +/** + * https://bugs.eclipse.org/543780 - [formatter] Compact 'if else': can't wrap before else statement + */ +public void testBug543780() { + this.formatterPrefs.keep_then_statement_on_same_line = true; + this.formatterPrefs.keep_else_statement_on_same_line = true; + this.formatterPrefs.alignment_for_compact_if = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE; + this.formatterPrefs.use_tabs_only_for_leading_indentations = true; + String source = + "class Example {\n" + + " int foo(int argument) {\n" + + " if (argument == 0)\n" + + " return 0;\n" + + " if (argument == 1)\n" + + " return 42;\n" + + " else\n" + + " return 43;\n" + + " }\n" + + "}"; + formatSource(source); +} } 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 704a97c3d5..36879049c5 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 @@ -714,7 +714,7 @@ public class FormatterRegressionTests extends AbstractJavaModelTests { public void test050() { DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings()); preferences.tab_char = DefaultCodeFormatterOptions.TAB; - preferences.insert_space_after_binary_operator = false; + preferences.insert_space_after_additive_operator = false; preferences.insert_space_before_unary_operator = false; preferences.insert_space_after_unary_operator = false; DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); @@ -1083,8 +1083,8 @@ public class FormatterRegressionTests extends AbstractJavaModelTests { preferences.brace_position_for_block = DefaultCodeFormatterConstants.NEXT_LINE; preferences.brace_position_for_type_declaration = DefaultCodeFormatterConstants.NEXT_LINE; preferences.brace_position_for_method_declaration = DefaultCodeFormatterConstants.NEXT_LINE; - preferences.insert_space_before_binary_operator = false; - preferences.insert_space_after_binary_operator = false; + preferences.insert_space_before_relational_operator = false; + preferences.insert_space_after_relational_operator = false; DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); runTest(codeFormatter, "test086", "A.java");//$NON-NLS-1$ //$NON-NLS-2$ } @@ -1143,8 +1143,8 @@ public class FormatterRegressionTests extends AbstractJavaModelTests { public void test092() { DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings()); preferences.tab_char = DefaultCodeFormatterOptions.TAB; - preferences.insert_space_after_binary_operator = false; - preferences.insert_space_before_binary_operator = false; + preferences.insert_space_after_relational_operator = false; + preferences.insert_space_before_relational_operator = false; DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); runTest(codeFormatter, "test092", "A.java", CodeFormatter.K_STATEMENTS);//$NON-NLS-1$ //$NON-NLS-2$ } @@ -1484,7 +1484,7 @@ public class FormatterRegressionTests extends AbstractJavaModelTests { public void test125() { DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings()); preferences.tab_char = DefaultCodeFormatterOptions.TAB; - preferences.insert_space_after_binary_operator = false; + preferences.insert_space_after_additive_operator = false; preferences.insert_space_before_unary_operator = false; preferences.insert_space_after_unary_operator = false; DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); @@ -4542,7 +4542,7 @@ public class FormatterRegressionTests extends AbstractJavaModelTests { preferences.tab_char = DefaultCodeFormatterOptions.TAB; preferences.insert_space_before_unary_operator = false; preferences.insert_space_after_assignment_operator = false; - preferences.insert_space_after_binary_operator = false; + preferences.insert_space_after_additive_operator = false; DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); runTest(codeFormatter, "test341", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$ } @@ -6392,8 +6392,10 @@ public class FormatterRegressionTests extends AbstractJavaModelTests { options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_FOR, JavaCore.INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, JavaCore.INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, JavaCore.INSERT); - options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT); - options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR, JavaCore.INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR, JavaCore.INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR, JavaCore.INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR, JavaCore.INSERT); DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options); DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); runTest(codeFormatter, "test476", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$ @@ -12122,8 +12124,8 @@ public void test767b() throws Exception { this.formatterOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7); this.formatterOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7); this.formatterOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR, JavaCore.INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR, JavaCore.DO_NOT_INSERT); setFormatterOptions80(); String source = "package test;\n" + @@ -12958,8 +12960,8 @@ public void testBug379793() throws Exception { //To verify that the whitespace options for resources in try statement work correctly public void testBug405038() throws Exception { this.formatterPrefs = null; - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); String source = "public class FormatterError {\n" + " int foo(int a, int b, int c) {\n" + @@ -12978,8 +12980,8 @@ public void testBug405038() throws Exception { //To verify that the whitespace options for resources in try statement work correctly public void testBug405038_2() throws Exception { this.formatterPrefs = null; - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); String source = "public class FormatterError {\n" + " int foo(int a, int b, int c) {\n" + @@ -12998,8 +13000,8 @@ public void testBug405038_2() throws Exception { //To verify that the whitespace options for resources in try statement work correctly public void testBug405038_3() throws Exception { this.formatterPrefs = null; - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); String source = "public class FormatterError {\n" + " int foo(int a, int b, int c) {\n" + @@ -13018,8 +13020,8 @@ public void testBug405038_3() throws Exception { //To verify that the whitespace options for resources in try statement work correctly public void testBug405038_4() throws Exception { this.formatterPrefs = null; - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); String source = "public class FormatterError {\n" + " int foo(int a, int b, int c) {\n" + @@ -13038,8 +13040,8 @@ public void testBug405038_4() throws Exception { //To verify that the whitespace options for resources in try statement work correctly public void testBug405038_5() throws Exception { this.formatterPrefs = null; - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); - this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); + this.formatterOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); String source = "public class FormatterError {\n" + " int foo(int a, int b, int c) {\n" + @@ -14708,4 +14710,67 @@ public void testBug543079g() throws JavaModelException { String input = getCompilationUnit("Formatter", "", "test543079", "in.java").getSource(); formatSource(input, getCompilationUnit("Formatter", "", "test543079", "G_out.java").getSource()); } +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565a() throws JavaModelException { + this.formatterPrefs.insert_space_before_multiplicative_operator = false; + this.formatterPrefs.insert_space_before_bitwise_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "A_out.java").getSource()); +} +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565b() throws JavaModelException { + this.formatterPrefs.insert_space_after_multiplicative_operator = false; + this.formatterPrefs.insert_space_after_additive_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "B_out.java").getSource()); +} +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565c() throws JavaModelException { + this.formatterPrefs.insert_space_before_additive_operator = false; + this.formatterPrefs.insert_space_before_logical_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "C_out.java").getSource()); +} +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565d() throws JavaModelException { + this.formatterPrefs.insert_space_before_string_concatenation = false; + this.formatterPrefs.insert_space_after_bitwise_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "D_out.java").getSource()); +} +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565e() throws JavaModelException { + this.formatterPrefs.insert_space_after_string_concatenation = false; + this.formatterPrefs.insert_space_before_shift_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "E_out.java").getSource()); +} +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565f() throws JavaModelException { + this.formatterPrefs.insert_space_after_shift_operator = false; + this.formatterPrefs.insert_space_after_relational_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "F_out.java").getSource()); +} +/** + * https://bugs.eclipse.org/159565 - [formatter] Separate white space preferences for separate operators + */ +public void testBug159565g() throws JavaModelException { + this.formatterPrefs.insert_space_before_relational_operator = false; + this.formatterPrefs.insert_space_after_logical_operator = false; + String input = getCompilationUnit("Formatter", "", "test159565", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "test159565", "G_out.java").getSource()); +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java index face2acc8e..f73f342df1 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java @@ -387,7 +387,7 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { * @return a test suite ({@link Test}) */ public static Test buildModelTestSuite(int minCompliance, Class evaluationTestClass) { - if ((AbstractCompilerTest.getPossibleComplianceLevels() & minCompliance) != 0) + if (AbstractCompilerTest.getPossibleComplianceLevels() >= minCompliance) return buildModelTestSuite(evaluationTestClass, ORDERING); return new Suite(evaluationTestClass.getName()); } @@ -519,6 +519,20 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { protected void addLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String[] nonJavaResources, String compliance) throws CoreException, IOException { addLibrary(javaProject, jarName, sourceZipName, pathAndContents, nonJavaResources, null, null, compliance, null); } + protected IClasspathAttribute[] moduleAttribute() { + return new IClasspathAttribute[] { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") }; + } + protected IClasspathEntry newModularLibraryEntry(IPath path, IPath sourceAttachmentPath, IPath sourceAttachmentRootPath) { + return JavaCore.newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, null, moduleAttribute(), false); + } + protected void addModularLibraryEntry(IJavaProject project, IPath libraryPath, IPath sourceAttachmentPath) throws JavaModelException { + addClasspathEntry(project, newModularLibraryEntry(libraryPath, sourceAttachmentPath, null)); + } + protected void addModularLibrary(IJavaProject javaProject, String jarName, String sourceZipName, String[] pathAndContents, String compliance) throws CoreException, IOException { + createLibrary(javaProject, jarName, sourceZipName, pathAndContents, null, compliance); + IPath projectPath = javaProject.getPath(); + addModularLibraryEntry(javaProject, projectPath.append(jarName), projectPath.append(sourceZipName)); + } protected void addLibrary( IJavaProject javaProject, String jarName, @@ -1454,6 +1468,8 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, e.getMessage(), e)); } } else { + if (attributes == null) + attributes = new IClasspathAttribute[] { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") }; jrtEntry = JavaCore.newLibraryEntry(bootModPath, sourceAttachment, null, null, attributes, false); } IJavaProject project = this.createJavaProject(name, srcFolders, new String[0], diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java index 62b87f8a2e..b9fc44645b 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2018 IBM Corporation and others. + * Copyright (c) 2016, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -830,6 +830,122 @@ public void test522613_001() throws Exception { deleteProject(project1); } } +public void test540591() throws Exception { + IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9"); + try { + project1.open(null); + createTypePlus("/Completion9_1/src/", "pack11", "IService", "", false /* isClass */, true /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC", "implements pack11.IService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "AbstractService", "implements pack11.IService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC2", "extends pack11.AbstractService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC3", "extends pack11.AbstractService", true /* isClass */, false /* createFolder */); + + String filePath1 = "/Completion9_1/src/module-info.java"; + String completeBehind = "CC"; + String fileContent1 = "module first {\n" + + "provides pack11.IService with " + completeBehind + + "}\n"; + createFile(filePath1, fileContent1); + addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project1.close(); // sync + project1.open(null); + + int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length(); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); + + ICompilationUnit unit = getCompilationUnit(filePath1); + unit.codeComplete(cursorLocation, requestor); + + String expected = "CCC[TYPE_REF]{pack11.CCC, pack11, Lpack11.CCC;, null, 49}\n" + + "CCC2[TYPE_REF]{pack11.CCC2, pack11, Lpack11.CCC2;, null, 49}\n" + + "CCC3[TYPE_REF]{pack11.CCC3, pack11, Lpack11.CCC3;, null, 49}" + ; + assertResults(expected, requestor.getResults()); + } finally { + deleteProject(project1); + } +} + + +public void test540591_mismatchedCase() throws Exception { + IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9"); + try { + project1.open(null); + createTypePlus("/Completion9_1/src/", "pack11", "IService", "", false /* isClass */, true /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC", "implements pack11.IService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "AbstractService", "implements pack11.IService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC2", "extends pack11.AbstractService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC3", "extends pack11.AbstractService", true /* isClass */, false /* createFolder */); + + String filePath1 = "/Completion9_1/src/module-info.java"; + String completeBehind = "cc"; + String fileContent1 = "module first {\n" + + "provides pack11.IService with " + completeBehind + + "}\n"; + createFile(filePath1, fileContent1); + addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project1.close(); // sync + project1.open(null); + + int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length(); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); + + ICompilationUnit unit = getCompilationUnit(filePath1); + unit.codeComplete(cursorLocation, requestor); + + String expected = "CCC[TYPE_REF]{pack11.CCC, pack11, Lpack11.CCC;, null, 39}\n" + + "CCC2[TYPE_REF]{pack11.CCC2, pack11, Lpack11.CCC2;, null, 39}\n" + + "CCC3[TYPE_REF]{pack11.CCC3, pack11, Lpack11.CCC3;, null, 39}" + ; + assertResults(expected, requestor.getResults()); + } finally { + deleteProject(project1); + } +} + +public void test540591_withoutPrefix() throws Exception { + IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9"); + try { + project1.open(null); + createTypePlus("/Completion9_1/src/", "pack11", "IService", "", false /* isClass */, true /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC", "implements pack11.IService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "AbstractService", "implements pack11.IService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC2", "extends pack11.AbstractService", true /* isClass */, false /* createFolder */); + createTypePlus("/Completion9_1/src/", "pack11", "CCC3", "extends pack11.AbstractService", true /* isClass */, false /* createFolder */); + + String filePath1 = "/Completion9_1/src/module-info.java"; + String completeBehind = "with "; + String fileContent1 = "module first {\n" + + "provides pack11.IService " + completeBehind + + "}\n"; + createFile(filePath1, fileContent1); + addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project1.close(); // sync + project1.open(null); + + int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length(); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); + + ICompilationUnit unit = getCompilationUnit(filePath1); + unit.codeComplete(cursorLocation, requestor); + + String expected = "AbstractService[TYPE_REF]{pack11.AbstractService, pack11, Lpack11.AbstractService;, null, 39}\n" + + "CCC[TYPE_REF]{pack11.CCC, pack11, Lpack11.CCC;, null, 39}\n" + + "CCC2[TYPE_REF]{pack11.CCC2, pack11, Lpack11.CCC2;, null, 39}\n" + + "CCC3[TYPE_REF]{pack11.CCC3, pack11, Lpack11.CCC3;, null, 39}\n"+ + "pack11[PACKAGE_REF]{pack11, pack11, null, null, 39}" + ; + + + assertResults(expected, requestor.getResults()); + } finally { + deleteProject(project1); + } +} + public void test527099_001() throws Exception { IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9"); IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9"); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java index db08a3384d..ed654f7d49 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2018 IBM Corporation and others. + * Copyright (c) 2017, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -794,7 +794,7 @@ public class Java9ElementTests extends AbstractJavaModelTests { IPath path = rawClasspath[i].getPath(); if (path.lastSegment().equals("jrt-fs.jar")) { path = path.removeLastSegments(2).append("jmods").append("java.base.jmod"); - IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base")); + IClasspathEntry newEntry = newModularLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base")); rawClasspath[i] = newEntry; } } @@ -849,7 +849,7 @@ public class Java9ElementTests extends AbstractJavaModelTests { IPath path = rawClasspath[i].getPath(); if (path.lastSegment().equals("jrt-fs.jar")) { path = path.removeLastSegments(2).append("jmods").append("java.base.jmod"); - IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base")); + IClasspathEntry newEntry = newModularLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base")); rawClasspath[i] = newEntry; } } @@ -976,7 +976,7 @@ public class Java9ElementTests extends AbstractJavaModelTests { "public class C {\n" + "}" }; - addLibrary(javaProject, "mod.one.jar", "mod.onesrc.zip", pathAndContents, JavaCore.VERSION_9); + addModularLibrary(javaProject, "mod.one.jar", "/Test/mod.onesrc.zip", pathAndContents, JavaCore.VERSION_9); // search self module: IModuleDescription modTest = javaProject.findModule("test", null); @@ -1585,7 +1585,7 @@ public class Java9ElementTests extends AbstractJavaModelTests { if (path.lastSegment().equals("jrt-fs.jar")) { jdkRootPath = path.removeLastSegments(2); path = jdkRootPath.append("jmods").append("java.base.jmod"); - IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base")); + IClasspathEntry newEntry = newModularLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base")); rawClasspath[i] = newEntry; } } @@ -1636,33 +1636,31 @@ public class Java9ElementTests extends AbstractJavaModelTests { } public void testBug530402b() throws CoreException, IOException { try { - IJavaProject project = createJavaProject("Java9Elements", - new String[] {"src"}, - new String[] {"JCL19_LIB", "/Java9Elements/lib530402.jar"}, - "bin", - "9"); + IJavaProject project = createJava9Project("Java9Elements"); + IPath libPath = project.getProject().getLocation().append("lib530402.jar"); createJar(new String[] { "module-info.java", "@Deprecated module M {}\n" }, - project.getProject().getLocation().append("lib530402.jar").toOSString(), + libPath.toOSString(), new String[] {}, "9"); + addModularLibraryEntry(project, libPath, null); project.getProject().refreshLocal(2, null); project.open(null); - String fileContent = - "module my.mod {\n" + - " requires M;\n" + - "}"; - createFile( "/Java9Elements/src/module-info.java", fileContent); + String fileContent = + "module my.mod {\n" + + " requires M;\n" + + "}"; + createFile( "/Java9Elements/src/module-info.java", fileContent); - ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java"); - int offsetToSql = fileContent.indexOf("M"); - IJavaElement[] selectedElements = unit.codeSelect(offsetToSql, "M".length()); - IModuleDescription module = (IModuleDescription) selectedElements[0]; - IAnnotation[] annotations = module.getAnnotations(); - assertEquals("should have one annotation", 1, annotations.length); - assertEquals("annotation name", "java.lang.Deprecated", annotations[0].getElementName()); + ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java"); + int offsetToSql = fileContent.indexOf("M"); + IJavaElement[] selectedElements = unit.codeSelect(offsetToSql, "M".length()); + IModuleDescription module = (IModuleDescription) selectedElements[0]; + IAnnotation[] annotations = module.getAnnotations(); + assertEquals("should have one annotation", 1, annotations.length); + assertEquals("annotation name", "java.lang.Deprecated", annotations[0].getElementName()); } finally { deleteProject("Java9Elements"); @@ -1671,7 +1669,7 @@ public class Java9ElementTests extends AbstractJavaModelTests { public void test530653() throws CoreException, IOException { try { IJavaProject project = createJava9Project("Java9Elements"); - addLibrary(project, "lib530653.jar", "lib530653src.zip", new String[] { + addModularLibrary(project, "lib530653.jar", "lib530653src.zip", new String[] { "module-info.java", "/** @category library */\n" + "module M {}\n" diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java index 770f241fc2..cc08ea50ff 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java @@ -40,6 +40,7 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; @@ -806,7 +807,11 @@ public class JavaSearchBugsTests2 extends AbstractJavaSearchTests { if ("macosx".equals(System.getProperty("osgi.os"))) { return; } - assertUTF8Encoding(); + String os = Platform.getOS(); + if (!Platform.OS_WIN32.equals(os)) { + // on Windows we have Windows-1252 as default, *nix should use UTF-8 + assertUTF8Encoding(); + } IJavaProject p = createJavaProject("P", new String[] {}, new String[] { "/P/lib376673.jar", "JCL17_LIB" }, "", "1.7"); IPath jarPath = p.getProject().getLocation().append("lib376673.jar"); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java index 1cff4eef88..898a0be039 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java @@ -103,16 +103,12 @@ public class ModuleBuilderTests extends ModifyingResourceTests { deleteProject("P1"); } - IClasspathAttribute[] moduleAttribute() { - return new IClasspathAttribute[] { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") }; - } void addModularProjectEntry(IJavaProject project, IJavaProject depProject) throws JavaModelException { - addClasspathEntry(project, JavaCore.newProjectEntry(depProject.getPath(), null, false, moduleAttribute(), false)); + addClasspathEntry(project, newModularProjectEntry(depProject)); } - void addModularLibraryEntry(IJavaProject project, String libraryPath) throws JavaModelException { - addLibraryEntry(project, new Path(libraryPath), null, null, null, null, moduleAttribute(), false); + IClasspathEntry newModularProjectEntry(IJavaProject depProject) { + return JavaCore.newProjectEntry(depProject.getPath(), null, false, moduleAttribute(), false); } - // Test that the java.base found as a module package fragment root in the project public void test001() throws CoreException { try { @@ -193,7 +189,7 @@ public class ModuleBuilderTests extends ModifyingResourceTests { IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); sortMarkers(markers); assertMarkers("Unexpected markers", - "The import java.sql cannot be resolved\n" + + "The type java.sql.Connection is not accessible\n" + "Connection cannot be resolved to a type", markers); } finally { } @@ -300,7 +296,7 @@ public class ModuleBuilderTests extends ModifyingResourceTests { IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); sortMarkers(markers); assertMarkers("Unexpected markers", - "The import com.greetings cannot be resolved\n" + + "The type com.greetings.Main is not accessible\n" + "Main cannot be resolved", markers); } finally { @@ -593,7 +589,7 @@ public class ModuleBuilderTests extends ModifyingResourceTests { markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); sortMarkers(markers); assertMarkers("Unexpected markers", - "The import com.greetings cannot be resolved\n" + + "The type com.greetings.Main is not accessible\n" + "Main cannot be resolved", markers); } finally { deleteProject("P2"); @@ -4925,7 +4921,7 @@ public class ModuleBuilderTests extends ModifyingResourceTests { markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); sortMarkers(markers); assertMarkers("Unexpected markers in mod.two", - "The import org cannot be resolved\n" + // cannot use cyclic requires + "The type org.astro.World is not accessible\n" + // cannot use cyclic requires "Cycle exists in module dependencies, Module mod.two requires itself via mod.one\n" + "World cannot be resolved to a type", markers); @@ -6402,8 +6398,8 @@ public class ModuleBuilderTests extends ModifyingResourceTests { "----------\n" + "1. ERROR in /mod1/src/com/mod1/pack1/Dummy.java (at line 2)\n" + " import org.junit.Assert;\n" + - " ^^^\n" + - "The import org cannot be resolved\n" + + " ^^^^^^^^^^^^^^^^\n" + + "The type org.junit.Assert is not accessible\n" + "----------\n" + "2. ERROR in /mod1/src/com/mod1/pack1/Dummy.java (at line 3)\n" + " public class Dummy extends Assert {\n" + @@ -6416,7 +6412,7 @@ public class ModuleBuilderTests extends ModifyingResourceTests { IMarker[] markers = javaProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); sortMarkers(markers); assertMarkers("Unexpected markers", - "The import org cannot be resolved\n" + + "The type org.junit.Assert is not accessible\n" + "Assert cannot be resolved to a type", markers); } finally { @@ -7029,7 +7025,8 @@ public class ModuleBuilderTests extends ModifyingResourceTests { "}\n" }); IFolder libs = createFolder("/Bug540788.common/libs"); - String emfCommonPath = libs.getLocation()+"/org.eclipse.emf.common.jar"; + String emfCommonLocation = libs.getLocation()+"/org.eclipse.emf.common.jar"; + Path emfCommonPath = new Path(emfCommonLocation); Util.createJar( new String[] { "src/org/eclipse/emf/common/Foo.java", @@ -7040,9 +7037,11 @@ public class ModuleBuilderTests extends ModifyingResourceTests { null, new HashMap<>(), null, - emfCommonPath); - addModularLibraryEntry(common, emfCommonPath); - String ecorePath = libs.getLocation()+"/org.eclipse.emf.ecore.jar"; + emfCommonLocation); + addModularLibraryEntry(common, emfCommonPath, null); + + String ecoreLocation = libs.getLocation()+"/org.eclipse.emf.ecore.jar"; + Path ecorePath = new Path(ecoreLocation); Util.createJar( new String[] { "src/org/eclipse/emf/ecore/EObject.java", @@ -7053,8 +7052,8 @@ public class ModuleBuilderTests extends ModifyingResourceTests { null, new HashMap<>(), null, - ecorePath); - addModularLibraryEntry(common, ecorePath); + ecoreLocation); + addModularLibraryEntry(common, ecorePath, null); // project vulkan: IJavaProject vulkan = createJava9Project("Bug540788.vulkan", new String[] { "src/main/java" }); createSourceFiles(vulkan, @@ -7075,8 +7074,8 @@ public class ModuleBuilderTests extends ModifyingResourceTests { "}\n", }); addModularProjectEntry(vulkan, common); - addModularLibraryEntry(vulkan, emfCommonPath); - addModularLibraryEntry(vulkan, ecorePath); + addModularLibraryEntry(vulkan, emfCommonPath, null); + addModularLibraryEntry(vulkan, ecorePath, null); // project vulkan.demo IJavaProject vulkan_demo = createJava9Project("Bug540788.vulkan.demo", new String[] { "src/main/java" }); createSourceFiles(vulkan_demo, @@ -7094,8 +7093,8 @@ public class ModuleBuilderTests extends ModifyingResourceTests { }); addModularProjectEntry(vulkan_demo, vulkan); addModularProjectEntry(vulkan_demo, common); - addModularLibraryEntry(vulkan_demo, emfCommonPath); - addModularLibraryEntry(vulkan_demo, ecorePath); + addModularLibraryEntry(vulkan_demo, emfCommonPath, null); + addModularLibraryEntry(vulkan_demo, ecorePath, null); getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); IMarker[] markers = vulkan_demo.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); @@ -7512,6 +7511,436 @@ public class ModuleBuilderTests extends ModifyingResourceTests { deleteProject(java10Project); } } + public void testBug543392a() throws Exception { + bug543392(null); + } + public void testBug543392b() throws Exception { + // put other on the *modulepath*: + IClasspathAttribute[] attrs = { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") }; + bug543392(attrs); + } + void bug543392(IClasspathAttribute[] dependencyAttrs) throws Exception { + IJavaProject other = createJava9Project("other"); + IJavaProject current = createJava9Project("current"); + try { + createFile("other/src/module-info.java", + "module other {\n" + + " exports other.p;\n" + + "}\n"); + createFolder("other/src/other/p"); + createFile("other/src/other/p/C.java", + "package other.p;\n" + + "public class C {}\n"); + + addClasspathEntry(current, + JavaCore.newProjectEntry(other.getProject().getFullPath(), null, false, dependencyAttrs, false)); // dependency, but .. + createFile("current/src/module-info.java", "module current {}\n"); // ... no 'requires'! + createFolder("current/src/current"); + + String test1path = "current/src/current/Test1.java"; + String test1source = + "package current;\n" + + "import other.p.C;\n" + + "public class Test1 {\n" + + "}\n"; + createFile(test1path, test1source); + String test2path = "current/src/current/Test2.java"; + String test2source = + "package current;\n" + + "public class Test2 {\n" + + " other.p.C c;\n" + + "}\n"; + createFile(test2path, test2source); + + getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + IMarker[] markers = current.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + sortMarkers(markers); + assertMarkers("Unexpected markers", + "The type other.p.C is not accessible\n" + + "The type other.p.C is not accessible", + markers); + + char[] sourceChars = test1source.toCharArray(); + this.problemRequestor.initialize(sourceChars); + getCompilationUnit(test1path).getWorkingCopy(this.wcOwner, null); + assertProblems("unexpected problems", + "----------\n" + + "1. ERROR in /current/src/current/Test1.java (at line 2)\n" + + " import other.p.C;\n" + + " ^^^^^^^^^\n" + + "The type other.p.C is not accessible\n" + + "----------\n", + this.problemRequestor); + sourceChars = test2source.toCharArray(); + this.problemRequestor.initialize(sourceChars); + getCompilationUnit(test2path).getWorkingCopy(this.wcOwner, null); + assertProblems("unexpected problems", + "----------\n" + + "1. ERROR in /current/src/current/Test2.java (at line 3)\n" + + " other.p.C c;\n" + + " ^^^^^^^^^\n" + + "The type other.p.C is not accessible\n" + + "----------\n", + this.problemRequestor); + } finally { + deleteProject(other); + deleteProject(current); + } + } + public void testBug541328() throws Exception { + IJavaProject pa = createJava9Project("m.a"); + IJavaProject pb = createJava9Project("m.b"); + IJavaProject test = createJava9Project("test"); + try { + createFolder("m.a/src/a/foo"); + createFile("m.a/src/a/foo/Bar.java", "package a.foo;\n public class Bar {}\n"); + createFile("m.a/src/module-info.java", + "module m.a {\n" + + " exports a.foo to m.b;\n" + + "}\n"); + createFile("m.b/src/module-info.java", + "module m.b {\n" + + " requires m.a;\n" + + " exports b;\n" + + "}\n"); + createFolder("m.b/src/b"); + createFile("m.b/src/b/Boo.java", + "package b;\n" + + "import a.foo.Bar;\n" + + "public class Boo extends Bar {}\n"); + addModularProjectEntry(pb, pa); + + IClasspathAttribute[] forceExport = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "m.a/a.foo=ALL-UNNAMED") + }; + addClasspathEntry(test, JavaCore.newProjectEntry(pa.getPath(), null, false, forceExport, false)); + addModularProjectEntry(test, pb); + + String testSource = + "import a.foo.Bar;\n" + + "import b.Boo;\n" + + "public class Test {\n" + + " Bar b = new Boo();\n" + + "}\n"; + String testPath = "test/src/Test.java"; + createFile(testPath, testSource); + getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + assertNoErrors(); + + this.problemRequestor.initialize(testSource.toCharArray()); + getCompilationUnit(testPath).getWorkingCopy(this.wcOwner, null); + assertProblems("unexpected problems", + "----------\n" + + "----------\n", + this.problemRequestor); + } finally { + deleteProject(pa); + deleteProject(pb); + deleteProject(test); + } + } + public void testBug543195() throws CoreException { + IJavaProject pj1 = createJava9Project("p1"); + IJavaProject pj2 = createJava9Project("p2"); + IJavaProject ptest = createJava9Project("ptest"); + try { + addModularProjectEntry(pj2, pj1); + addModularProjectEntry(ptest, pj2); + + createFolder("p1/src/p"); + createFile("p1/src/p/Missing.java", + "package p;\n" + + "public class Missing {\n" + + " public void miss() {}\n" + + "}\n"); + createFile("p1/src/module-info.java", + "module p1 {\n" + + " exports p;\n" + + "}\n"); + + createFolder("p2/src/q"); + createFile("p2/src/q/API.java", + "package q;\n" + + "public class API extends p.Missing {}\n"); + createFile("p2/src/q/API2.java", + "package q;\n" + + "public class API2 extends API {}\n"); + createFile("p2/src/module-info.java", + "module p2 {\n" + + " requires p1;\n" + + " exports q;\n" + + "}\n"); + getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + + deleteFile("p1/bin/p/Missing.class"); + pj1.getProject().close(null); + + createFolder("ptest/src/p/r"); + createFile("ptest/src/p/r/P.java", "package p.r;\n public class P {}\n"); + createFolder("ptest/src/t"); + createFile("ptest/src/t/Test1.java", + "package t;\n" + + "import q.API2;\n" + + "public class Test1 {\n" + + " void m(API2 a) {\n" + + " a.miss();\n" + + " }\n" + + "}\n"); + String test2Path = "ptest/src/t/Test2.java"; + String test2Content = + "package t;\n" + + "import p.Missing;\n" + + "public class Test2 {}\n"; + createFile(test2Path, test2Content); + ptest.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + IMarker[] markers = ptest.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + sortMarkers(markers); + assertMarkers("unexpected markers", + "The import p.Missing cannot be resolved\n" + + "The method miss() is undefined for the type API2", + markers); + + this.problemRequestor.initialize(test2Content.toCharArray()); + getCompilationUnit(test2Path).getWorkingCopy(this.wcOwner, null); + assertProblems("unexpected problems", + "----------\n" + + "1. ERROR in /ptest/src/t/Test2.java (at line 2)\n" + + " import p.Missing;\n" + + " ^^^^^^^^^\n" + + "The import p.Missing cannot be resolved\n" + + "----------\n", + this.problemRequestor); + } finally { + deleteProject(pj1); + deleteProject(pj2); + deleteProject(ptest); + } + } + + public void testBug543701() throws Exception { + IJavaProject p = createJava9Project("p"); + String outputDirectory = Util.getOutputDirectory(); + try { + String jar1Path = outputDirectory + File.separator + "lib1.jar"; + Util.createJar(new String[] { + "javax/xml/transform/Result.java", + "package javax.xml.transform;\n" + + "public class Result {}\n" + }, new HashMap<>(), jar1Path); + + String jar2Path = outputDirectory + File.separator + "lib2.jar"; + Util.createJar(new String[] { + "p2/C2.java", + "package p2;\n" + + "import javax.xml.transform.Result;\n" + + "public class C2 {\n" + + " public void m(Number n) {}\n" + + " public void m(Result r) {}\n" + // Result will be ambiguous looking from project 'p', but should not break compilation + "}\n" + }, new HashMap<>(), jar2Path); + + addLibraryEntry(p, jar1Path, false); + addLibraryEntry(p, jar2Path, false); + + createFolder("p/src/pp"); + String testPath = "p/src/pp/Test.java"; + String testSource = + "package pp;\n" + + "import p2.C2;\n" + + "public class Test {\n" + + " void test(C2 c2) {\n" + + " c2.m(Integer.valueOf(1));\n" + + " }\n" + + "}\n"; + createFile(testPath, testSource); + + p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + assertNoErrors(); + + this.problemRequestor.initialize(testSource.toCharArray()); + getCompilationUnit(testPath).getWorkingCopy(this.wcOwner, null); + assertProblems("unexpected problems", + "----------\n" + + "----------\n", + this.problemRequestor); + } finally { + deleteProject(p); + // clean up output dir + File outputDir = new File(outputDirectory); + if (outputDir.exists()) + Util.flushDirectoryContent(outputDir); + } + } + + public void testBug543441() throws Exception { + // unsuccessful attempt at triggering NPE on null required module + IJavaProject p = createJava9Project("p"); + String outputDirectory = Util.getOutputDirectory(); + try { + String jar1Path = outputDirectory + File.separator + "lib1.jar"; + Util.createJar(new String[] { + "module-info.java", + "module lib1 {}\n" + }, jar1Path, "9"); + + String jar2Path = outputDirectory + File.separator + "lib2.jar"; + Util.createJar(new String[] { + "module-info.java", + "module lib2 {\n" + + " requires lib1;\n" + // will be messing when seen from project 'p' + " exports p2;\n" + + "}\n", + "p2/C2.java", + "package p2;\n" + + "public class C2 {}\n" + }, + null, jar2Path, new String[] { jar1Path }, "9"); + + File jar1File = new File(jar1Path); + jar1File.delete(); + + addModularLibraryEntry(p, new Path(jar2Path), null); + createFile("p/src/module-info.java", + "module p {\n" + + " requires transitive lib2;\n" + // not lib1 + "}\n"); + createFolder("p/src/pkg"); + createFile("p/src/pkg/Test.java", + "package pkg;\n" + + "import p2.C2;\n" + + "public class Test {\n" + + " void test(C2 c) {}\n" + + "}\n"); + + p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + assertNoErrors(); + + } finally { + deleteProject(p); + File outputDir = new File(outputDirectory); + if (outputDir.exists()) + Util.flushDirectoryContent(outputDir); + } + } + + public void testBug543765() throws CoreException, IOException { + // failure never seen in this test + IJavaProject m = createJava9Project("M"); + IJavaProject n = createJava9Project("N"); + IJavaProject x = createJava9Project("X"); + IJavaProject y = createJava9Project("Y"); + String outputDirectory = Util.getOutputDirectory(); + try { + // ------ W ------ + String wJarLocation = outputDirectory + File.separator + "w-0.0.1-SNAPSHOT.jar"; + IPath wJarPath = new Path(wJarLocation); + Util.createJar(new String[] { + "external/W.java", + "public class W {\n" + + " public static void main(String... args) {}\n" + + "}\n" + }, wJarLocation, "9"); + + // ------ X ------ + addModularLibraryEntry(x, wJarPath, null); + createFolder("X/src/com/example/x"); + createFile("X/src/com/example/x/X.java", + "package com.example.x;\n" + + "public class X {\n" + + " public static void main(String[] args) { \n" + + " System.out.println(\"X\");\n" + + " }\n" + + "}\n"); + createFile("X/src/module-info.java", + "open module com.example.x {\n" + + " exports com.example.x;\n" + + " requires w;\n" + + "}\n"); + + // ------ Y ------ + addModularLibraryEntry(y, wJarPath, null); + addModularProjectEntry(y, x); + createFolder("Y/src/com/example/y"); + createFile("Y/src/com/example/y/Y.java", + "package com.example.y;\n" + + "public class Y {\n" + + " public static void main(String[] args) { \n" + + " System.out.println(\"Y\");\n" + + " }\n" + + "}\n"); + createFile("Y/src/module-info.java", + "open module com.example.y {\n" + + " exports com.example.y;\n" + + " requires com.example.x;\n" + + "}\n"); + + // ------ N ------ + createFolder("N/src/com/example/n"); + createFile("N/src/com/example/n/N.java", + "package com.example.n;\n" + + "public class N {\n" + + " public static void main(String[] args) { \n" + + " System.out.println(\"N\");\n" + + " } \n" + + "}\n"); + createFile("N/src/module-info.java", + "open module n {\n" + + " exports com.example.n;\n" + + "}\n"); + + // ------ M ------ + // insert new entries before JRE: + IClasspathEntry[] entries = m.getRawClasspath(); + int length = entries.length; + System.arraycopy(entries, 0, entries = new IClasspathEntry[length + 4], 4, length); + entries[0] = entries[4]; + entries[1] = newModularLibraryEntry(wJarPath, null, null); + entries[2] = newModularProjectEntry(n); + entries[3] = newModularProjectEntry(x); + entries[4] = newModularProjectEntry(y); + m.setRawClasspath(entries, null); + + createFolder("M/src/m"); + String mSource = + "package m;\n" + + "import com.example.n.N;\n" + + "public class M {\n" + + " public static void main(String[] args) {\n" + + " System.out.println(\"M\");\n" + + " N.main(null);\n" + + " }\n" + + "}\n"; + String mPath = "M/src/m/M.java"; + createFile(mPath, mSource); + createFile("M/src/module-info.java", + "open module m {\n" + + " requires n;\n" + + " requires w;\n" + + "}\n"); + + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + assertNoErrors(); + + m.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + assertNoErrors(); + + this.problemRequestor.initialize(mSource.toCharArray()); + getCompilationUnit(mPath).getWorkingCopy(this.wcOwner, null); + assertProblems("unexpected problems", + "----------\n" + + "----------\n", + this.problemRequestor); + } finally { + deleteProject(m); + deleteProject(n); + deleteProject(x); + deleteProject(y); + File outputDir = new File(outputDirectory); + if (outputDir.exists()) + Util.flushDirectoryContent(outputDir); + } + } protected void assertNoErrors() throws CoreException { for (IProject p : getWorkspace().getRoot().getProjects()) { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java index c483da872e..d6777cb46d 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java @@ -963,4 +963,44 @@ public class NullAnnotationModelTests extends ReconcilerTests { deleteProject(project); } } + public void testBug543304() throws Exception { + IJavaProject annotations = createJavaProject("Annotations", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "1.8"); + IJavaProject client = createJavaProject("Client", new String[] {"src"}, new String[] {"JCL17_LIB"}, "bin", "1.7"); + try { + createFolder("Annotations/src/p"); + createFile("Annotations/src/p/NonNull.java", + "package p;\n" + + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Target({METHOD, PARAMETER, FIELD, TYPE_USE})\n" + + "public @interface NonNull {}\n"); + createFile("Annotations/src/p/Nullable.java", + "package p;\n" + + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Target({METHOD, PARAMETER, FIELD, TYPE_USE})\n" + + "public @interface Nullable {}\n"); + + addClasspathEntry(client, JavaCore.newProjectEntry(annotations.getPath())); + client.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "p.NonNull"); + client.setOption(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "p.Nullable"); + client.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED); + + createFile("Client/src/Test.java", + "import p.*;\n" + + "public class Test {\n" + + " @Nullable int[] ints = null;\n" + + " public @NonNull Object foo(@NonNull byte[] data) {\n" + + " return data;\n" + + " }\n" + + "}\n"); + + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = client.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", "", markers); + } finally { + deleteProject(annotations); + deleteProject(client); + } + } } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests9.java index 9a72d96b4a..0386f57d44 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests9.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests9.java @@ -87,9 +87,10 @@ public class NullAnnotationModelTests9 extends ReconcilerTests { " public String id(String in) { return in; }\n" + "}\n"); - p2 = createJavaProject("mod.two", new String[] {"src"}, new String[] {"JCL19_LIB", this.ANNOTATION_LIB}, "bin", "9"); + p2 = createJavaProject("mod.two", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9"); IClasspathAttribute[] attr = { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") }; addClasspathEntry(p2, JavaCore.newProjectEntry(p.getPath(), null, false, attr, false)); + addClasspathEntry(p2, JavaCore.newLibraryEntry(new Path(this.ANNOTATION_LIB), null, null, null, attr, false)); p2.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED); createFolder("/mod.two/src/client"); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java index 919c45ef17..16166b5a8d 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -449,5 +449,125 @@ public void testBug540541() throws CoreException, IOException { JavaCore.setOptions(options); } } +public void testBug543092() throws Exception { + if (!isJRE9) { + System.err.println("Test "+getName()+" requires a JRE 9"); + return; + } + IJavaProject p = null; + try { + // ---- module log: + // - has log4j on the module path + p = createJava9ProjectWithJREAttributes("p", new String[] {"src"}, + new IClasspathAttribute[] {JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")}); + String jarAbsPath = p.getProject().getLocation()+"/lib-modular.jar"; + createJar(new String[] { + "module-info.java", + "module lib {\n" + + " exports lib.lab;\n" + + "}\n", + "lib/lab/Lib.java", + "package lib.lab;\n" + + "public class Lib {}\n" + }, + jarAbsPath, + null, + "9"); + addLibraryEntry(p, new Path(jarAbsPath), false); + + String jarAbsPath2 = p.getProject().getLocation()+"/lib-nonmodular.jar"; + createJar(new String[] { + "lib/lab/Lib.java", + "package lib.lab;\n" + + "public class Lib {}\n", + }, + jarAbsPath2); + addLibraryEntry(p, new Path(jarAbsPath2), false); + + createFolder("p/src/test"); + createFile("p/src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " lib.lab.Lib lob;\n" + + "}\n"); + p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("markers in p", + "", + markers); + + this.workingCopy = getCompilationUnit("p/src/test/Test.java").getWorkingCopy(this.wcOwner, null); + this.problemRequestor.initialize(this.workingCopy.getSource().toCharArray()); + this.workingCopy.reconcile(AST_INTERNAL_JLS11, true, this.wcOwner, null); + assertProblems("Expecting no problems", + "----------\n" + + "----------\n", + this.problemRequestor); + + } finally { + deleteProject(p); + } +} +public void testBug543092b() throws Exception { + if (!isJRE9) { + System.err.println("Test "+getName()+" requires a JRE 9"); + return; + } + IJavaProject p = null; + try { + // ---- module log: + // - has log4j on the module path + IClasspathAttribute[] moduleAttributes = new IClasspathAttribute[] {JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")}; + p = createJava9ProjectWithJREAttributes("p", new String[] {"src"}, moduleAttributes); + String jarAbsPath = p.getProject().getLocation()+"/lib-modular.jar"; + createJar(new String[] { + "module-info.java", + "module lib {\n" + + " exports lib.lab;\n" + + "}\n", + "lib/lab/Lib.java", + "package lib.lab;\n" + + "public class Lib {}\n" + }, + jarAbsPath, + null, + "9"); + addLibraryEntry(p, new Path(jarAbsPath), null, null, null, null, moduleAttributes, false); + String jarAbsPath2 = p.getProject().getLocation()+"/lib-nonmodular.jar"; + createJar(new String[] { + "lib/lab/Lib.java", + "package lib.lab;\n" + + "public class Lib {}\n", + }, + jarAbsPath2); + addLibraryEntry(p, new Path(jarAbsPath2), false); + + createFolder("p/src/test"); + createFile("p/src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " lib.lab.Lib lob;\n" + + "}\n"); + p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("markers in p", + "The package lib.lab is accessible from more than one module: <unnamed>, lib", + markers); + + this.workingCopy = getCompilationUnit("p/src/test/Test.java").getWorkingCopy(this.wcOwner, null); + this.problemRequestor.initialize(this.workingCopy.getSource().toCharArray()); + this.workingCopy.reconcile(AST_INTERNAL_JLS11, true, this.wcOwner, null); + assertProblems("Expecting no problems", + "----------\n" + + "1. ERROR in /p/src/test/Test.java (at line 3)\n" + + " lib.lab.Lib lob;\n" + + " ^^^^^^^\n" + + "The package lib.lab is accessible from more than one module: <unnamed>, lib\n" + + "----------\n", + this.problemRequestor); + } finally { + deleteProject(p); + } +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java index 97c91ab4b4..47a4613851 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java @@ -2330,8 +2330,8 @@ public class ASTRewritingExpressionsTest extends ASTRewritingTest { buf.append("}\n"); assertEqualString(preview, buf.toString()); - this.project1.setOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); - this.project1.setOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.DO_NOT_INSERT); + this.project1.setOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); + this.project1.setOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.DO_NOT_INSERT); preview= evaluateRewrite(cu, rewrite); diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/A_out.java new file mode 100644 index 0000000000..c29bd823b5 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/A_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4 + -9; + int b = a++/ --number; + b = (a++)/ (--number) + (-9); + String d = "a = " + a; + if (a == b && a > c) + c += (a << 5)& 0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/B_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/B_out.java new file mode 100644 index 0000000000..ed2e6b94b2 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/B_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4 +-9; + int b = a++ /--number; + b = (a++) /(--number) +(-9); + String d = "a = " + a; + if (a == b && a > c) + c += (a << 5) & 0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/C_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/C_out.java new file mode 100644 index 0000000000..995b4c0278 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/C_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4+ -9; + int b = a++ / --number; + b = (a++) / (--number)+ (-9); + String d = "a = " + a; + if (a == b&& a > c) + c += (a << 5) & 0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/D_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/D_out.java new file mode 100644 index 0000000000..b1f1f5d646 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/D_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4 + -9; + int b = a++ / --number; + b = (a++) / (--number) + (-9); + String d = "a = "+ a; + if (a == b && a > c) + c += (a << 5) &0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/E_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/E_out.java new file mode 100644 index 0000000000..d4806b2ea6 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/E_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4 + -9; + int b = a++ / --number; + b = (a++) / (--number) + (-9); + String d = "a = " +a; + if (a == b && a > c) + c += (a<< 5) & 0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/F_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/F_out.java new file mode 100644 index 0000000000..62247c46f7 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/F_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4 + -9; + int b = a++ / --number; + b = (a++) / (--number) + (-9); + String d = "a = " + a; + if (a ==b && a >c) + c += (a <<5) & 0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/G_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/G_out.java new file mode 100644 index 0000000000..37958f9a20 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/G_out.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list = new ArrayList(); + int a = -4 + -9; + int b = a++ / --number; + b = (a++) / (--number) + (-9); + String d = "a = " + a; + if (a== b &&a> c) + c += (a << 5) & 0xFF; + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/in.java new file mode 100644 index 0000000000..ddea756db3 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test159565/in.java @@ -0,0 +1,11 @@ +class C { + void f() { + List list=new ArrayList(); + int a=-4+-9; + int b=a++/--number; + b=(a++)/(--number)+(-9); + String d="a = "+a; + if (a==b&&a>c) + c+=(a<<5)&0xFF; + } +}
\ No newline at end of file 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 f2b428d9b6..099d883256 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -41,6 +41,7 @@ import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.ITypeHierarchy; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -12018,7 +12019,33 @@ public final class CompletionEngine if (answer != null ) { if (answer.isSourceType()) { IType typeHandle = ((SourceTypeElementInfo) answer.getSourceTypes()[0]).getHandle(); - pattern = SearchPattern.createPattern(typeHandle, IJavaSearchConstants.IMPLEMENTORS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); + try { + ArrayList<IType> allTypes = new ArrayList<IType>(); + ITypeHierarchy newTypeHierarchy = typeHandle.newTypeHierarchy(this.javaProject, null); + IType[] implementingClasses = newTypeHierarchy.getImplementingClasses(typeHandle); + for (IType iClass : implementingClasses) { + getAllTypesInHierarchy(newTypeHierarchy,iClass,allTypes); + } + for (IType iType : allTypes) { + String pkg = iType.getPackageFragment().getElementName(); + String name = iType.getElementName(); + if ( CharOperation.ALL_PREFIX != this.completionToken) { + if(!CharOperation.prefixEquals(this.completionToken, name.toCharArray(), false)) + if(!CharOperation.prefixEquals(this.completionToken, pkg.toCharArray(), false)) + continue; + } + this.acceptType(pkg.toCharArray(), name.toCharArray(), CharOperation.NO_CHAR_CHAR, iType.getFlags(), null); + acceptTypes(scope); + } + if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { + checkCancel(); + findPackagesInCurrentModule(); + } + return; + + } catch (JavaModelException e) { + // + } } else if (answer.isBinaryType()) { String typeName = new String(CharOperation.replaceOnCopy(answer.getBinaryType().getName(), '/', '.')); pattern = SearchPattern.createPattern(typeName, @@ -12097,6 +12124,16 @@ public final class CompletionEngine } } + private void getAllTypesInHierarchy(ITypeHierarchy newTypeHierarchy, IType iClass, ArrayList<IType> allTypes) { + allTypes.add(iClass); + IType[] subclasses = newTypeHierarchy.getSubclasses(iClass); + for (IType iType2 : subclasses) { + getAllTypesInHierarchy(newTypeHierarchy,iType2,allTypes); + + } + + } + private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) { final TypeReference type = variable.type; if(type != null && diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java index 5976850032..9127dc9511 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java @@ -1439,8 +1439,13 @@ public final class SelectionEngine extends Engine implements ISearchRequestor { @Override public boolean visit( LocalDeclaration localDeclaration, BlockScope scope) { - if (localDeclaration.type instanceof SingleTypeReference && ((SingleTypeReference)localDeclaration.type).token == assistIdentifier) - throw new SelectionNodeFound(localDeclaration.binding.type); + if (localDeclaration.type instanceof SingleTypeReference && ((SingleTypeReference)localDeclaration.type).token == assistIdentifier) { + if(localDeclaration.binding != null) { + throw new SelectionNodeFound(localDeclaration.binding.type); + } else { + throw new SelectionNodeFound(); + } + } return true; // do nothing by default, keep traversing } @Override diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java index 6e2fb89be3..7710fcfdee 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -591,7 +591,7 @@ public MethodBinding inferConstructorOfElidedParameterizedType(final Scope scope if (this.expressionContext == INVOCATION_CONTEXT && this.typeExpected == null) constructor = ParameterizedGenericMethodBinding.computeCompatibleMethod18(constructor.shallowOriginal(), this.argumentTypes, scope, this); } - if (this.typeExpected != null) + if (this.typeExpected != null && this.typeExpected.isProperType(true)) registerResult(this.typeExpected, constructor); } return constructor; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java index c8bc57a9b5..f2b5b6e2e5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java index 8e9986241f..5b8054c57d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java @@ -361,8 +361,11 @@ public final boolean checkCastTypesCompatibility(Scope scope, TypeBinding castTy if (match == null) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); } - // recurse on the type variable upper bound - return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression); + for (TypeBinding bound : ((TypeVariableBinding) castType).allUpperBounds()) { + if (!checkCastTypesCompatibility(scope, bound, expressionType, expression)) + return false; + } + return true; default: // ( CLASS/INTERFACE ) ARRAY @@ -381,11 +384,23 @@ public final boolean checkCastTypesCompatibility(Scope scope, TypeBinding castTy case Binding.TYPE_PARAMETER : TypeBinding match = expressionType.findSuperTypeOriginatingFrom(castType); - if (match != null) { - return checkUnsafeCast(scope, castType, expressionType, match, false); + if (match == null) { + // recursively on the type variable upper bounds + if (castType instanceof TypeVariableBinding) { + // prefer iterating over required types, not provides + for (TypeBinding bound : ((TypeVariableBinding)castType).allUpperBounds()) { + if (!checkCastTypesCompatibility(scope, bound, expressionType, expression)) + return false; + } + } else { + for (TypeBinding bound : ((TypeVariableBinding)expressionType).allUpperBounds()) { + if (!checkCastTypesCompatibility(scope, castType, bound, expression)) + return false; + } + } } - // recursively on the type variable upper bound - return checkCastTypesCompatibility(scope, castType, ((TypeVariableBinding)expressionType).upperBound(), expression); + // if no incompatibility found: + return checkUnsafeCast(scope, castType, expressionType, match, match == null); case Binding.WILDCARD_TYPE : case Binding.INTERSECTION_TYPE : @@ -424,8 +439,12 @@ public final boolean checkCastTypesCompatibility(Scope scope, TypeBinding castTy if (match == null) { checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true); } - // recurse on the type variable upper bound - return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression); + // recursively on the type variable upper bounds + for (TypeBinding upperBound : ((TypeVariableBinding)castType).allUpperBounds()) { + if (!checkCastTypesCompatibility(scope, upperBound, expressionType, expression)) + return false; + } + return true; default : if (castType.isInterface()) { @@ -517,8 +536,12 @@ public final boolean checkCastTypesCompatibility(Scope scope, TypeBinding castTy if (match == null) { checkUnsafeCast(scope, castType, expressionType, null, true); } - // recurse on the type variable upper bound - return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression); + // recursively on the type variable upper bounds + for (TypeBinding upperBound : ((TypeVariableBinding)castType).allUpperBounds()) { + if (!checkCastTypesCompatibility(scope, upperBound, expressionType, expression)) + return false; + } + return true; default : if (castType.isInterface()) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java index 349406911d..08067d8306 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2018 IBM Corporation and others. + * Copyright (c) 2012, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -136,6 +136,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre protected Expression [] resultExpressions = NO_EXPRESSIONS; public InferenceContext18 inferenceContext; // when performing tentative resolve keep a back reference to the driving context private Map<Integer/*sourceStart*/, LocalTypeBinding> localTypes; // support look-up of a local type from this lambda copy + public boolean argumentsTypeVar = false; public LambdaExpression(CompilationResult compilationResult, boolean assistNode, boolean requiresGenericSignature) { @@ -247,7 +248,6 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre public TypeBinding resolveType(BlockScope blockScope, boolean skipKosherCheck) { boolean argumentsTypeElided = argumentsTypeElided(); - boolean argumentsTypeVar = argumentsTypeVar(blockScope); int argumentsLength = this.arguments == null ? 0 : this.arguments.length; if (this.constant != Constant.NotAConstant) { @@ -256,7 +256,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre if (this.original == this) this.ordinal = recordFunctionalType(blockScope); - if (!argumentsTypeElided && !argumentsTypeVar) { + if (!argumentsTypeElided) { for (int i = 0; i < argumentsLength; i++) this.argumentTypes[i] = this.arguments[i].type.resolveType(blockScope, true /* check bounds*/); } @@ -289,7 +289,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre int parametersLength = this.descriptor.parameters.length; if (parametersLength != argumentsLength) { this.scope.problemReporter().lambdaSignatureMismatched(this); - if (argumentsTypeElided || argumentsTypeVar || this.original != this) // no interest in continuing to error check copy. + if (argumentsTypeElided || this.original != this) // no interest in continuing to error check copy. return this.resolvedType = null; // FUBAR, bail out ... else { this.resolvedType = null; // continue to type check. @@ -314,7 +314,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre TypeBinding argumentType; final TypeBinding expectedParameterType = haveDescriptor && i < this.descriptor.parameters.length ? this.descriptor.parameters[i] : null; - argumentType = (argumentsTypeElided || argumentsTypeVar) ? expectedParameterType : this.argumentTypes[i]; + argumentType = argumentsTypeElided ? expectedParameterType : this.argumentTypes[i]; if (argumentType == null) { argumentsHaveErrors = true; } else if (argumentType == TypeBinding.VOID) { @@ -329,7 +329,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre } } } - if (!argumentsTypeElided && !argumentsTypeVar && !argumentsHaveErrors) { + if (!argumentsTypeElided && !argumentsHaveErrors) { ReferenceBinding groundType = null; ReferenceBinding expectedSAMType = null; if (this.expectedType instanceof IntersectionTypeBinding18) @@ -365,7 +365,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre Argument argument = this.arguments[i]; TypeBinding argumentType; final TypeBinding expectedParameterType = haveDescriptor && i < this.descriptor.parameters.length ? this.descriptor.parameters[i] : null; - argumentType = (argumentsTypeElided || argumentsTypeVar) ? expectedParameterType : this.argumentTypes[i]; + argumentType = argumentsTypeElided ? expectedParameterType : this.argumentTypes[i]; expectedParameterTypes[i] = expectedParameterType; if (argumentType != null && argumentType != TypeBinding.VOID) { if (haveDescriptor && expectedParameterType != null && argumentType.isValidBinding() && TypeBinding.notEquals(argumentType, expectedParameterType)) { @@ -396,7 +396,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre } } } - if (argumentsTypeVar) { + if (this.argumentsTypeVar) { for (int i = 0; i < argumentsLength; ++i) { this.arguments[i].type.resolvedType = expectedParameterTypes[i]; } @@ -408,7 +408,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre this.binding.setParameterAnnotations(parameterAnnotations); } - if (!argumentsTypeElided && !argumentsTypeVar && !argumentsHaveErrors && this.binding.isVarargs()) { + if (!argumentsTypeElided && !argumentsHaveErrors && this.binding.isVarargs()) { if (!this.binding.parameters[this.binding.parameters.length - 1].isReifiable()) { this.scope.problemReporter().possibleHeapPollutionFromVararg(this.arguments[this.arguments.length - 1]); } @@ -438,7 +438,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre } // TODO (stephan): else? (can that happen?) if (haveDescriptor && !argumentsHaveErrors && blockScope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) { - if (!argumentsTypeElided && !argumentsTypeVar) { + if (!argumentsTypeElided) { AbstractMethodDeclaration.createArgumentBindings(this.arguments, this.binding, this.scope); // includes validation // no application of null-ness default, hence also no warning regarding redundant null annotation mergeParameterNullAnnotations(blockScope); @@ -533,28 +533,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre @Override public boolean argumentsTypeElided() { - return this.arguments.length > 0 && this.arguments[0].hasElidedType(); - } - - private boolean argumentsTypeVar(BlockScope blockScope) { - if (blockScope.compilerOptions().complianceLevel < ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_11)) return false; - boolean retval = false, isVar = false, mixReported = false; - Argument[] args = this.arguments; - for (int i = 0, l = args.length; i < l; ++i) { - Argument arg = args[i]; - TypeReference type = arg.type; - if (type == null) continue; - boolean prev = isVar; - retval |= isVar = type.isTypeNameVar(blockScope); - if (i > 0 && prev != isVar && !mixReported) { // report only once per list - blockScope.problemReporter().varCannotBeMixedWithNonVarParams(isVar ? arg : args[i - 1]); - mixReported = true; - } - if (isVar && (type.dimensions() > 0 || type.extraDimensions() > 0)) { - blockScope.problemReporter().varLocalCannotBeArray(arg); - } - } - return retval; + return (this.arguments.length > 0 && this.arguments[0].hasElidedType()) || this.argumentsTypeVar; } private void analyzeExceptions() { @@ -710,7 +689,6 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre if (targetType == null) // assumed to signal another primary error return true; - if (argumentsTypeElided()) return false; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java index 7d70b9a053..5b74b22c5a 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -123,7 +123,7 @@ public class QualifiedTypeReference extends TypeReference { PackageBinding uniquePackage = packageBinding.getVisibleFor(scope.module(), false); if (uniquePackage instanceof SplitPackageBinding) { SplitPackageBinding splitPackage = (SplitPackageBinding) uniquePackage; - scope.problemReporter().conflictingPackagesFromModules(splitPackage, this.sourceStart, (int)this.sourcePositions[typeStart-1]); + scope.problemReporter().conflictingPackagesFromModules(splitPackage, scope.module(), this.sourceStart, (int)this.sourcePositions[typeStart-1]); this.resolvedType = new ProblemReferenceBinding(this.tokens, null, ProblemReasons.Ambiguous); return null; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java index 73e4615d54..afb99dfd62 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java @@ -18,6 +18,8 @@ * Bug 424727 - [compiler][null] NullPointerException in nullAnnotationUnsupportedLocation(ProblemReporter.java:5708) * Bug 457210 - [1.8][compiler][null] Wrong Nullness errors given on full build build but not on incremental build? * Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class + * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for + * Bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -30,6 +32,7 @@ import org.eclipse.jdt.internal.compiler.flow.*; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.parser.*; import org.eclipse.jdt.internal.compiler.problem.*; +import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray; import org.eclipse.jdt.internal.compiler.util.Util; public class TypeDeclaration extends Statement implements ProblemSeverities, ReferenceContext { @@ -745,6 +748,7 @@ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) { if (this.methods != null) { UnconditionalFlowInfo outerInfo = flowInfo.unconditionalFieldLessCopy(); FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo); + SimpleSetOfCharArray jUnitMethodSourceValues = getJUnitMethodSourceValues(); for (int i = 0, count = this.methods.length; i < count; i++) { AbstractMethodDeclaration method = this.methods[i]; if (method.ignoreFurtherInvestigation) @@ -760,6 +764,10 @@ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) { ((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode()); } } else { // regular method + // JUnit 5 only accepts methods without arguments for method sources + if (method.arguments == null && jUnitMethodSourceValues.includes(method.selector) && method.binding != null) { + method.binding.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; + } // pass down the parentContext (NOT an initializer context, see above): ((MethodDeclaration)method).analyseCode(this.scope, parentContext, flowInfo.copy()); } @@ -771,6 +779,31 @@ private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) { } } +private SimpleSetOfCharArray getJUnitMethodSourceValues() { + SimpleSetOfCharArray junitMethodSourceValues = new SimpleSetOfCharArray(); + for (AbstractMethodDeclaration methodDeclaration : this.methods) { + junitMethodSourceValues.add(getJUnitMethodSourceValue(methodDeclaration)); + } + return junitMethodSourceValues; +} + +private char[] getJUnitMethodSourceValue(AbstractMethodDeclaration methodDeclaration) { + if (methodDeclaration.annotations != null) { + for (Annotation annotation : methodDeclaration.annotations) { + if (annotation.resolvedType != null && annotation.resolvedType.id == TypeIds.T_OrgJunitJupiterParamsProviderMethodSource) { + for (MemberValuePair memberValuePair : annotation.memberValuePairs()) { + if (CharOperation.equals(memberValuePair.name, TypeConstants.VALUE)) { + return ((StringLiteral) memberValuePair.value).source; + } + } + // value member not specified (i.e. marker annotation): JUnit 5 defaults to the test method's name + return methodDeclaration.selector; + } + } + } + return CharOperation.NO_CHAR; +} + public final static int kind(int flags) { switch (flags & (ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation|ClassFileConstants.AccEnum)) { case ClassFileConstants.AccInterface : diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java index 6337561397..18903e8156 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java @@ -3073,7 +3073,7 @@ public void generateSyntheticBodyForSwitchTable(SyntheticMethodBinding methodBin } } aload_0(); - if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK9) { + if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK9 || !syntheticFieldBinding.isFinal()) { // Modifying a final field outside of the <clinit> method is not allowed in 9 dup(); fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java index 8ac3f0281c..6c4cb11224 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2018 GK Software SE, and others. + * Copyright (c) 2017, 2019 GK Software SE, and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -211,7 +211,7 @@ public class BinaryModuleBinding extends ModuleBinding { if (compoundName.length > 1) { PackageBinding parent = forcedGetExportedPackage(CharOperation.subarray(compoundName, 0, compoundName.length-1)); binding = new PackageBinding(compoundName, parent, this.environment, this); - parent.addPackage(binding, this, true); + parent.addPackage(binding, this); return binding; } binding = new PackageBinding(compoundName[0], this.environment, this); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 6e084b3634..393c864722 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -465,6 +465,8 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) { } char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4 this.tagBits |= binaryType.getTagBits(); + if (this.environment.globalOptions.complianceLevel < ClassFileConstants.JDK1_8) + this.tagBits &= ~TagBits.AnnotationForTypeUse; // avoid confusion with semantics that are not supported at 1.7- char[][][] missingTypeNames = binaryType.getMissingTypeNames(); SignatureWrapper wrapper = null; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java index aee95e635f..0199eae16c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java @@ -427,7 +427,7 @@ void faultInImports() { PackageBinding uniquePackage = ((PackageBinding)importBinding).getVisibleFor(module(), false); if (uniquePackage instanceof SplitPackageBinding) { SplitPackageBinding splitPackage = (SplitPackageBinding) uniquePackage; - problemReporter().conflictingPackagesFromModules(splitPackage, importReference.sourceStart, importReference.sourceEnd); + problemReporter().conflictingPackagesFromModules(splitPackage, module(), importReference.sourceStart, importReference.sourceEnd); continue nextImport; } } @@ -441,7 +441,7 @@ void faultInImports() { if (importBinding instanceof SplitPackageBinding) { SplitPackageBinding splitPackage = (SplitPackageBinding) importBinding; int sourceEnd = (int)(importReference.sourcePositions[splitPackage.compoundName.length-1] & 0xFFFF); - problemReporter().conflictingPackagesFromModules((SplitPackageBinding) importBinding, importReference.sourceStart, sourceEnd); + problemReporter().conflictingPackagesFromModules((SplitPackageBinding) importBinding, module(), importReference.sourceStart, sourceEnd); continue nextImport; } if (!importBinding.isValidBinding()) { @@ -472,7 +472,7 @@ void faultInImports() { if (importedPackage instanceof SplitPackageBinding) { SplitPackageBinding splitPackage = (SplitPackageBinding) importedPackage; int sourceEnd = (int) importReference.sourcePositions[splitPackage.compoundName.length-1]; - problemReporter().conflictingPackagesFromModules(splitPackage, importReference.sourceStart, sourceEnd); + problemReporter().conflictingPackagesFromModules(splitPackage, module(), importReference.sourceStart, sourceEnd); continue nextImport; } } @@ -565,7 +565,7 @@ private Binding findImport(char[][] compoundName, int length) { ReferenceBinding type; if (binding == null) { if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) - return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound); + return problemType(compoundName, i, null); type = findType(compoundName[0], this.environment.defaultPackage, this.environment.defaultPackage); if (type == null || !type.isValidBinding()) return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java index e06463c6b8..14abe12ca0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -408,7 +408,8 @@ private static NameEnvironmentAnswer fromSplitPackageOrOracle(IModuleAwareNameEn if (binding != null && binding.isValidBinding()) { if (binding instanceof UnresolvedReferenceBinding) binding = ((UnresolvedReferenceBinding) binding).resolve(module.environment, false); - return new NameEnvironmentAnswer(binding, module); + if (binding.isValidBinding()) + return new NameEnvironmentAnswer(binding, module); } } return moduleEnv.findType(name, packageBinding.compoundName, module.nameForLookup()); @@ -771,7 +772,7 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM if (isMissing) { packageBinding.tagBits |= TagBits.HasMissingType; } - packageBinding = parent.addPackage(packageBinding, this.module, true); + packageBinding = parent.addPackage(packageBinding, this.module); } } if (packageBinding instanceof SplitPackageBinding) { @@ -1121,7 +1122,7 @@ public PackageBinding createPackage(char[][] compoundName) { } if (packageBinding == null) { packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this, this.module); - packageBinding = parent.addPackage(packageBinding, this.module, true); + packageBinding = parent.addPackage(packageBinding, this.module); } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java index d6117ed47a..66e02b7a3c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2018 IBM Corporation and others. + * Copyright (c) 2016, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -325,25 +325,37 @@ public class ModuleBinding extends Binding implements IUpdatableModule { protected void recordExportRestrictions(PackageBinding exportedPackage, char[][] targetModules) { if (targetModules != null && targetModules.length > 0) { - SimpleSetOfCharArray targetModuleSet = new SimpleSetOfCharArray(targetModules.length); + SimpleSetOfCharArray targetModuleSet = null; + if (this.exportRestrictions != null) { + targetModuleSet = this.exportRestrictions.get(exportedPackage); + } else { + this.exportRestrictions = new HashMap<>(); + } + if (targetModuleSet == null) { + targetModuleSet = new SimpleSetOfCharArray(targetModules.length); + this.exportRestrictions.put(exportedPackage, targetModuleSet); + } for (int i = 0; i < targetModules.length; i++) { targetModuleSet.add(targetModules[i]); } - if (this.exportRestrictions == null) - this.exportRestrictions = new HashMap<>(); - this.exportRestrictions.put(exportedPackage, targetModuleSet); } } protected void recordOpensRestrictions(PackageBinding openedPackage, char[][] targetModules) { if (targetModules != null && targetModules.length > 0) { - SimpleSetOfCharArray targetModuleSet = new SimpleSetOfCharArray(targetModules.length); + SimpleSetOfCharArray targetModuleSet = null; + if (this.openRestrictions != null) { + targetModuleSet = this.openRestrictions.get(openedPackage); + } else { + this.openRestrictions = new HashMap<>(); + } + if (targetModuleSet == null) { + targetModuleSet = new SimpleSetOfCharArray(targetModules.length); + this.openRestrictions.put(openedPackage, targetModuleSet); + } for (int i = 0; i < targetModules.length; i++) { targetModuleSet.add(targetModules[i]); } - if (this.openRestrictions == null) - this.openRestrictions = new HashMap<>(); - this.openRestrictions.put(openedPackage, targetModuleSet); } } @@ -559,7 +571,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { if (declaredPackage != null) { // don't add foreign package to 'parent' (below), but to its own parent: if (declaredPackage.parent != null) - declaredPackage.parent.addPackage(declaredPackage, declaringModule, true); + declaredPackage.parent.addPackage(declaredPackage, declaringModule); parent = null; // binding = SplitPackageBinding.combine(declaredPackage, binding, this); @@ -579,15 +591,19 @@ public class ModuleBinding extends Binding implements IUpdatableModule { binding = combineWithPackagesFromOtherRelevantModules(binding, subPkgCompoundName, declaringModuleNames); } if (binding == null || !binding.isValidBinding()) { - if (parent != null && !packageMayBeIncomplete) // don't remember package that may still lack some siblings + if (parent != null + && !packageMayBeIncomplete // don't remember package that may still lack some siblings + && !(parent instanceof SplitPackageBinding)) // don't store problem into SPB, because from different focus things may look differently + { parent.knownPackages.put(name, binding == null ? LookupEnvironment.TheNotFoundPackage : binding); + } return null; } // remember if (parentName.length == 0) binding.environment.knownPackages.put(name, binding); else if (parent != null) - binding = parent.addPackage(binding, this, false); + binding = parent.addPackage(binding, this); return addPackage(binding, false); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java index d7d4555f0c..4054281c71 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java @@ -86,10 +86,10 @@ private void addNotFoundType(char[] simpleName) { } /** * Remembers a sub-package. - * For a split parent package this will include enriching with siblings, if checkForSplitSiblings is true + * For a split parent package this will include potentially enriching with siblings, * in which case the enriched (split) binding will be returned. */ -PackageBinding addPackage(PackageBinding element, ModuleBinding module, boolean checkForSplitSiblings) { +PackageBinding addPackage(PackageBinding element, ModuleBinding module) { if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit(); this.knownPackages.put(element.compoundName[element.compoundName.length - 1], element); return element; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java index f7a144f39b..d40fbeb2c0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -278,7 +278,7 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin TypeBinding[] solutions = infCtx18.getSolutions(typeVariables, invocationSite, result); if (solutions != null) { methodSubstitute = scope.environment().createParameterizedGenericMethod(originalMethod, solutions, infCtx18.usesUncheckedConversion, hasReturnProblem, expectedType); - if (invocationSite instanceof Invocation && allArgumentsAreProper) + if (invocationSite instanceof Invocation && allArgumentsAreProper && (expectedType == null || expectedType.isProperType(true))) infCtx18.forwardResults(result, (Invocation) invocationSite, methodSubstitute, expectedType); try { if (hasReturnProblem) { // illegally working from the provisional result? diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index 90e9f6757c..48f8cbeef5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -45,6 +45,8 @@ * bug 527554 - [18.3] Compiler support for JEP 286 Local-Variable Type * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for * bug 386692 - Missing "unused" warning on "autowired" fields + * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for + * bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -889,6 +891,14 @@ public void computeId() { } return; } + if (CharOperation.equals(TypeConstants.JUNIT, this.compoundName[1])) { + if (CharOperation.equals(TypeConstants.METHOD_SOURCE, this.compoundName[5])) { + if (CharOperation.equals(TypeConstants.ORG_JUNIT_METHOD_SOURCE, this.compoundName)) { + this.id = TypeIds.T_OrgJunitJupiterParamsProviderMethodSource; + } + } + return; + } if (!CharOperation.equals(TypeConstants.JDT, this.compoundName[2]) || !CharOperation.equals(TypeConstants.ITYPEBINDING, this.compoundName[5])) return; if (CharOperation.equals(TypeConstants.ORG_ECLIPSE_JDT_CORE_DOM_ITYPEBINDING, this.compoundName)) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 3734dd55a3..7a085094e8 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -2970,7 +2970,7 @@ public abstract class Scope { char[][] qName = new char[][] { compoundName[0] }; return new ProblemReferenceBinding(qName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } - return binding; + return problemType(compoundName, -1, binding); } if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package @@ -2979,7 +2979,7 @@ public abstract class Scope { while (currentIndex < length) { binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<length); if (binding == null) { - return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound); + return problemType(compoundName, currentIndex, null); } if (!binding.isValidBinding() && binding.problemId() != ProblemReasons.Ambiguous) return new ProblemReferenceBinding( @@ -2993,6 +2993,29 @@ public abstract class Scope { return new ProblemReferenceBinding(compoundName, null /* no closest match since search for pkg*/, ProblemReasons.NotFound); } + /** + * Return the most suitable ProblemReferenceBinding: + * (1) previousProblem if provided and problem different from NotFound + * (2) a new NotAccessible binding + * (3) previousProblem if provided otherwise + * (4) a new NotFound binding + */ + Binding problemType(char[][] compoundName, int currentIndex, Binding previousProblem) { + if (previousProblem != null && previousProblem.problemId() != ProblemReasons.NotFound) + return previousProblem; + + LookupEnvironment environment = environment(); + if (environment.useModuleSystem && module() != environment.UnNamedModule) { + // try if the UnNamedModule can see the type: + ReferenceBinding notAccessibleType = environment.root.getType(compoundName, environment.UnNamedModule); + if (notAccessibleType != null && notAccessibleType.isValidBinding()) + return new ProblemReferenceBinding(compoundName, notAccessibleType, ProblemReasons.NotAccessible); + } + return previousProblem != null + ? previousProblem + : new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound); + } + /* Answer the package from the compoundName or null if it begins with a type. * Intended to be used while resolving a package name only. * diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java index bcd6af0a87..ee5fd9a20e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2018 GK Software AG, and others. + * Copyright (c) 2017, 2019 GK Software AG, and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -41,7 +41,7 @@ public class SourceModuleBinding extends ModuleBinding { } public void setRequires(ModuleBinding[] requires, ModuleBinding[] requiresTransitive) { - // TODO(SHMOD): it's a bit awkward that we may get called after applyModuleUpdates() has already worked. + // remember that we may get called after applyModuleUpdates() has already worked. ModuleBinding javaBase = this.environment.javaBaseModule(); this.requires = merge(this.requires, requires, javaBase, ModuleBinding[]::new); this.requiresTransitive = merge(this.requiresTransitive, requiresTransitive, null, ModuleBinding[]::new); @@ -106,18 +106,32 @@ public class SourceModuleBinding extends ModuleBinding { @Override Stream<ModuleBinding> getRequiredModules(boolean transitiveOnly) { - if (this.requires == NO_MODULES) { - this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); - } + // don't rely on "if (this.requires == NO_MODULES)" - could have been modified by completeIfNeeded() + this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); return super.getRequiredModules(transitiveOnly); } @Override public ModuleBinding[] getAllRequiredModules() { - if (this.scope != null) - this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); + // don't rely on "if (this.requires == NO_MODULES)" - could have been modified by completeIfNeeded() + this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); return super.getAllRequiredModules(); } + + @Override + public PackageBinding[] getExports() { + // don't rely on "if (this.exportedPackages == Binding.NO_PACKAGES)" - could have been modified by completeIfNeeded() + this.scope.referenceContext.moduleDeclaration.resolvePackageDirectives(this.scope); + return super.getExports(); + } + + @Override + public PackageBinding[] getOpens() { + // don't rely on "if (this.openedPackages == Binding.NO_PACKAGES)" - could have been modified by completeIfNeeded() + this.scope.referenceContext.moduleDeclaration.resolvePackageDirectives(this.scope); + return super.getOpens(); + } + @Override public long getAnnotationTagBits() { ensureAnnotationsResolved(); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index 79ad44f613..d2c525fb07 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -1310,7 +1310,7 @@ public void generateSyntheticFinalFieldInitialization(CodeStream codeStream) { return; Collection<FieldBinding> syntheticFields = this.synthetics[SourceTypeBinding.FIELD_EMUL].values(); for (FieldBinding field : syntheticFields) { - if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_SWITCH_ENUM_TABLE, field.name)) { + if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_SWITCH_ENUM_TABLE, field.name) && field.isFinal()) { MethodBinding[] accessors = (MethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(new String(field.name)); if (accessors == null || accessors[0] == null) // not a field for switch enum continue; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java index 47221fe09c..8bb5266322 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java @@ -83,22 +83,18 @@ public class SplitPackageBinding extends PackageBinding { } } } - PackageBinding addPackage(PackageBinding element, ModuleBinding module) { - return addPackage(element, module, true); - } @Override - PackageBinding addPackage(PackageBinding element, ModuleBinding module, boolean enrichWithSplitSiblings) { + PackageBinding addPackage(PackageBinding element, ModuleBinding module) { char[] simpleName = element.compoundName[element.compoundName.length-1]; // enrich - if (enrichWithSplitSiblings) - element = combineWithSiblings(element, simpleName, module); + element = combineWithSiblings(element, simpleName, module); PackageBinding visible = this.knownPackages.get(simpleName); visible = SplitPackageBinding.combine(element, visible, this.enclosingModule); this.knownPackages.put(simpleName, visible); PackageBinding incarnation = getIncarnation(element.enclosingModule); if (incarnation != null) - incarnation.addPackage(element, module, enrichWithSplitSiblings); + incarnation.addPackage(element, module); return element; } @@ -112,6 +108,8 @@ public class SplitPackageBinding extends PackageBinding { ModuleBinding moduleBinding = incarnation.enclosingModule; if (moduleBinding == module) continue; + if (childPackage.isDeclaredIn(moduleBinding)) + continue; PackageBinding next = moduleBinding.getVisiblePackage(incarnation, name, false); childPackage = combine(next, childPackage, primaryModule); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java index 47e32057f4..f3387f47fc 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java @@ -29,6 +29,8 @@ * Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for * bug 386692 - Missing "unused" warning on "autowired" fields + * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for + * bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -316,6 +318,9 @@ public interface TypeConstants { char[] JUNIT = "junit".toCharArray(); //$NON-NLS-1$ char[] FRAMEWORK = "framework".toCharArray(); //$NON-NLS-1$ + char[] JUPITER = "jupiter".toCharArray(); //$NON-NLS-1$ + char[] PARAMS = "params".toCharArray(); //$NON-NLS-1$ + char[] PROVIDER = "provider".toCharArray(); //$NON-NLS-1$ char[][] JUNIT_FRAMEWORK_ASSERT = new char[][] { JUNIT, FRAMEWORK, ASSERT_CLASS }; char[][] ORG_JUNIT_ASSERT = new char[][] { ORG, JUNIT, ASSERT_CLASS }; // ... methods: @@ -323,6 +328,9 @@ public interface TypeConstants { char[] ASSERT_NOTNULL = "assertNotNull".toCharArray(); //$NON-NLS-1$ char[] ASSERT_TRUE = "assertTrue".toCharArray(); //$NON-NLS-1$ char[] ASSERT_FALSE = "assertFalse".toCharArray(); //$NON-NLS-1$ + // ... annotations: + char[] METHOD_SOURCE = "MethodSource".toCharArray(); //$NON-NLS-1$ + char[][] ORG_JUNIT_METHOD_SOURCE = new char[][] { ORG, JUNIT, JUPITER, PARAMS, PROVIDER, METHOD_SOURCE }; char[] VALIDATE_CLASS = "Validate".toCharArray(); //$NON-NLS-1$ char[][] ORG_APACHE_COMMONS_LANG_VALIDATE = new char[][] { ORG, APACHE, COMMONS, LANG, VALIDATE_CLASS }; @@ -333,7 +341,6 @@ public interface TypeConstants { // ... methods: char[] IS_TRUE = "isTrue".toCharArray(); //$NON-NLS-1$ char[] NOT_NULL = "notNull".toCharArray(); //$NON-NLS-1$ - char[] PROVIDER = "provider".toCharArray(); //$NON-NLS-1$ char[][] COM_GOOGLE_COMMON_BASE_PRECONDITIONS = new char[][] { COM, GOOGLE, "common".toCharArray(), "base".toCharArray(), "Preconditions".toCharArray() }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java index cb3893e1b3..52c1428f80 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2018 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -18,10 +18,12 @@ * bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account * bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions * Bug 410218 - Optional warning for arguments of "unexpected" types to Map#get(Object), Collection#remove(Object) et al. - * Jesper S Moller <jesper@selskabet.org> - Contributions for + * Jesper S Moller <jesper@selskabet.org> - Contributions for * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for * bug 386692 - Missing "unused" warning on "autowired" fields + * Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for + * bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -141,6 +143,9 @@ public interface TypeIds { final int T_JavaUtilMap = 91; final int T_JavaUtilList = 92; + // @MethodSource + final int T_OrgJunitJupiterParamsProviderMethodSource = 93; + // If you add new type id, make sure to bump up T_LastWellKnownTypeId if there is a cross over. final int T_LastWellKnownTypeId = 128; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index 21a7ce03b6..bb3ca2a0b7 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -42,6 +42,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; +import java.util.Arrays; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; @@ -965,6 +966,17 @@ public class TypeVariableBinding extends ReferenceBinding { return this.superclass; // java/lang/Object } + public TypeBinding[] allUpperBounds() { + if (this.superclass == null) + return this.superInterfaces; + if (this.superInterfaces == null || this.superInterfaces.length == 0) + return new TypeBinding[] { this.superclass }; + int nInterfaces = this.superInterfaces.length; + TypeBinding[] all = Arrays.copyOf(this.superInterfaces, nInterfaces+1); + all[nInterfaces] = this.superclass; + return all; + } + public void evaluateNullAnnotations(Scope scope, TypeParameter parameter) { long nullTagBits = NullAnnotationMatching.validNullTagBits(this.tagBits); if (this.firstBound != null && this.firstBound.isValidBinding()) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java index 18558d1801..fd4246da7d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -107,10 +107,10 @@ ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericTo if (targetType == null) { char[] typeName = this.compoundName[this.compoundName.length - 1]; targetType = this.fPackage.getType0(typeName); - if (targetType == this) { //$IDENTITY-COMPARISON$ + if (targetType == this || targetType == null) { //$IDENTITY-COMPARISON$ if (this.fPackage instanceof SplitPackageBinding) // leverage SplitPackageBinding to avoid duplicate creation of BinaryTypeBinding targetType = environment.askForType(this.fPackage, typeName, this.fPackage.enclosingModule); - else + else if (targetType == this) //$IDENTITY-COMPARISON$ targetType = environment.askForType(this.compoundName, this.fPackage.enclosingModule); } if ((targetType == null || targetType == this) && CharOperation.contains('.', typeName)) { //$IDENTITY-COMPARISON$ 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 02200bb2cc..ef5bf2652f 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -947,6 +947,7 @@ private int stateStackLengthStack[] = new int[0]; protected boolean parsingJava8Plus; protected boolean parsingJava9Plus; protected boolean parsingJava12Plus; +protected boolean parsingJava11Plus; protected int unstackedAct = ERROR_ACTION; private boolean haltOnSyntaxError = false; private boolean tolerateDefaultClassMethods = false; @@ -966,6 +967,7 @@ public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) { this.parsingJava8Plus = this.options.sourceLevel >= ClassFileConstants.JDK1_8; this.parsingJava9Plus = this.options.sourceLevel >= ClassFileConstants.JDK9; this.parsingJava12Plus = this.options.sourceLevel >= ClassFileConstants.JDK12; + this.parsingJava11Plus = this.options.sourceLevel >= ClassFileConstants.JDK11; this.astLengthStack = new int[50]; this.expressionLengthStack = new int[30]; this.typeAnnotationLengthStack = new int[30]; @@ -8619,6 +8621,31 @@ protected void consumeLambdaHeader() { this.currentElement.lambdaNestLevel++; } } +private void setArgumentsTypeVar(LambdaExpression lexp) { + Argument[] args = lexp.arguments; + if (!this.parsingJava11Plus || args == null || args.length == 0) { + lexp.argumentsTypeVar = false; + return; + } + + boolean isVar = false, mixReported = false; + for (int i = 0, l = args.length; i < l; ++i) { + Argument arg = args[i]; + TypeReference type = arg.type; + char[][] typeName = type != null ? type.getTypeName() : null; + boolean prev = isVar; + isVar = typeName != null && typeName.length == 1 && + CharOperation.equals(typeName[0], TypeConstants.VAR); + lexp.argumentsTypeVar |= isVar; + if (i > 0 && prev != isVar && !mixReported) { // report only once per list + this.problemReporter().varCannotBeMixedWithNonVarParams(isVar ? arg : args[i - 1]); + mixReported = true; + } + if (isVar && (type.dimensions() > 0 || type.extraDimensions() > 0)) { + this.problemReporter().varLocalCannotBeArray(arg); + } + } +} protected void consumeLambdaExpression() { // LambdaExpression ::= LambdaHeader LambdaBody @@ -8648,6 +8675,7 @@ protected void consumeLambdaExpression() { if (!this.parsingJava8Plus) { problemReporter().lambdaExpressionsNotBelow18(lexp); } + setArgumentsTypeVar(lexp); pushOnExpressionStack(lexp); if (this.currentElement != null) { this.lastCheckPoint = body.sourceEnd + 1; 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 929c296a46..652c32698c 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 @@ -3353,10 +3353,9 @@ public void importProblem(ImportReference importRef, Binding expectedImport) { } invalidType(importRef, (TypeBinding)expectedImport); } -public void conflictingPackagesFromModules(SplitPackageBinding splitPackage, int sourceStart, int sourceEnd) { - ModuleBinding enclosingModule = splitPackage.enclosingModule; +public void conflictingPackagesFromModules(SplitPackageBinding splitPackage, ModuleBinding focusModule, int sourceStart, int sourceEnd) { String modules = splitPackage.incarnations.stream() - .filter(enclosingModule::canAccess) + .filter(focusModule::canAccess) .map(p -> String.valueOf(p.enclosingModule.readableName())) .sorted() .collect(Collectors.joining(", ")); //$NON-NLS-1$ 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 60fb2e7e30..8390c3a88b 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -2152,10 +2152,98 @@ public class DefaultCodeFormatterConstants { * @see JavaCore#INSERT * @see JavaCore#DO_NOT_INSERT * @since 3.0 + * @deprecated Use the new settings instead: {@link #FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR}, + * {@link #FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR}, {@link #FORMATTER_INSERT_SPACE_AFTER_STRING_CONCATENATION}, + * {@link #FORMATTER_INSERT_SPACE_AFTER_SHIFT_OPERATOR}, {@link #FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR}, + * {@link #FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR}, {@link #FORMATTER_INSERT_SPACE_AFTER_LOGICAL_OPERATOR} */ public static final String FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_binary_operator"; //$NON-NLS-1$ /** * <pre> + * FORMATTER / Option to insert a space after a multiplicative operator (*, /, %) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_multiplicative_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space after an additive operator (+, -) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_additive_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space after a string concatenation operator + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_STRING_CONCATENATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_string_concatenation"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space after a shift operator (<<, >>, >>>) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_SHIFT_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_shift_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space after a relational operator (<, >, <=, >=, ==, !=) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_relational_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space after a bitwise operator (&, ^, |) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_bitwise_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space after a logical operator (&&, ||) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_LOGICAL_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_logical_operator"; //$NON-NLS-1$ + /** + * <pre> * FORMATTER / Option to insert a space after the closing angle bracket in explicit type arguments on method/constructor invocations * - option id: "org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" * - possible values: { INSERT, DO_NOT_INSERT } @@ -2885,10 +2973,98 @@ public class DefaultCodeFormatterConstants { * @see JavaCore#INSERT * @see JavaCore#DO_NOT_INSERT * @since 3.0 + * @deprecated Use the new settings instead: {@link #FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR}, + * {@link #FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR}, {@link #FORMATTER_INSERT_SPACE_BEFORE_STRING_CONCATENATION}, + * {@link #FORMATTER_INSERT_SPACE_BEFORE_SHIFT_OPERATOR}, {@link #FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR}, + * {@link #FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR}, {@link #FORMATTER_INSERT_SPACE_BEFORE_LOGICAL_OPERATOR} */ public static final String FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_binary_operator"; //$NON-NLS-1$ /** * <pre> + * FORMATTER / Option to insert a space before a multiplicative operator (*, /, %) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_multiplicative_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space before an additive operator (+, -) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_additive_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space before a string concatenation operator + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_STRING_CONCATENATION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_string_concatenation"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space before a shift operator (<<, >>, >>>) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_SHIFT_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_shift_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space before a relational operator (<, >, <=, >=, ==, !=) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_relational_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space before a bitwise operator (&, ^, |) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_bitwise_operator"; //$NON-NLS-1$ + /** + * <pre> + * FORMATTER / Option to insert a space before a logical operator (&&, ||) + * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + * </pre> + * @see JavaCore#INSERT + * @see JavaCore#DO_NOT_INSERT + * @since 3.17 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_LOGICAL_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_logical_operator"; //$NON-NLS-1$ + /** + * <pre> * FORMATTER / Option to insert a space before the closing angle bracket in parameterized type reference * - option id: "org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" * - possible values: { INSERT, DO_NOT_INSERT } 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 a5ff4c5095..12b0b2f2f0 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -274,7 +274,13 @@ public class DefaultCodeFormatterOptions { public boolean insert_space_after_assignment_operator; public boolean insert_space_after_at_in_annotation; public boolean insert_space_after_at_in_annotation_type_declaration; - public boolean insert_space_after_binary_operator; + public boolean insert_space_after_multiplicative_operator; + public boolean insert_space_after_additive_operator; + public boolean insert_space_after_string_concatenation; + public boolean insert_space_after_shift_operator; + public boolean insert_space_after_relational_operator; + public boolean insert_space_after_bitwise_operator; + public boolean insert_space_after_logical_operator; public boolean insert_space_after_closing_angle_bracket_in_type_arguments; public boolean insert_space_after_closing_angle_bracket_in_type_parameters; public boolean insert_space_after_closing_paren_in_cast; @@ -336,7 +342,13 @@ public class DefaultCodeFormatterOptions { public boolean insert_space_before_and_in_type_parameter; public boolean insert_space_before_at_in_annotation_type_declaration; public boolean insert_space_before_assignment_operator; - public boolean insert_space_before_binary_operator; + public boolean insert_space_before_multiplicative_operator; + public boolean insert_space_before_additive_operator; + public boolean insert_space_before_string_concatenation; + public boolean insert_space_before_shift_operator; + public boolean insert_space_before_relational_operator; + public boolean insert_space_before_bitwise_operator; + public boolean insert_space_before_logical_operator; public boolean insert_space_before_closing_angle_bracket_in_parameterized_type_reference; public boolean insert_space_before_closing_angle_bracket_in_type_arguments; public boolean insert_space_before_closing_angle_bracket_in_type_parameters; @@ -629,7 +641,13 @@ public class DefaultCodeFormatterOptions { options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, this.insert_space_after_assignment_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION, this.insert_space_after_at_in_annotation? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION_TYPE_DECLARATION, this.insert_space_after_at_in_annotation_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); - options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, this.insert_space_after_binary_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR, this.insert_space_after_multiplicative_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, this.insert_space_after_additive_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_STRING_CONCATENATION, this.insert_space_after_string_concatenation ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SHIFT_OPERATOR, this.insert_space_after_shift_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR, this.insert_space_after_relational_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR, this.insert_space_after_bitwise_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_LOGICAL_OPERATOR, this.insert_space_after_logical_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS, this.insert_space_after_closing_angle_bracket_in_type_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS, this.insert_space_after_closing_angle_bracket_in_type_parameters ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST, this.insert_space_after_closing_paren_in_cast? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); @@ -690,7 +708,13 @@ public class DefaultCodeFormatterOptions { options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_AND_IN_TYPE_PARAMETER, this.insert_space_before_and_in_type_parameter ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_AT_IN_ANNOTATION_TYPE_DECLARATION, this.insert_space_before_at_in_annotation_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, this.insert_space_before_assignment_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); - options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, this.insert_space_before_binary_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR, this.insert_space_before_multiplicative_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, this.insert_space_before_additive_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_STRING_CONCATENATION, this.insert_space_before_string_concatenation ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SHIFT_OPERATOR, this.insert_space_before_shift_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR, this.insert_space_before_relational_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR, this.insert_space_before_bitwise_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LOGICAL_OPERATOR, this.insert_space_before_logical_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE, this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS, this.insert_space_before_closing_angle_bracket_in_type_arguments? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS, this.insert_space_before_closing_angle_bracket_in_type_parameters? JavaCore.INSERT : JavaCore.DO_NOT_INSERT); @@ -1619,10 +1643,20 @@ public class DefaultCodeFormatterOptions { if (insertSpaceAfterAtInAnnotationTypeDeclarationOption != null) { this.insert_space_after_at_in_annotation_type_declaration = JavaCore.INSERT.equals(insertSpaceAfterAtInAnnotationTypeDeclarationOption); } - final Object insertSpaceAfterBinaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR); - if (insertSpaceAfterBinaryOperatorOption != null) { - this.insert_space_after_binary_operator = JavaCore.INSERT.equals(insertSpaceAfterBinaryOperatorOption); - } + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_multiplicative_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_additive_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_STRING_CONCATENATION, JavaCore.INSERT, + v -> this.insert_space_after_string_concatenation = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SHIFT_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_shift_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_relational_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_bitwise_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_LOGICAL_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_logical_operator = v); final Object insertSpaceAfterClosingAngleBracketInTypeArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS); if (insertSpaceAfterClosingAngleBracketInTypeArgumentsOption != null) { this.insert_space_after_closing_angle_bracket_in_type_arguments = JavaCore.INSERT.equals(insertSpaceAfterClosingAngleBracketInTypeArgumentsOption); @@ -1863,10 +1897,20 @@ public class DefaultCodeFormatterOptions { if (insertSpaceBeforeAssignmentOperatorOption != null) { this.insert_space_before_assignment_operator = JavaCore.INSERT.equals(insertSpaceBeforeAssignmentOperatorOption); } - final Object insertSpaceBeforeBinaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR); - if (insertSpaceBeforeBinaryOperatorOption != null) { - this.insert_space_before_binary_operator = JavaCore.INSERT.equals(insertSpaceBeforeBinaryOperatorOption); - } + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_multiplicative_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_additive_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_STRING_CONCATENATION, JavaCore.INSERT, + v -> this.insert_space_before_string_concatenation = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SHIFT_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_shift_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_relational_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_bitwise_operator = v); + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LOGICAL_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_logical_operator = v); final Object insertSpaceBeforeClosingAngleBracketInParameterizedTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE); if (insertSpaceBeforeClosingAngleBracketInParameterizedTypeReferenceOption != null) { this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference = JavaCore.INSERT.equals(insertSpaceBeforeClosingAngleBracketInParameterizedTypeReferenceOption); @@ -2656,6 +2700,64 @@ public class DefaultCodeFormatterOptions { setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_BINARY_OPERATOR, DefaultCodeFormatterConstants.TRUE, v -> this.wrap_before_logical_operator = v); } + + // add space before and after binary operator -> more granular settings + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_multiplicative_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_additive_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_STRING_CONCATENATION) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_string_concatenation = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SHIFT_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_shift_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_relational_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_bitwise_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LOGICAL_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_before_logical_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_multiplicative_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_additive_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_STRING_CONCATENATION) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_string_concatenation = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SHIFT_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_shift_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_relational_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_bitwise_operator = v); + } + if (settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_LOGICAL_OPERATOR) == null) { + setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, JavaCore.INSERT, + v -> this.insert_space_after_logical_operator = v); + } } public void setDefaultSettings() { @@ -2798,7 +2900,13 @@ public class DefaultCodeFormatterOptions { this.insert_space_after_assignment_operator = true; this.insert_space_after_at_in_annotation = false; this.insert_space_after_at_in_annotation_type_declaration = false; - this.insert_space_after_binary_operator = true; + this.insert_space_after_multiplicative_operator = true; + this.insert_space_after_additive_operator = true; + this.insert_space_after_string_concatenation = true; + this.insert_space_after_shift_operator = true; + this.insert_space_after_relational_operator = true; + this.insert_space_after_bitwise_operator = true; + this.insert_space_after_logical_operator = true; this.insert_space_after_closing_angle_bracket_in_type_arguments = false; this.insert_space_after_closing_angle_bracket_in_type_parameters = true; this.insert_space_after_closing_paren_in_cast = true; @@ -2859,7 +2967,13 @@ public class DefaultCodeFormatterOptions { this.insert_space_before_and_in_type_parameter = true; this.insert_space_before_at_in_annotation_type_declaration = true; this.insert_space_before_assignment_operator = true; - this.insert_space_before_binary_operator = true; + this.insert_space_before_multiplicative_operator = true; + this.insert_space_before_additive_operator = true; + this.insert_space_before_string_concatenation = true; + this.insert_space_before_shift_operator = true; + this.insert_space_before_relational_operator = true; + this.insert_space_before_bitwise_operator = true; + this.insert_space_before_logical_operator = true; this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference = false; this.insert_space_before_closing_angle_bracket_in_type_arguments = false; this.insert_space_before_closing_angle_bracket_in_type_parameters = false; @@ -3134,7 +3248,13 @@ public class DefaultCodeFormatterOptions { this.insert_space_after_assignment_operator = true; this.insert_space_after_at_in_annotation = false; this.insert_space_after_at_in_annotation_type_declaration = false; - this.insert_space_after_binary_operator = true; + this.insert_space_after_multiplicative_operator = true; + this.insert_space_after_additive_operator = true; + this.insert_space_after_string_concatenation = true; + this.insert_space_after_shift_operator = true; + this.insert_space_after_relational_operator = true; + this.insert_space_after_bitwise_operator = true; + this.insert_space_after_logical_operator = true; this.insert_space_after_closing_angle_bracket_in_type_arguments = false; this.insert_space_after_closing_angle_bracket_in_type_parameters = true; this.insert_space_after_closing_paren_in_cast = true; @@ -3195,7 +3315,13 @@ public class DefaultCodeFormatterOptions { this.insert_space_before_and_in_type_parameter = true; this.insert_space_before_at_in_annotation_type_declaration = true; this.insert_space_before_assignment_operator = true; - this.insert_space_before_binary_operator = true; + this.insert_space_before_multiplicative_operator = true; + this.insert_space_before_additive_operator = true; + this.insert_space_before_string_concatenation = true; + this.insert_space_before_shift_operator = true; + this.insert_space_before_relational_operator = true; + this.insert_space_before_bitwise_operator = true; + this.insert_space_before_logical_operator = true; this.insert_space_before_closing_angle_bracket_in_parameterized_type_reference = false; this.insert_space_before_closing_angle_bracket_in_type_arguments = false; this.insert_space_before_closing_angle_bracket_in_type_parameters = false; diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java index 96353d1bfa..f194800322 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2018 Mateusz Matela and others. + * Copyright (c) 2014, 2019 Mateusz Matela and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -18,7 +18,12 @@ package org.eclipse.jdt.internal.formatter; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.*; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.function.Predicate; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; @@ -54,6 +59,7 @@ import org.eclipse.jdt.core.dom.ForStatement; import org.eclipse.jdt.core.dom.IfStatement; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.InfixExpression.Operator; import org.eclipse.jdt.core.dom.InstanceofExpression; import org.eclipse.jdt.core.dom.IntersectionType; import org.eclipse.jdt.core.dom.LabeledStatement; @@ -72,7 +78,6 @@ import org.eclipse.jdt.core.dom.ParenthesizedExpression; import org.eclipse.jdt.core.dom.PostfixExpression; import org.eclipse.jdt.core.dom.PrefixExpression; import org.eclipse.jdt.core.dom.ProvidesDirective; -import org.eclipse.jdt.core.dom.PrefixExpression.Operator; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; @@ -99,6 +104,43 @@ import org.eclipse.jdt.core.dom.WildcardType; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; public class SpacePreparator extends ASTVisitor { + + private static final Map<Operator, Predicate<DefaultCodeFormatterOptions>> SPACE_BEFORE_OPERATOR; + private static final Map<Operator, Predicate<DefaultCodeFormatterOptions>> SPACE_AFTER_OPERATOR; + + static { + Map<Operator, Predicate<DefaultCodeFormatterOptions>> spaceBeforeOperator = new HashMap<>(); + Map<Operator, Predicate<DefaultCodeFormatterOptions>> spaceAfterOperator = new HashMap<>(); + for (Operator op : Arrays.asList(Operator.TIMES, Operator.DIVIDE, Operator.REMAINDER)) { + spaceBeforeOperator.put(op, o -> o.insert_space_before_multiplicative_operator); + spaceAfterOperator.put(op, o -> o.insert_space_after_multiplicative_operator); + } + for (Operator op : Arrays.asList(Operator.PLUS, Operator.MINUS)) { + spaceBeforeOperator.put(op, o -> o.insert_space_before_additive_operator); + spaceAfterOperator.put(op, o -> o.insert_space_after_additive_operator); + } + for (Operator op : Arrays.asList(Operator.LEFT_SHIFT, Operator.RIGHT_SHIFT_SIGNED, + Operator.RIGHT_SHIFT_UNSIGNED)) { + spaceBeforeOperator.put(op, o -> o.insert_space_before_shift_operator); + spaceAfterOperator.put(op, o -> o.insert_space_after_shift_operator); + } + for (Operator op : Arrays.asList(Operator.LESS, Operator.GREATER, Operator.LESS_EQUALS, + Operator.GREATER_EQUALS, Operator.EQUALS, Operator.NOT_EQUALS)) { + spaceBeforeOperator.put(op, o -> o.insert_space_before_relational_operator); + spaceAfterOperator.put(op, o -> o.insert_space_after_relational_operator); + } + for (Operator op : Arrays.asList(Operator.AND, Operator.XOR, Operator.OR)) { + spaceBeforeOperator.put(op, o -> o.insert_space_before_bitwise_operator); + spaceAfterOperator.put(op, o -> o.insert_space_after_bitwise_operator); + } + for (Operator op : Arrays.asList(Operator.CONDITIONAL_AND, Operator.CONDITIONAL_OR)) { + spaceBeforeOperator.put(op, o -> o.insert_space_before_logical_operator); + spaceAfterOperator.put(op, o -> o.insert_space_after_logical_operator); + } + SPACE_BEFORE_OPERATOR = Collections.unmodifiableMap(spaceBeforeOperator); + SPACE_AFTER_OPERATOR = Collections.unmodifiableMap(spaceAfterOperator); + } + TokenManager tm; private DefaultCodeFormatterOptions options; @@ -710,21 +752,26 @@ public class SpacePreparator extends ASTVisitor { @Override public boolean visit(InfixExpression node) { - String operator = node.getOperator().toString(); - handleOperator(operator, node.getRightOperand(), this.options.insert_space_before_binary_operator, - this.options.insert_space_after_binary_operator); + Operator operator = node.getOperator(); + boolean spaceBefore = SPACE_BEFORE_OPERATOR.get(operator).test(this.options); + boolean spaceAfter = SPACE_AFTER_OPERATOR.get(operator).test(this.options); + if (this.tm.isStringConcatenation(node)) { + spaceBefore = this.options.insert_space_before_string_concatenation; + spaceAfter = this.options.insert_space_after_string_concatenation; + } + handleOperator(operator.toString(), node.getRightOperand(), spaceBefore, spaceAfter); List<Expression> extendedOperands = node.extendedOperands(); for (Expression operand : extendedOperands) { - handleOperator(operator, operand, this.options.insert_space_before_binary_operator, - this.options.insert_space_after_binary_operator); + handleOperator(operator.toString(), operand, spaceBefore, spaceAfter); } return true; } @Override public boolean visit(PrefixExpression node) { - Operator operator = node.getOperator(); - if (operator.equals(Operator.INCREMENT) || operator.equals(Operator.DECREMENT)) { + PrefixExpression.Operator operator = node.getOperator(); + if (operator.equals(PrefixExpression.Operator.INCREMENT) + || operator.equals(PrefixExpression.Operator.DECREMENT)) { handleOperator(operator.toString(), node.getOperand(), this.options.insert_space_before_prefix_operator, this.options.insert_space_after_prefix_operator); @@ -782,8 +829,8 @@ public class SpacePreparator extends ASTVisitor { public boolean visit(IntersectionType node) { List<Type> types = node.types(); for (int i = 1; i < types.size(); i++) - handleTokenBefore(types.get(i), TokenNameAND, this.options.insert_space_before_binary_operator, - this.options.insert_space_after_binary_operator); + handleTokenBefore(types.get(i), TokenNameAND, this.options.insert_space_before_bitwise_operator, + this.options.insert_space_after_bitwise_operator); return true; } @@ -910,8 +957,8 @@ public class SpacePreparator extends ASTVisitor { public boolean visit(UnionType node) { List<Type> types = node.types(); for (int i = 1; i < types.size(); i++) - handleTokenBefore(types.get(i), TokenNameOR, this.options.insert_space_before_binary_operator, - this.options.insert_space_after_binary_operator); + handleTokenBefore(types.get(i), TokenNameOR, this.options.insert_space_before_bitwise_operator, + this.options.insert_space_after_bitwise_operator); return true; } diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java index 4e42073ab8..f05462943a 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2018 Mateusz Matela and others. + * Copyright (c) 2014, 2019 Mateusz Matela and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -26,6 +26,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.InfixExpression.Operator; import org.eclipse.jdt.internal.formatter.Token.WrapMode; import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor; @@ -386,6 +390,21 @@ public class TokenManager implements Iterable<Token> { && get(index).originalEnd <= node.getStartPosition() + node.getLength(); } + public boolean isStringConcatenation(InfixExpression node) { + if (!node.getOperator().equals(Operator.PLUS)) + return false; + List<Expression> operands = new ArrayList<Expression>(node.extendedOperands()); + operands.add(node.getLeftOperand()); + operands.add(node.getRightOperand()); + for (Expression o : operands) { + if (o instanceof StringLiteral) + return true; + if ((o instanceof InfixExpression) && isStringConcatenation((InfixExpression) o)) + return true; + } + return false; + } + public void addNLSAlignIndex(int index, int align) { if (this.tokenIndexToNLSAlign == null) this.tokenIndexToNLSAlign = new HashMap<Integer, Integer>(); 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 c4130435dd..0d39d3e9ed 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2018 Mateusz Matela and others. + * Copyright (c) 2014, 2019 Mateusz Matela and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -90,7 +90,6 @@ import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.SuperConstructorInvocation; import org.eclipse.jdt.core.dom.SuperFieldAccess; import org.eclipse.jdt.core.dom.SuperMethodInvocation; @@ -616,7 +615,7 @@ public class WrapPreparator extends ASTVisitor { int wrappingOption = OPERATOR_WRAPPING_OPTION.get(node.getOperator()).applyAsInt(this.options); boolean wrapBeforeOperator = OPERATOR_WRAP_BEFORE_OPTION.get(node.getOperator()).test(this.options); - if (isStringConcatenation(node)) { + if (this.tm.isStringConcatenation(node)) { wrappingOption = this.options.alignment_for_string_concatenation; wrapBeforeOperator = this.options.wrap_before_string_concatenation; } @@ -673,21 +672,6 @@ public class WrapPreparator extends ASTVisitor { } } - private boolean isStringConcatenation(InfixExpression node) { - if (!node.getOperator().equals(Operator.PLUS)) - return false; - List<Expression> operands = new ArrayList<Expression>(node.extendedOperands()); - operands.add(node.getLeftOperand()); - operands.add(node.getRightOperand()); - for (Expression o : operands) { - if (o instanceof StringLiteral) - return true; - if ((o instanceof InfixExpression) && isStringConcatenation((InfixExpression) o)) - return true; - } - return false; - } - private boolean samePrecedence(InfixExpression expression1, InfixExpression expression2) { Integer precedence1 = OPERATOR_PRECEDENCE.get(expression1.getOperator()); Integer precedence2 = OPERATOR_PRECEDENCE.get(expression2.getOperator()); @@ -779,10 +763,14 @@ public class WrapPreparator extends ASTVisitor { int rParen = this.tm.firstIndexAfter(node.getExpression(), TokenNameRPAREN); handleParenthesesPositions(lParen, rParen, this.options.parenthesis_positions_in_if_while_statement); + Statement elseStatement = node.getElseStatement(); boolean keepThenOnSameLine = this.options.keep_then_statement_on_same_line - || (this.options.keep_simple_if_on_one_line && node.getElseStatement() == null); + || (this.options.keep_simple_if_on_one_line && elseStatement == null); if (keepThenOnSameLine) handleSimpleLoop(node.getThenStatement(), this.options.alignment_for_compact_if); + + if (this.options.keep_else_statement_on_same_line && elseStatement != null) + handleSimpleLoop(elseStatement, this.options.alignment_for_compact_if); return true; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java index 9c13682bd4..5a7012840f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java @@ -41,6 +41,7 @@ import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; @@ -71,7 +72,33 @@ public class ExternalFoldersManager { // Prevent instantiation // https://bugs.eclipse.org/bugs/show_bug.cgi?id=377806 if (Platform.isRunning()) { - getFolders(); + /* + * The code here runs during JavaCore start-up. + * So if we need to open the external folders project, we do this from a job. + * Otherwise workspace jobs that attempt to access JDT core functionality can cause a deadlock. + * + * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=542860. + */ + class InitializeFolders extends WorkspaceJob { + public InitializeFolders() { + super("Initialize external folders"); //$NON-NLS-1$ + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) { + getFolders(); + return Status.OK_STATUS; + } + + @Override + public boolean belongsTo(Object family) { + return family == InitializeFolders.class; + } + } + InitializeFolders initializeFolders = new InitializeFolders(); + IProject project = getExternalFoldersProject(); + initializeFolders.setRule(project); + initializeFolders.schedule(); } } @@ -429,7 +456,11 @@ public class ExternalFoldersManager { } catch (CoreException e) { Util.log(e, "Exception while initializing external folders"); //$NON-NLS-1$ } - this.folders = Collections.synchronizedMap(tempFolders); + synchronized (this) { + if (this.folders == null) { + this.folders = Collections.synchronizedMap(tempFolders); + } + } } return this.folders; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java index cf98d1712f..835d45736e 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -879,8 +879,6 @@ public class NameLookup implements SuffixConstants { try { if (root.getKind() == IPackageFragmentRoot.K_SOURCE) module = root.getJavaProject().getModuleDescription(); // from any root in this project - else - module = root.getModuleDescription(); } catch (JavaModelException e) { cache.put(root, NO_MODULE); return null; @@ -890,9 +888,14 @@ public class NameLookup implements SuffixConstants { IClasspathEntry classpathEntry = rootToEntry.apply(root); if (classpathEntry instanceof ClasspathEntry) { if (((ClasspathEntry) classpathEntry).isModular()) { - // modular but no module-info implies this is an automatic module - module = ((PackageFragmentRoot) root).getAutomaticModuleDescription(classpathEntry); + module = root.getModuleDescription(); + if (module == null) { + // modular but no module-info implies this is an automatic module + module = ((PackageFragmentRoot) root).getAutomaticModuleDescription(classpathEntry); + } } + } else if (root instanceof JrtPackageFragmentRoot) { + module = root.getModuleDescription(); // always considered modular } } cache.put(root, module != null ? module : NO_MODULE); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java index d272502db1..269e064480 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java @@ -344,8 +344,14 @@ private void createInconsistentBuildMarker(CoreException coreException) throws C private void cleanup() { this.participants = null; - this.nameEnvironment = null; - this.testNameEnvironment = null; + if(this.nameEnvironment != null) { + this.nameEnvironment.cleanup(); + this.nameEnvironment = null; + } + if(this.testNameEnvironment != null) { + this.testNameEnvironment.cleanup(); + this.testNameEnvironment = null; + } this.binaryLocationsPerProject = null; this.lastState = null; this.notifier = null; |