diff options
author | Stephan Herrmann | 2018-11-04 16:14:47 +0000 |
---|---|---|
committer | Stephan Herrmann | 2018-11-04 16:14:47 +0000 |
commit | 7bc42c0482b92818d18e57075fb11b5b56879406 (patch) | |
tree | 03614fb46a91ea7511ab904d60ab23fedc26f096 | |
parent | e2be43953bc2de1c94661fffef56df58576b4cbe (diff) | |
download | org.eclipse.objectteams-7bc42c0482b92818d18e57075fb11b5b56879406.tar.gz org.eclipse.objectteams-7bc42c0482b92818d18e57075fb11b5b56879406.tar.xz org.eclipse.objectteams-7bc42c0482b92818d18e57075fb11b5b56879406.zip |
Update jdt.core to I20181031-1800 for 4.10M2
34 files changed, 859 insertions, 65 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java index 435318871..8d21da270 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java @@ -196,4 +196,169 @@ public void test006() throws Exception { String expectedOutput = "// Compiled from X.java (version 11 : 55.0, super bit)"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput); } -}
\ No newline at end of file +public void testBug540123a() throws Exception { + this.runConformTest( + new String[] { + "SecurePrefs.java", + "public class SecurePrefs {\n" + + " public SecurePrefs node (String s) {\n" + + " System.out.println(s);\n" + + " return null;\n" + + " }\n" + + "}", + "SecurePrefsRoot.java", + "public class SecurePrefsRoot extends SecurePrefs {\n" + + "\n" + + " public void foo() {\n" + + " SecurePrefs node = node(\"Hello\");\n" + + " if (node != null)\n" + + " System.out.println(node.toString());\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " new SecurePrefsRoot().foo();\n" + + " }\n" + + "}" + }, + "\"" + OUTPUT_DIR + File.separator + "SecurePrefsRoot.java\"" + +" \"" + OUTPUT_DIR + File.separator + "SecurePrefs.java\"" + + " -source 1.3 -target 1.2", + "", + "", + true); + String expectedOutput = "invokevirtual SecurePrefsRoot.node(java.lang.String) : SecurePrefs [14]"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "SecurePrefsRoot.class", "SecurePrefsRoot", expectedOutput); +} +public void testBug540123b() throws Exception { + this.runConformTest( + new String[] { + "SecurePrefs.java", + "public class SecurePrefs {\n" + + " public SecurePrefs node (String s) {\n" + + " System.out.println(s);\n" + + " return null;\n" + + " }\n" + + "}", + "SecurePrefsRoot.java", + "public class SecurePrefsRoot extends SecurePrefs {\n" + + "\n" + + " public void foo() {\n" + + " SecurePrefs node = node(\"Hello\");\n" + + " if (node != null)\n" + + " System.out.println(node.toString());\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " new SecurePrefsRoot().foo();\n" + + " }\n" + + "}" + }, + "\"" + OUTPUT_DIR + File.separator + "SecurePrefsRoot.java\"" + +" \"" + OUTPUT_DIR + File.separator + "SecurePrefs.java\"" + + " -source 1.3", + "", + "", + true); + String expectedOutput = "invokevirtual SecurePrefsRoot.node(java.lang.String) : SecurePrefs [14]"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "SecurePrefsRoot.class", "SecurePrefsRoot", expectedOutput); +} +public void testBug540123c() throws Exception { + this.runConformTest( + new String[] { + "SecurePrefs.java", + "public class SecurePrefs {\n" + + " public SecurePrefs node (String s) {\n" + + " System.out.println(s);\n" + + " return null;\n" + + " }\n" + + "}", + "SecurePrefsRoot.java", + "public class SecurePrefsRoot extends SecurePrefs {\n" + + "\n" + + " public void foo() {\n" + + " SecurePrefs node = node(\"Hello\");\n" + + " if (node != null)\n" + + " System.out.println(node.toString());\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " new SecurePrefsRoot().foo();\n" + + " }\n" + + "}" + }, + "\"" + OUTPUT_DIR + File.separator + "SecurePrefsRoot.java\"" + +" \"" + OUTPUT_DIR + File.separator + "SecurePrefs.java\"" + + " -target 1.3", + "", + "", + true); + String expectedOutput = "invokevirtual SecurePrefsRoot.node(java.lang.String) : SecurePrefs [14]"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "SecurePrefsRoot.class", "SecurePrefsRoot", expectedOutput); +} +public void testBug540123d() throws Exception { + this.runConformTest( + new String[] { + "SecurePrefs.java", + "public class SecurePrefs {\n" + + " public SecurePrefs node (String s) {\n" + + " System.out.println(s);\n" + + " return null;\n" + + " }\n" + + "}", + "SecurePrefsRoot.java", + "public class SecurePrefsRoot extends SecurePrefs {\n" + + "\n" + + " public void foo() {\n" + + " SecurePrefs node = node(\"Hello\");\n" + + " if (node != null)\n" + + " System.out.println(node.toString());\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " new SecurePrefsRoot().foo();\n" + + " }\n" + + "}" + }, + "\"" + OUTPUT_DIR + File.separator + "SecurePrefsRoot.java\"" + +" \"" + OUTPUT_DIR + File.separator + "SecurePrefs.java\"" + + " -1.4", + "", + "", + true); + String expectedOutput = "invokevirtual SecurePrefsRoot.node(java.lang.String) : SecurePrefs [14]"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "SecurePrefsRoot.class", "SecurePrefsRoot", expectedOutput); +} +public void testBug540123e() throws Exception { + this.runConformTest( + new String[] { + "SecurePrefs.java", + "public class SecurePrefs {\n" + + " public SecurePrefs node (String s) {\n" + + " System.out.println(s);\n" + + " return null;\n" + + " }\n" + + "}", + "SecurePrefsRoot.java", + "public class SecurePrefsRoot extends SecurePrefs {\n" + + "\n" + + " public void foo() {\n" + + " SecurePrefs node = node(\"Hello\");\n" + + " if (node != null)\n" + + " System.out.println(node.toString());\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " new SecurePrefsRoot().foo();\n" + + " }\n" + + "}" + }, + "\"" + OUTPUT_DIR + File.separator + "SecurePrefsRoot.java\"" + +" \"" + OUTPUT_DIR + File.separator + "SecurePrefs.java\"" + + " -1.3", + "", + "", + true); + String expectedOutput = "invokevirtual SecurePrefs.node(java.lang.String) : SecurePrefs [14]"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "SecurePrefsRoot.class", "SecurePrefsRoot", expectedOutput); +} +} 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 dce0bd85b..99da258d2 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 @@ -6375,5 +6375,106 @@ public void testBug532137() { false ); } + +public void testBug540313() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "X/C120644mr.java", + "package X;\n" + + "\n" + + "public class C120644mr<V, X extends java.lang.Exception> extends X.C16280iv<V> {\n" + + "}\n" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. ERROR in X\\C120644mr.java (at line 3)\n" + + " public class C120644mr<V, X extends java.lang.Exception> extends X.C16280iv<V> {\n" + + " ^^^^^^^^^^\n" + + "X.C16280iv cannot be resolved to a type\n" + + "----------\n"; + runner.runNegativeTest(); +} + +public void testBug540313a() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "X/C120644mr.java", + "package X;\n" + + "\n" + + "class Outer {\n" + + " class Inner<Z> {}\n" + + "}\n" + + "public class C120644mr<V, X extends Outer> extends X.Inner<V> {\n" + + "}\n" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. ERROR in X\\C120644mr.java (at line 6)\n" + + " public class C120644mr<V, X extends Outer> extends X.Inner<V> {\n" + + " ^^^^^^^\n" + + "X.Inner cannot be resolved to a type\n" + + "----------\n"; + runner.runNegativeTest(); +} + +public void testBug540313b() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "X/C120644mr.java", + "package X;\n" + + "\n" + + "class Outer {\n" + + " class Inner<Z> {}\n" + + "}\n" + + "public class C120644mr<X extends Outer, V> {\n" + + " X.Inner<V> inner;\n" + // is this backed by JLS? + "}\n" + }; + runner.runConformTest(); +} +public void testBug478708() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "bug/IInterface.java", + "package bug;\n" + + "\n" + + "public class IInterface {\n" + + "\n" + + "}\n", + "bug/AbstractA.java", + "package bug;\n" + + "\n" + + "public abstract class AbstractA<T extends IInterface> {\n" + + "\n" + + " public abstract class AbstractD<U> {\n" + + "\n" + + " }\n" + + "}\n", + "bug/AbstractC.java", + "package bug;\n" + + "\n" + + "\n" + + "public abstract class AbstractC<T extends IInterface> extends T.AbstractD<E> {\n" + + "\n" + + " public AbstractC(AbstractA<T> a) {\n" + + " a.super();\n" + + " }\n" + + "}\n", + "bug/E.java", + "package bug;\n" + + "\n" + + "public class E {\n" + + "\n" + + "}\n" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. ERROR in bug\\AbstractC.java (at line 4)\n" + + " public abstract class AbstractC<T extends IInterface> extends T.AbstractD<E> {\n" + + " ^^^^^^^^^^^\n" + + "T.AbstractD cannot be resolved to a type\n" + + "----------\n"; + runner.runNegativeTest(); +} } 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 f35658641..120b628ff 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 @@ -5536,7 +5536,7 @@ public void testBug470542() { "1. ERROR in X.java (at line 5)\n" + " process(missing::new);\n" + " ^^^^^^^\n" + - "missing cannot be resolved\n" + + "missing cannot be resolved to a type\n" + "----------\n"); } public void testBug471280_comment0() { @@ -9424,4 +9424,35 @@ public void testBug508834_comment0() { "}\n" }); } + public void testBug539329() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "Bug539329.java", + " import java.util.*;\n" + + " \n" + + " public class Bug539329 {\n" + + "\n" + + " public static Collection<Class<? extends Interface>> getClasses() {\n" + + " // This yields a compile error in 2018-09, but works in Photon.\n" + + " return Arrays.asList(One.class, Two.class, Three.class);\n" + + " }\n" + + "\n" + + " public static Collection<Class<? extends Interface>> getClassesThatWorks() {\n" + + " // This works surprisinly in both versions\n" + + " return Arrays.asList(One.class, Two.class);\n" + + " }\n" + + " }\n" + + "\n" + + " class One extends Parent<String> implements Interface { }\n" + + "\n" + + " class Two extends Parent<Integer> implements Interface { }\n" + + "\n" + + " class Three extends Parent<Object> implements Interface { }\n" + + "\n" + + " class Parent<T> { }\n" + + "\n" + + " interface Interface { }\n" + }; + runner.runConformTest(); + } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java index 2ac9f09d4..da0ddf9b4 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java @@ -39,7 +39,7 @@ import junit.framework.Test; public class LambdaExpressionsTest extends AbstractRegressionTest { static { - TESTS_NAMES = new String[] { "test449063"}; +// TESTS_NAMES = new String[] { "testBug540520"}; // TESTS_NUMBERS = new int[] { 50 }; // TESTS_RANGE = new int[] { 11, -1 }; } @@ -1277,8 +1277,8 @@ public void test045() { "----------\n" + "5. ERROR in X.java (at line 15)\n" + " i = X.Y::new;\n" + - " ^\n" + - "Y cannot be resolved or is not a field\n" + + " ^^^\n" + + "X.Y cannot be resolved to a type\n" + "----------\n" + "6. ERROR in X.java (at line 27)\n" + " new X().new Y().f();\n" + @@ -6997,6 +6997,104 @@ public void testBug531093() { "" ); } +public void testBug540520() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "Run.java", + "import java.util.ArrayList;\n" + + "import java.util.HashMap;\n" + + "import java.util.List;\n" + + "import java.util.Map;\n" + + "import java.util.stream.Collectors;\n" + + "\n" + + "public class Run {\n" + + "\n" + + " public static void main(String[] args) {\n" + + " \n" + + " List<TypeDeptCount> list = new ArrayList<>();\n" + + " for(int i=0;i<10;i++) {\n" + + " TypeDeptCount ty = new TypeDeptCount();\n" + + " ty.setCykbbm(\"10\"+i);\n" + + " ty.setCount(i);\n" + + " }\n" + + " List<Map<String, Object>> datas = list.stream().collect(Collectors.groupingBy(TypeDeptCount::getType))\n" + + " .entrySet().stream().map(item -> item.getValue().stream().reduce(new HashMap<String, Object>() {\n" + + " private static final long serialVersionUID = 1L;\n" + + " {\n" + + " put(\"count\", 0);\n" + + " put(\"type\", item.getKey());\n" + + " }\n" + + " }, (data1, val) -> {\n" + + " data1.put(val.getCykbbm(), val.getCount());\n" + + " data1.put(\"count\", (Integer) data1.get(\"count\") + val.getCount());\n" + + " return data1;\n" + + " }, (data1, data2) -> {\n" + + " data2.put(\"count\", (Integer) data1.get(\"count\") + (Integer) data2.get(\"count\"));\n" + + " data1.putAll(data2);\n" + + " return data1;\n" + + " })).sorted((item1, item2) -> (Integer) item2.get(\"count\") - (Integer) item1.get(\"count\"))\n" + + " .collect(Collectors.toList());\n" + + " System.out.println(datas);\n" + + " }\n" + + "}\n", + "TypeDeptCount.java", + "public class TypeDeptCount {\n" + + "\n" + + " private String type;\n" + + " private String cykbbm;\n" + + " private Integer count;\n" + + " \n" + + " public String getType() {\n" + + " return type;\n" + + " }\n" + + " public void setType(String type) {\n" + + " this.type = type;\n" + + " }\n" + + " public String getCykbbm() {\n" + + " return cykbbm;\n" + + " }\n" + + " public void setCykbbm(String cykbbm) {\n" + + " this.cykbbm = cykbbm;\n" + + " }\n" + + " public Integer getCount() {\n" + + " return count;\n" + + " }\n" + + " public void setCount(Integer count) {\n" + + " this.count = count;\n" + + " }\n" + + "}\n" + }; + runner.runConformTest(); +} +public void testBug540631() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "EclipseCompileBug.java", + "public enum EclipseCompileBug {\n" + + " /*\n" + + " * Next line fails with these errors in Eclipse, works with javac:\n" + + " * <li>Test cannot be resolved to a type\n" + + " * <li>Cannot reference a field before it is defined\n" + + " */\n" + + " Test(Test::new);\n" + + "\n" + + " @FunctionalInterface\n" + + " public interface IConstructor<T extends Object> {\n" + + " T apply();\n" + + " }\n" + + "\n" + + " private final IConstructor<?> constructor;\n" + + " private EclipseCompileBug (IConstructor<?> newObj) {\n" + + " constructor = newObj;\n" + + " }\n" + + " \n" + + " public static class Test {\n" + + " \n" + + " }\n" + + "}\n" + }; + runner.runConformTest(); +} public static Class testClass() { return LambdaExpressionsTest.class; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java index dea338945..0e9cab5c5 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java @@ -17738,4 +17738,37 @@ public void testBug536555() { runner.javacTestOptions = JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings; runner.runWarningTest(); } +public void testBug540264() { + runNegativeTestWithLibs( + new String[] { + "example/Example.java", + "package example;\n" + + "\n" + + "public abstract class Example {\n" + + " void f() {\n" + + " for (X.Y<Z> entry : x) {\n" + + " }\n" + + " }\n" + + "}\n" + + "", + }, + getCompilerOptions(), + "----------\n" + + "1. ERROR in example\\Example.java (at line 5)\n" + + " for (X.Y<Z> entry : x) {\n" + + " ^\n" + + "X cannot be resolved to a type\n" + + "----------\n" + + "2. ERROR in example\\Example.java (at line 5)\n" + + " for (X.Y<Z> entry : x) {\n" + + " ^\n" + + "Z cannot be resolved to a type\n" + + "----------\n" + + "3. ERROR in example\\Example.java (at line 5)\n" + + " for (X.Y<Z> entry : x) {\n" + + " ^\n" + + "x cannot be resolved to a variable\n" + + "----------\n" + ); +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java index f8253068a..3a4270269 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java @@ -11912,4 +11912,28 @@ public class ASTConverter15Test extends ConverterTestSetup { assertTrue("Bad field definition", fields != null && fields.length == 1); assertEquals("Type binding mismatch", elem, fields[0].getType()); } + + public void testBug540313() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter15/src/X/C120644mr.java", true/*resolve*/); + String contents = + "package X;\n" + + "\n" + + "/* renamed from: X.4mr */\n" + + "public class C120644mr<V, X extends java.lang.Exception> extends X.C16280iv<V> {\n" + + "}\n"; + ASTNode node = buildAST( + contents, + this.workingCopy, + false); + assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType()); + CompilationUnit unit = (CompilationUnit) node; + String expectedError = "X.C16280iv cannot be resolved to a type"; + assertProblemsSize(unit, 1, expectedError); + node = (ASTNode) unit.types().get(0); + assertEquals("Not a type declaration", ASTNode.TYPE_DECLARATION, node.getNodeType()); + Type superclassType = ((TypeDeclaration) node).getSuperclassType(); + ITypeBinding typeBinding = superclassType.resolveBinding(); + assertNull("Binding", typeBinding); + } + } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java index 1fed55bda..1ebb8cb05 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 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 @@ -49,6 +49,7 @@ import org.eclipse.core.runtime.ILogListener; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentDescription; @@ -7400,4 +7401,33 @@ public void testClasspathTestSourceValidation5() throws CoreException { this.deleteProject("P"); } } + +public void testBug539998() throws CoreException { + try { + IJavaProject proj1TestOnly = this.createJavaProject("P1", new String[] {}, "bin-tests"); + IClasspathEntry[] originalCP1 = proj1TestOnly.getRawClasspath(); + + IClasspathEntry[] newCP1 = new IClasspathEntry[originalCP1.length + 1]; + System.arraycopy(originalCP1, 0, newCP1, 0, originalCP1.length); + newCP1[originalCP1.length] = JavaCore.newSourceEntry(new Path("/P1/src-tests"), null, null, null, + new IClasspathAttribute[] { JavaCore.newClasspathAttribute(IClasspathAttribute.TEST, "true") }); + proj1TestOnly.setRawClasspath(newCP1, new NullProgressMonitor()); + IJavaProject proj = this.createJavaProject("P2", new String[] {}, "bin"); + IClasspathEntry[] originalCP = proj.getRawClasspath(); + + IClasspathEntry[] newCP = new IClasspathEntry[originalCP.length + 2]; + System.arraycopy(originalCP, 0, newCP, 0, originalCP.length); + newCP[originalCP.length] = JavaCore.newSourceEntry(new Path("/P2/src"), null, null, null, + new IClasspathAttribute[] {}); + newCP[originalCP.length + 1] = JavaCore.newProjectEntry(new Path("/P1/")); + + IJavaModelStatus status = JavaConventions.validateClasspath(proj, newCP, proj.getOutputLocation()); + + assertStatus("should complain", + "Project has only main sources but depends on project 'P1' which has only test sources.", + status); + } finally { + this.deleteProjects(new String[] { "P1", "P2" }); + } +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java index 4e6d0c39a..39240b754 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java @@ -3500,7 +3500,7 @@ public void testBug519151_023() throws Exception { project1.open(null); waitUntilIndexesReady(); SearchPattern pattern = SearchPattern.createPattern("module519151/pack519151.X519151", IJavaSearchConstants.TYPE, DECLARATIONS, ERASURE_RULE); - IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] {project1, project2}); + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] {project2, project1}); search(pattern, scope, this.resultCollector); assertSearchResults( "lib/lib519151.jar pack519151.X519151 EXACT_MATCH", diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests9.java index 8200653c4..9e769451b 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests9.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests9.java @@ -16,6 +16,8 @@ package org.eclipse.jdt.core.tests.model; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -23,6 +25,7 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathAttribute; @@ -43,6 +46,10 @@ import org.eclipse.jdt.internal.core.search.indexing.IndexRequest; import junit.framework.Test; public class ResolveTests9 extends AbstractJavaModelTests { + private static final int MODULE = 1; + private static final int WITHOUT_TEST = 2; + private static final int TEST = 4; + ICompilationUnit wc = null; static { @@ -91,6 +98,30 @@ public class ResolveTests9 extends AbstractJavaModelTests { } super.tearDown(); } + + void addProjectEntry(IJavaProject thisProject, IJavaProject otherProject, int flags) throws JavaModelException { + addClasspathEntry(thisProject, + JavaCore.newProjectEntry(otherProject.getPath(), null, false, attributes(flags), false)); + } + IClasspathAttribute[] attributes(int flags) { + List<IClasspathAttribute> attrs = new ArrayList<>(); + if ((flags & MODULE) != 0) + attrs.add(JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")); + if ((flags & WITHOUT_TEST) != 0) + attrs.add(JavaCore.newClasspathAttribute(IClasspathAttribute.WITHOUT_TEST_CODE, "true")); + if ((flags & TEST) != 0) + attrs.add(JavaCore.newClasspathAttribute(IClasspathAttribute.TEST, "true")); + return attrs.toArray(new IClasspathAttribute[attrs.size()]); + } + void addTestSrc(IJavaProject prj) throws CoreException { + IPath path = prj.getProject().getFullPath(); + IClasspathEntry testSrc = JavaCore.newSourceEntry(path.append(new Path("src-test")), + null, null, path.append(new Path("bin-test")), + new IClasspathAttribute[] {JavaCore.newClasspathAttribute(IClasspathAttribute.TEST, "true")}); + addClasspathEntry(prj, testSrc); + createFolder(prj.getElementName() + "/src-test"); + } + public void testModuleInfo_serviceImplementation_OK() throws CoreException { IFile modInfo = null; try { @@ -399,4 +430,131 @@ public class ResolveTests9 extends AbstractJavaModelTests { deleteProject(mod); } } + + public void testBug537934() throws Exception { + if (!isJRE9) { + System.err.println("Test "+getName()+" requires a JRE 9"); + return; + } + IJavaProject gui = null; + IJavaProject model = null; + IJavaProject type = null; + IJavaProject logg = null; + try { + // ---- module log: + // - has log4j on the module path + logg = createJava9ProjectWithJREAttributes("com.igorion.log", new String[] {"src"}, attributes(MODULE)); + String jarAbsPath = logg.getProject().getLocation()+"/log4j.jar"; + createJar(new String[] { + "log4j/Dummy.java", + "package log4j;\n" + + "public class Dummy {}\n" + }, + jarAbsPath); + addLibraryEntry(logg, new Path(jarAbsPath), null, null, null, null, attributes(MODULE), false); + createFolder("com.igorion.log/src/com/igorion/log"); + createFile("com.igorion.log/src/com/igorion/log/ILog.java", + "package com.igorion.log;\n public interface ILog {}\n"); + createFile("com.igorion.log/src/module-info.java", + "module com.igorion.log {\n" + + " requires log4j;\n" + + " exports com.igorion.log;\n" + + "}\n"); + logg.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = logg.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("markers in com.igorion.log", + "Name of automatic module \'log4j\' is unstable, it is derived from the module\'s file name.", + markers); + + // ---- module type: + // - has test sources + type = createJava9Project("com.igorion.type"); + createFolder("com.igorion.type/src/com/igorion/type"); + createFile("com.igorion.type/src/com/igorion/type/IOther.java", + "package com.igorion.type;\n public interface IOther {}\n"); + createFile("com.igorion.type/src/module-info.java", + "module com.igorion.type {\n" + + " exports com.igorion.type;\n" + + "}\n"); + addTestSrc(type); + type.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + markers = type.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("markers in com.igorion.type", "", markers); + + // ---- module model: + // - has test sources + // - has log4j on the module path + // - has modules log & type on the module path without_test_code + model = createJava9ProjectWithJREAttributes("com.igorion.model", new String[] {"src"}, attributes(MODULE)); + createFolder("com.igorion.model/src/com/igorion/model/define"); + createFile("com.igorion.model/src/com/igorion/model/IModel.java", + "package com.igorion.model;\n public interface IModel {}\n"); + createFile("com.igorion.model/src/com/igorion/model/define/Model.java", + "package com.igorion.model.define;\n" + + "import com.igorion.model.IModel;\n" + + "import java.util.Optional;\n" + + "public class Model {\n" + + " public static synchronized Optional<IModel> instance() { return Optional.empty(); }\n" + + "}\n"); + createFile("com.igorion.model/src/module-info.java", + "module com.igorion.model {\n" + + " requires com.igorion.log;\n" + + " exports com.igorion.model;\n" + + " exports com.igorion.model.define;\n" + + "}\n"); + addTestSrc(model); + addLibraryEntry(model, new Path(jarAbsPath), null, null, null, null, attributes(MODULE), false); + addProjectEntry(model, logg, MODULE|WITHOUT_TEST); + addProjectEntry(model, type, MODULE|WITHOUT_TEST); + model.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + markers = model.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("markers in com.igorion.model", "", markers); + + // ---- module gui: + // - has log4j on the module path for test code + // - has modules type, model, log on the module path without_test_code (order is significant) + gui = createJava9ProjectWithJREAttributes("com.igorion.gui", new String[] {"src"}, attributes(MODULE)); + addTestSrc(gui); + createFolder("com.igorion.gui/src/com/igorion/gui"); + String source = + "package com.igorion.gui;\n" + + "import com.igorion.model.IModel;\n" + + "import com.igorion.model.define.Model;\n" + + "import java.util.Optional;\n" + + "public class Reproduce {\n" + + " static void meth() {\n" + + " Optional<IModel> oModel = Model.instance();\n" + + " if (oModel.isPresent())\n" + + " oModel.get();\n" + + " }\n" + + "}\n"; + createFile("com.igorion.gui/src/com/igorion/gui/Reproduce.java", source); + createFile("com.igorion.gui/src/module-info.java", + "module com.igorion.gui {\n" + + " requires com.igorion.type;\n" + + " requires com.igorion.model;\n" + + "}\n"); + addLibraryEntry(gui, new Path(jarAbsPath), null, null, null, null, attributes(MODULE|TEST), false); + addProjectEntry(gui, type, MODULE|WITHOUT_TEST); + addProjectEntry(gui, model, MODULE|WITHOUT_TEST); + addProjectEntry(gui, logg, MODULE|WITHOUT_TEST); + gui.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null); + markers = gui.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("markers in com.igorion.gui", "", markers); + + // test that selection finds a fully resolved type Optional<IModel>: + ICompilationUnit unit = getCompilationUnit("com.igorion.gui/src/com/igorion/gui/Reproduce.java"); + int start = source.indexOf("get("); + IJavaElement[] selected = unit.codeSelect(start, 3); + assertElementsEqual( + "Unexpected elements", + "get() [in Optional [in Optional.class [in java.util [in <module:java.base>]]]]", + selected); + } finally { + deleteProject(gui); + deleteProject(model); + deleteProject(type); + deleteProject(logg); + } + } } diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java index 9986bdb1c..d1030b9b6 100644 --- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java +++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java @@ -5583,11 +5583,13 @@ protected void validateOptions(boolean didSpecifyCompliance) { || CompilerOptions.VERSION_1_6.equals(source)) { this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6); } else { - if (CompilerOptions.versionToJdkLevel(source) > 0) + // 1.3 is the lowest version that can be specified as -source + // The following check will ensure '0' is ignored. + if (CompilerOptions.versionToJdkLevel(source) >= ClassFileConstants.JDK1_7) this.options.put(CompilerOptions.OPTION_TargetPlatform, source); } } else { - if (CompilerOptions.versionToJdkLevel(version) > 0) { + if (CompilerOptions.versionToJdkLevel(version) > ClassFileConstants.JDK10) { this.options.put(CompilerOptions.OPTION_Source, version); this.options.put(CompilerOptions.OPTION_TargetPlatform, version); } @@ -5620,7 +5622,7 @@ protected void validateOptions(boolean didSpecifyCompliance) { if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_10); if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_10); } else { - if (CompilerOptions.versionToJdkLevel(version) > 0) { + if (CompilerOptions.versionToJdkLevel(version) > ClassFileConstants.JDK10) { if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, version); if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, version); } 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 5bb5fa732..0e0790c20 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 @@ -1495,7 +1495,7 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre if (((LambdaExpression) lambdaScope2.referenceContext).sourceStart == LambdaExpression.this.sourceStart) { // local type within this lambda needs replacement: TypeBinding substType = this.localTypes2.get(orgLocal.sourceStart); - if (substType != null) { + if (substType != null && substType != orgLocal) { //$IDENTITY-COMPARISON$ orgLocal.transferConstantPoolNameTo(substType); return substType; } @@ -1521,10 +1521,11 @@ public class LambdaExpression extends FunctionalExpression implements IPolyExpre /** * Perform substitution with a {@link LocalTypeSubstitutor} on all types mentioned in the given method binding. */ - void updateLocalTypesInMethod(MethodBinding method) { + boolean updateLocalTypesInMethod(MethodBinding method) { if (this.localTypes == null) - return; + return false; updateLocalTypesInMethod(method, new LocalTypeSubstitutor(this.localTypes), new NullSubstitution(this.scope.environment())); + return true; } private void updateLocalTypesInMethod(MethodBinding method, Substitutor substor, Substitution subst) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java index ae5b3f49e..2634ce355 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java @@ -424,11 +424,10 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl if (variableTypeInferenceError) { return; } - boolean resolveAnnotationsEarly = false; if (scope.environment().usesNullTypeAnnotations() && !isTypeNameVar // 'var' does not provide a target type - && variableType.isValidBinding()) { + && variableType != null && variableType.isValidBinding()) { resolveAnnotationsEarly = this.initialization instanceof Invocation || this.initialization instanceof ConditionalExpression || this.initialization instanceof ArrayInitializer; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java index 26f75ffb0..62c16d28b 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java @@ -372,6 +372,11 @@ public void resolve(BlockScope scope) { if (methodType == null) return; + if (methodType.isProperType(true) && lambda != null) { + // ensure that type conversions don't leak a preliminary local type: + if (lambda.updateLocalTypesInMethod(lambda.descriptor)) + methodType = lambda.expectedResultType(); + } if (TypeBinding.notEquals(methodType, expressionType)) // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(methodType, expressionType); if (this.expression.isConstantValueOfTypeAssignableToType(expressionType, methodType) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java index ff1de21bf..135747305 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java @@ -238,7 +238,7 @@ public class IntersectionTypeBinding18 extends ReferenceBinding { } } if (classIdx > -1 && classIdx < Integer.MAX_VALUE) - return this.intersectingTypes[classIdx]; + return this.intersectingTypes[classIdx].erasure(); return this; } 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 c8ebc6922..d0f230d80 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 @@ -992,7 +992,7 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM } } } else { - packageBinding = this.module.getVisiblePackage(parent, constantPoolName[i]); + packageBinding = this.module.getVisiblePackage(parent, constantPoolName[i], true); } } if (packageBinding == null || packageBinding == TheNotFoundPackage) { 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 455058cdb..7cf8b0ed0 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 @@ -487,7 +487,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { binding = this.environment.getPackage0(name); if (binding != null) return binding; - binding = getVisiblePackage(null, name); + binding = getVisiblePackage(null, name, true); // remember: if (binding != null) { this.environment.knownPackages.put(name, binding); @@ -515,7 +515,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { return binding; } // Given parent is visible in this module, see if there is sub package named name visible in this module - PackageBinding getVisiblePackage(PackageBinding parent, char[] name) { + PackageBinding getVisiblePackage(PackageBinding parent, char[] name, boolean considerRequiredModules) { // check caches: char[][] parentName = parent == null ? CharOperation.NO_CHAR_CHAR : parent.compoundName; char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name); @@ -535,6 +535,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { } PackageBinding binding = null; + boolean packageMayBeIncomplete = !considerRequiredModules; if (this.environment.useModuleSystem) { IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment; char[][] declaringModuleNames = moduleEnv.getModulesDeclaringPackage(parentName, name, nameForLookup()); @@ -542,19 +543,23 @@ public class ModuleBinding extends Binding implements IUpdatableModule { if (!this.isUnnamed() && CharOperation.containsEqual(declaringModuleNames, this.moduleName)) { // declared here, not yet known, so create it now: binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this); - } else { + } else if (considerRequiredModules) { // visible but foreign (when current is unnamed or auto): for (char[] declaringModuleName : declaringModuleNames) { ModuleBinding declaringModule = this.environment.root.getModule(declaringModuleName); - if (declaringModule != null && !declaringModule.isPackageLookupActive) { - PackageBinding declaredPackage = declaringModule.getDeclaredPackage(parentName, name); - 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); - parent = null; - // - binding = SplitPackageBinding.combine(declaredPackage, binding, this); + if (declaringModule != null) { + if (declaringModule.isPackageLookupActive) { + packageMayBeIncomplete = true; + } else { + PackageBinding declaredPackage = declaringModule.getDeclaredPackage(parentName, name); + 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); + parent = null; + // + binding = SplitPackageBinding.combine(declaredPackage, binding, this); + } } } } @@ -566,11 +571,14 @@ public class ModuleBinding extends Binding implements IUpdatableModule { } // enrich with split-siblings from visible modules: - if (!isUnnamed()) { + if (!isUnnamed() && considerRequiredModules) { binding = combineWithPackagesFromRequired(binding, subPkgCompoundName); } - if (binding == null || !binding.isValidBinding()) + if (binding == null || !binding.isValidBinding()) { + if (parent != null && !packageMayBeIncomplete) // don't remember package that may still lack some siblings + parent.knownPackages.put(name, binding == null ? LookupEnvironment.TheNotFoundPackage : binding); return null; + } // remember if (parentName.length == 0) binding.environment.knownPackages.put(name, binding); @@ -598,7 +606,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { // check each sub package for (int i = 1; i < qualifiedPackageName.length; i++) { - PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i]); + PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i], true); if (binding == null || binding == LookupEnvironment.TheNotFoundPackage) { return null; } @@ -619,12 +627,12 @@ public class ModuleBinding extends Binding implements IUpdatableModule { // Returns a package binding if there exists such a package in the context of this module and it is observable // A package is observable if it is declared in this module or it is exported by some required module if (parentPackageName == null || parentPackageName.length == 0) { - return getVisiblePackage(null, packageName); + return getVisiblePackage(null, packageName, true); } PackageBinding binding = null; PackageBinding parent = getVisiblePackage(parentPackageName); if (parent != null && parent != LookupEnvironment.TheNotFoundPackage) { - binding = getVisiblePackage(parent, packageName); + binding = getVisiblePackage(parent, packageName, true); } if (binding != null) return addPackage(binding, false); 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 fd1c51a91..4b691535c 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 @@ -1703,9 +1703,11 @@ public abstract class Scope { ReferenceBinding sourceType = currentType.isParameterizedType() ? ((ParameterizedTypeBinding) currentType).genericType() : currentType; - if (sourceType.isHierarchyBeingConnected()) - return null; // looking for an undefined member type in its own superclass ref - ((SourceTypeBinding) sourceType).scope.connectTypeHierarchy(); + if (sourceType instanceof SourceTypeBinding) { // could be TypeVariableBinding + if (sourceType.isHierarchyBeingConnected()) + return null; // looking for an undefined member type in its own superclass ref + ((SourceTypeBinding) sourceType).scope.connectTypeHierarchy(); + } itsInterfaces = currentType.superInterfaces(); } if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { 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 f6133e895..ee2f19134 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 @@ -112,7 +112,7 @@ public class SplitPackageBinding extends PackageBinding { ModuleBinding moduleBinding = incarnation.enclosingModule; if (moduleBinding == module) continue; - PackageBinding next = moduleBinding.getVisiblePackage(incarnation, name); // TODO(SHMOD): reduce split-package work during this invocation? + PackageBinding next = moduleBinding.getVisiblePackage(incarnation, name, false); childPackage = combine(next, childPackage, primaryModule); } return childPackage; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java index 2327fcc57..a75bb883e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java @@ -26,6 +26,10 @@ import org.eclipse.jdt.internal.compiler.util.Util; * Parser specialized for decoding javadoc comments */ public class JavadocParser extends AbstractCommentParser { + private static final JavadocSingleNameReference[] NO_SINGLE_NAME_REFERENCE = new JavadocSingleNameReference[0]; + private static final JavadocSingleTypeReference[] NO_SINGLE_TYPE_REFERENCE = new JavadocSingleTypeReference[0]; + private static final TypeReference[] NO_TYPE_REFERENCE = new TypeReference[0]; + private static final Expression[] NO_EXPRESSION = new Expression[0]; // Public fields public Javadoc docComment; @@ -1001,12 +1005,12 @@ public class JavadocParser extends AbstractCommentParser { //{ObjectTeams: role references: this.docComment.roleReferences = new JavadocSingleTypeReference[sizes[ROLE_TAG_EXPECTED_ORDER]]; // SH} - this.docComment.seeReferences = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]]; - this.docComment.exceptionReferences = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]]; + this.docComment.seeReferences = sizes[SEE_TAG_EXPECTED_ORDER] > 0 ? new Expression[sizes[SEE_TAG_EXPECTED_ORDER]] : NO_EXPRESSION; + this.docComment.exceptionReferences = sizes[THROWS_TAG_EXPECTED_ORDER] > 0 ? new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]] : NO_TYPE_REFERENCE; int paramRefPtr = sizes[PARAM_TAG_EXPECTED_ORDER]; - this.docComment.paramReferences = new JavadocSingleNameReference[paramRefPtr]; + this.docComment.paramReferences = paramRefPtr > 0 ? new JavadocSingleNameReference[paramRefPtr] : NO_SINGLE_NAME_REFERENCE; int paramTypeParamPtr = sizes[PARAM_TAG_EXPECTED_ORDER]; - this.docComment.paramTypeParameters = new JavadocSingleTypeReference[paramTypeParamPtr]; + this.docComment.paramTypeParameters = paramTypeParamPtr > 0 ? new JavadocSingleTypeReference[paramTypeParamPtr] : NO_SINGLE_TYPE_REFERENCE; // Store nodes in arrays while (this.astLengthPtr >= 0) { 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 5ee4eb31b..8c661ac91 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 @@ -10994,6 +10994,9 @@ protected void consumeReferenceExpressionTypeForm(boolean isPrimitive) { // actu } else { referenceExpression.initialize(this.compilationUnit.compilationResult, getUnspecifiedReference(), typeArguments, selector, sourceEnd); } + if (CharOperation.equals(selector, TypeConstants.INIT) && referenceExpression.lhs instanceof NameReference) { + referenceExpression.lhs.bits &= ~Binding.VARIABLE; + } consumeReferenceExpression(referenceExpression); } protected void consumeReferenceExpressionPrimaryForm() { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java index 505da26ba..1604a57d4 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.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 @@ -375,4 +375,14 @@ public interface IJavaModelStatusConstants { */ public static final int TEST_OUTPUT_FOLDER_MUST_BE_SEPARATE_FROM_MAIN_OUTPUT_FOLDERS = 1016; + /** + * <p> + * Status constant indicating that the project has only main source folders but depends on a project that has only + * test source folders. + * </p> + * + * @since 3.16 + */ + public static final int MAIN_ONLY_PROJECT_DEPENDS_ON_TEST_ONLY_PROJECT = 1017; + } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java index 6b8f47281..20b09a0d6 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java @@ -451,9 +451,9 @@ public interface IPackageFragmentRoot void move(IPath destination, int updateResourceFlags, int updateModelFlags, IClasspathEntry sibling, IProgressMonitor monitor) throws JavaModelException; /** - * Returns the <code>IModuleDescription</code> that this package fragment root contains - * or <code>null</code> if the root doesn't contain any named module. If present the module - * descriptor is found as a child of the package fragment representing the default package. + * Returns the <code>IModuleDescription</code> that this package fragment root contains. + * Returns <code>null</code> if the root doesn't contain any named module or if the project compiler compliance is 1.8 or lower. + * If present the module descriptor is found as a child of the package fragment representing the default package. * * Note that only one of the source package fragment roots in a Java Project can legally * contain a module descriptor. diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java index fb4fb3a77..68bdc8255 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java @@ -2579,6 +2579,21 @@ public final class JavaCore extends Plugin { * @since 3.6.4 */ public static final String CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE = PLUGIN_ID + ".classpath.outputOverlappingAnotherSource"; //$NON-NLS-1$ + + /** + * Core option ID: Reporting if a project which has only main sources depends on a project with only test sources. + * <p> Indicate the severity of the problem reported when a project that has one or more main source folders but + * no test source folders has a project on its build path that only has one or more test source folders, but no main source folders.</p> + * + * <dl> + * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency"</code></dd> + * <dt>Possible values:</dt><dd><code>{ "error", "ignore" }</code></dd> + * <dt>Default:</dt><dd><code>"error"</code></dd> + * </dl> + * @since 3.16 + */ + public static final String CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY = PLUGIN_ID + ".classpath.mainOnlyProjectHasTestOnlyDependency"; //$NON-NLS-1$ + /** * Core option ID: Set the timeout value for retrieving the method's parameter names from javadoc. * <p>Timeout in milliseconds to retrieve the method's parameter names from javadoc.</p> @@ -4285,6 +4300,37 @@ public final class JavaCore extends Plugin { } /** + * Returns the option that can be used to configure the severity of the + * compiler build path problem identified by <code>id</code> if any, + * <code>null</code> otherwise. Non-null return values are taken from the + * constants defined by this class whose names start with + * <code>CORE_</code> and for which the possible values of the + * option are defined by <code>{ "error", "warning", "info", "ignore" }</code>. A + * null return value means that the provided id is unknown or that + * it matches a problem whose severity cannot be configured. + * @param id one of the build path problems defined in IJavaModelStatusConstants + * @return the option that can be used to configure the severity of the + * compiler problem identified by <code>id</code> if any, + * <code>null</code> otherwise + * @since 3.16 + */ + public static String getOptionForConfigurableBuildPathProblemSeverity(int id) { + switch (id) { + case IJavaModelStatusConstants.CLASSPATH_CYCLE: + return JavaCore.CORE_CIRCULAR_CLASSPATH; + case IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL: + return JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL; + case IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE: + return JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE; + case IJavaModelStatusConstants.MAIN_ONLY_PROJECT_DEPENDS_ON_TEST_ONLY_PROJECT: + return JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY; + case IJavaModelStatusConstants.INVALID_CLASSPATH: + return JavaCore.CORE_INCOMPLETE_CLASSPATH; + } + return null; + } + + /** * Returns the table of the current options. Initially, all options have their default values, * and this method returns a table that includes all known options. * <p> diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Annotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Annotation.java index 277edc5fc..fd01fd524 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Annotation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Annotation.java @@ -39,7 +39,7 @@ public class Annotation extends SourceRefElement implements IAnnotation { public Annotation(JavaElement parent, String name, String memberValuePairName) { super(parent); - this.name = name; + this.name = name.intern(); this.memberValuePairName = memberValuePairName; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java index 428a0c4fc..284fb648f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java @@ -1870,11 +1870,10 @@ public class ClasspathEntry implements IClasspathEntry { } catch(JavaModelException e){ return e.getJavaModelStatus(); } - int length = classpath.length; int outputCount = 1; - IPath[] outputLocations = new IPath[length+1]; - boolean[] allowNestingInOutputLocations = new boolean[length+1]; + IPath[] outputLocations = new IPath[classpath.length+1]; + boolean[] allowNestingInOutputLocations = new boolean[classpath.length+1]; outputLocations[0] = projectOutputLocation; // retrieve and check output locations @@ -1964,8 +1963,7 @@ public class ClasspathEntry implements IClasspathEntry { } } - for (int i = 0 ; i < length; i++) { - IClasspathEntry resolvedEntry = classpath[i]; + for (IClasspathEntry resolvedEntry : classpath) { IPath path = resolvedEntry.getPath(); int index; switch(resolvedEntry.getEntryKind()){ @@ -1991,8 +1989,7 @@ public class ClasspathEntry implements IClasspathEntry { } // check all entries - for (int i = 0 ; i < length; i++) { - IClasspathEntry entry = classpath[i]; + for (IClasspathEntry entry : classpath) { if (entry == null) continue; IPath entryPath = entry.getPath(); int kind = entry.getEntryKind(); @@ -2010,8 +2007,7 @@ public class ClasspathEntry implements IClasspathEntry { // allow nesting source entries in each other as long as the outer entry excludes the inner one if (kind == IClasspathEntry.CPE_SOURCE || (kind == IClasspathEntry.CPE_LIBRARY && (JavaModel.getTarget(entryPath, false/*don't check existence*/) instanceof IContainer))) { - for (int j = 0; j < classpath.length; j++){ - IClasspathEntry otherEntry = classpath[j]; + for (IClasspathEntry otherEntry : classpath) { if (otherEntry == null) continue; int otherKind = otherEntry.getEntryKind(); IPath otherPath = otherEntry.getPath(); @@ -2071,8 +2067,7 @@ public class ClasspathEntry implements IClasspathEntry { // diagnose nesting source folder issue before this one, for example, [src]"Project/", [src]"Project/source/" and output="Project/" should // first complain about missing exclusion pattern IJavaModelStatus cachedStatus = null; - for (int i = 0 ; i < length; i++) { - IClasspathEntry entry = classpath[i]; + for (IClasspathEntry entry : classpath) { if (entry == null) continue; IPath entryPath = entry.getPath(); int kind = entry.getEntryKind(); @@ -2084,8 +2079,7 @@ public class ClasspathEntry implements IClasspathEntry { if (kind == IClasspathEntry.CPE_SOURCE) { IPath output = entry.getOutputLocation(); if (output == null) output = projectOutputLocation; // if no specific output, still need to check using default output (this line would check default output) - for (int j = 0; j < length; j++) { - IClasspathEntry otherEntry = classpath[j]; + for (IClasspathEntry otherEntry : classpath) { if (otherEntry == entry) continue; switch (otherEntry.getEntryKind()) { @@ -2126,6 +2120,42 @@ public class ClasspathEntry implements IClasspathEntry { } } + if (hasSource && testSourcesFolders.size() == 0 && !JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, true))) { + for (IClasspathEntry entry : classpath) { + if (entry == null) + continue; + IPath entryPath = entry.getPath(); + if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { + if (entryPath.isAbsolute() && entryPath.segmentCount() == 1) { + IProject prereqProjectRsc = workspaceRoot.getProject(entryPath.segment(0)); + IJavaProject prereqProject = JavaCore.create(prereqProjectRsc); + boolean hasMain = false; + boolean hasTest = false; + try { + for (IClasspathEntry nested : prereqProject.getRawClasspath()) { + if (nested.getEntryKind() == IClasspathEntry.CPE_SOURCE) { + if (nested.isTest()) { + hasTest = true; + } else { + hasMain = true; + } + if (hasTest && hasMain) + break; + } + } + } catch (JavaModelException e) { + // is reported elsewhere + } + if (hasTest && !hasMain) { + return new JavaModelStatus(IJavaModelStatusConstants.MAIN_ONLY_PROJECT_DEPENDS_ON_TEST_ONLY_PROJECT, + Messages.bind(Messages.classpath_main_only_project_depends_on_test_only_project, + new String[] { prereqProject.getElementName() })); + } + } + } + } + } + // NOTE: The above code that checks for IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, can be configured to return // a WARNING status and hence should be at the end of this validation method. Any other code that might return a more severe ERROR should be // inserted before the mentioned code. 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 1fb75315a..9c13682bd 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 @@ -57,6 +57,7 @@ import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; public class ExternalFoldersManager { + private static final boolean WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows"); //$NON-NLS-1$//$NON-NLS-2$ private static final String EXTERNAL_PROJECT_NAME = ".org.eclipse.jdt.core.external.folders"; //$NON-NLS-1$ private static final String LINKED_FOLDER_NAME = ".link"; //$NON-NLS-1$ private Map<IPath, IFolder> folders; @@ -118,11 +119,12 @@ public class ExternalFoldersManager { if (externalPath == null || externalPath.isEmpty()) { return false; } + JavaModelManager manager = JavaModelManager.getJavaModelManager(); if (manager.isExternalFile(externalPath) || manager.isAssumedExternalFile(externalPath)) { return false; } - if (!externalPath.isAbsolute()) { + if (!externalPath.isAbsolute() || (WINDOWS && externalPath.getDevice() == null)) { // can be only project relative path return false; } @@ -142,12 +144,14 @@ public class ExternalFoldersManager { if (isInternalContainerPath(externalPath)) { return false; } + // From here on the legacy code assumes that not existing resource must be external. + // We just follow the old assumption. if (externalPath.getFileExtension() != null/*likely a .jar, .zip, .rar or other file*/) { manager.addAssumedExternalFile(externalPath); - // not existing external file + // assume not existing external (?) file (?) (can also be a folder with dotted name!) return false; } - // not existing external folder + // assume not existing external (?) folder (?) return true; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java index dfebdb8d1..ed85f3b54 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.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 @@ -79,6 +79,7 @@ public class JavaCorePreferenceInitializer extends AbstractPreferenceInitializer //{ObjectTeams: one more setting: defaultOptionsMap.put(JavaCore.AST_INCLUDES_ROLE_FILES, JavaCore.DISABLED); // SH} + defaultOptionsMap.put(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, JavaCore.ERROR); // encoding setting comes from resource plug-in optionNames.add(JavaCore.CORE_ENCODING); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java index 648cee83e..09250fcc7 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java @@ -1708,6 +1708,7 @@ public class JavaModelManager implements ISaveParticipant, IContentTypeChangeLis propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) || propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) || propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) || + propertyName.equals(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY) || propertyName.equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM) || propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE)) { JavaModelManager manager = JavaModelManager.getJavaModelManager(); @@ -2470,6 +2471,7 @@ public class JavaModelManager implements ISaveParticipant, IContentTypeChangeLis defaultOptionsMap.put(JavaCore.CORE_INCOMPLETE_CLASSPATH, JavaCore.ERROR); defaultOptionsMap.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.ERROR); defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE); + defaultOptionsMap.put(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, JavaCore.ERROR); defaultOptionsMap.put(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, JavaCore.ERROR); defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaCore.ENABLED); defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java index c170620af..abe02ffe9 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java @@ -1186,6 +1186,14 @@ public class JavaProject return; // setting == IGNORE } break; + case IJavaModelStatusConstants.MAIN_ONLY_PROJECT_DEPENDS_ON_TEST_ONLY_PROJECT: + setting = getOption(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, true); + if (JavaCore.ERROR.equals(setting)) { + severity = IMarker.SEVERITY_ERROR; + } else { + return; // setting == IGNORE + } + break; default: IPath path = status.getPath(); if (path != null) arguments = new String[] { path.toString() }; @@ -1945,6 +1953,7 @@ public class JavaProject propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) || propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE) || propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) || + propertyName.equals(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY) || propertyName.equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM)) { manager.deltaState.addClasspathValidation(JavaProject.this); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java index 702e50730..cd3e8158c 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java @@ -151,6 +151,11 @@ public class JrtPackageFragmentRoot extends JarPackageFragmentRoot implements IM } return null; } + + @Override + protected boolean isComplianceJava9OrHigher() { + return true; + } @Override public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String requestedModuleName) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java index 519c2c8e4..5d8f782c3 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java @@ -22,7 +22,9 @@ import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AutomaticModuleNaming; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; @@ -884,6 +886,13 @@ public String getClassFilePath(String classname) { } @Override public IModuleDescription getModuleDescription() { + if (isComplianceJava9OrHigher()) { + return getSourceModuleDescription(); + } + return null; +} + +private IModuleDescription getSourceModuleDescription() { try { IJavaElement[] pkgs = getChildren(); for (int j = 0, length = pkgs.length; j < length; j++) { @@ -959,4 +968,16 @@ public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName public Manifest getManifest() { return null; } + +protected boolean isComplianceJava9OrHigher() { + IJavaProject javaProject = getJavaProject(); + return isComplianceJava9OrHigher(javaProject); +} + +private static boolean isComplianceJava9OrHigher(IJavaProject javaProject) { + if (javaProject == null) { + return false; + } + return CompilerOptions.versionToJdkLevel(javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true)) >= ClassFileConstants.JDK9; +} } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java index 82e9c0243..f1fe4d648 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java @@ -192,6 +192,7 @@ public final class Messages extends NLS { public static String classpath_invalidExternalAnnotationPath; public static String classpath_testSourceRequiresSeparateOutputFolder; public static String classpath_testOutputFolderMustBeSeparateFromMainOutputFolders; + public static String classpath_main_only_project_depends_on_test_only_project; public static String file_notFound; public static String file_badFormat; public static String path_nullPath; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties index 7d00a513b..305dbb823 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties @@ -188,6 +188,7 @@ classpath_deprecated_variable = Classpath variable ''{0}'' in project ''{1}'' is classpath_invalidExternalAnnotationPath = Invalid external annotation path: ''{0}'' in project ''{1}'', for classpath entry ''{2}'' classpath_testSourceRequiresSeparateOutputFolder=Test source folder ''{0}'' in project ''{1}'' must have a separate output folder classpath_testOutputFolderMustBeSeparateFromMainOutputFolders=Test source folder ''{0}'' in project ''{1}'' must have an output folder that is not also used for main sources +classpath_main_only_project_depends_on_test_only_project=Project has only main sources but depends on project ''{0}'' which has only test sources. ### miscellaneous buffer_closed=Buffer is closed diff --git a/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF index 783aecc66..c6ce1807f 100644 --- a/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF @@ -3,4 +3,4 @@ Bundle-Name: Source of Eclipse Compiler for Java(TM) Bundle-SymbolicName: org.eclipse.jdt.core.compiler.batch.source Bundle-Version: 3.11.0.qualifier Bundle-Vendor: Eclipse.org -Eclipse-SourceBundle: org.eclipse.jdt.core.compiler.batch;version="3.11.0.${buildQualifier}";roots:="." +Eclipse-SourceBundle: org.eclipse.jdt.core.compiler.batch;version="${unqualifiedVersion}.${buildQualifier}";roots:="." |