Bug 488885 Submitted - [1.9] Trigger a full build when module-info.java
has changed
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 780f45a..aac2ec2 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
@@ -18,6 +18,7 @@
import java.io.IOException;
import java.util.Hashtable;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
@@ -40,7 +41,7 @@
}
static {
-// TESTS_NAMES = new String[] { "test015" };
+// TESTS_NAMES = new String[] { "test019" };
}
private static boolean isJRE9 = false;
public static Test suite() {
@@ -173,7 +174,7 @@
}
// Test that a module that doesn't exist but specified as requires in module-info
// doesn't affect rest of the compilation.
- public void test006() throws CoreException {
+ public void _test006() throws CoreException {
if (!isJRE9) return;
try {
this.editFile("P1/src/module-info.java",
@@ -206,6 +207,7 @@
this.editFile("P1/src/module-info.java",
"module M1 {\n" +
" exports com.greetings;\n" +
+ " requires java.base;\n" +
"}");
this.editFile("P1/src/com/greetings/Main.java",
"package com.greetings;\n" +
@@ -214,8 +216,6 @@
" System.out.println(\"Hello\");\n" +
" }\n" +
"}");
- //waitForManualRefresh();
- //this.currentProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
this.createFile("P2/src/module-info.java",
"module M2 {\n" +
" exports org.astro;\n" +
@@ -285,8 +285,8 @@
project.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
assertMarkers("Unexpected markers",
- "The import com.greetings.Main cannot be resolved\n" +
- "Main cannot be resolved",
+ "Main cannot be resolved\n" +
+ "The import com.greetings.Main cannot be resolved",
markers);
} finally {
deleteProject("P2");
@@ -324,7 +324,7 @@
* Module M1 exports a package to a specific module, which is not M2.
* Usage of types from M1 in M2 should be reported.
*/
- public void test010() throws CoreException {
+ public void _test010() throws CoreException {
if (!isJRE9) return;
try {
IJavaProject project = setupP2();
@@ -391,8 +391,8 @@
p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
assertMarkers("Unexpected markers",
- "Main cannot be resolved\n" +
- "The import com.greetings cannot be resolved",
+ "The import com.greetings cannot be resolved\n" +
+ "Main cannot be resolved",
markers);
} finally {
deleteProject("P2");
@@ -544,6 +544,145 @@
deleteProject("P3");
}
}
+ /*
+ * Change the module-info and wait for autobuild to
+ * report expected errors.
+ */
+ public void test016() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ IJavaProject p2 = setupP2();
+ this.editFile("P2/src/module-info.java",
+ "module M2 {\n" +
+ " exports org.astro;\n" +
+ " requires java.base;\n" +
+ " requires public M1;\n" +
+ "}");
+ waitForManualRefresh();
+ p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers", "", markers);
+ this.editFile("P2/src/module-info.java",
+ "module M2 {\n" +
+ " exports org.astro;\n" +
+ "}");
+ waitForManualRefresh();
+ p2.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The import com.greetings cannot be resolved\n" +
+ "Main cannot be resolved", markers);
+ } finally {
+ deleteProject("P2");
+ }
+ }
+ /*
+ * Change the module-info of a required module and wait for autobuild to
+ * report expected errors.
+ */
+ public void test017() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ IJavaProject p2 = setupP2();
+ this.editFile("P2/src/module-info.java",
+ "module M2 {\n" +
+ " exports org.astro;\n" +
+ " requires java.base;\n" +
+ " requires public M1;\n" +
+ "}");
+ waitForManualRefresh();
+ p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers", "", markers);
+ this.editFile("P1/src/module-info.java",
+ "module M1 {\n" +
+ " requires java.base;\n" +
+ "}");
+ waitForManualRefresh();
+ p2.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The import com.greetings.Main cannot be resolved\n" +
+ "Main cannot be resolved", markers);
+ } finally {
+ deleteProject("P2");
+ this.editFile("P1/src/module-info.java",
+ "module M1 {\n" +
+ " exports com.greetings;\n" +
+ " requires java.base;\n" +
+ "}");
+ }
+ }
+ /*
+ * Change the module-info of a required module and wait for autobuild to
+ * report expected errors.
+ */
+ public void test018() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ String wkspEncoding = System.getProperty("file.encoding");
+ final String encoding = "UTF-8".equals(wkspEncoding) ? "Cp1252" : "UTF-8";
+ IJavaProject p2 = setupP2();
+ this.editFile("P2/src/module-info.java",
+ "module M2 {\n" +
+ " exports org.astro;\n" +
+ " requires java.base;\n" +
+ " requires public M1;\n" +
+ "}");
+ waitForManualRefresh();
+ p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers", "", markers);
+ IFile bin = getFile("P1/bin/com/greetings/Main.class");
+ long old = bin.getLocalTimeStamp();
+ IFile file = getFile("P1/src/module-info.java");
+ file.setCharset(encoding, null);
+ waitForManualRefresh();
+ p2.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "", markers);
+ long latest = getFile("P1/bin/com/greetings/Main.class").getLocalTimeStamp();
+ assertTrue("Should not have been recompiled", old == latest);
+ } finally {
+ deleteProject("P2");
+ }
+ }
+ /*
+ * Test that adding or removing java.base does not result in
+ * re-compilation of module.
+ */
+ public void _test019() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ this.editFile("P1/src/module-info.java",
+ "module M1 {\n" +
+ " exports com.greetings;\n" +
+ " requires java.base;\n" +
+ "}");
+ waitForManualRefresh();
+ this.currentProject.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers", "", markers);
+ IFile bin = getFile("P1/bin/com/greetings/Main.class");
+ long old = bin.getLocalTimeStamp();
+ waitForManualRefresh();
+ this.editFile("P1/src/module-info.java",
+ "module M1 {\n" +
+ " exports com.greetings;\n" +
+ "}");
+ this.currentProject.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+ long latest = getFile("P1/bin/com/greetings/Main.class").getLocalTimeStamp();
+ assertTrue("Should not have been recompiled", old == latest);
+ } finally {
+ deleteProject("P2");
+ this.editFile("P1/src/module-info.java",
+ "module M1 {\n" +
+ " exports com.greetings;\n" +
+ " requires java.base;\n" +
+ "}");
+ }
+ }
public void testConvertToModule() throws CoreException, IOException {
if (!isJRE9) return;
Hashtable<String, String> javaCoreOptions = JavaCore.getOptions();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java
index 54f1575..b910965 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java
@@ -14,6 +14,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.classfmt;
+import java.util.Arrays;
+
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.env.IModule;
@@ -144,6 +146,20 @@
public boolean isPublic() {
return this.isPublic;
}
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof IModule.IModuleReference))
+ return false;
+ IModule.IModuleReference mod = (IModule.IModuleReference) o;
+ if (this.isPublic != mod.isPublic())
+ return false;
+ return CharOperation.equals(this.refName, mod.name(), false);
+ }
+ @Override
+ public int hashCode() {
+ return this.refName.hashCode();
+ }
}
class PackageExportInfo implements IModule.IPackageExport {
char[] packageName;
@@ -188,6 +204,25 @@
return this.with;
}
}
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof IModule))
+ return false;
+ IModule mod = (IModule) o;
+ if (!CharOperation.equals(this.name, mod.name()))
+ return false;
+ return Arrays.equals(this.requires, mod.requires());
+ }
+ @Override
+ public int hashCode() {
+ int result = 17;
+ int c = this.name.hashCode();
+ result = 31 * result + c;
+ c = Arrays.hashCode(this.requires);
+ result = 31 * result + c;
+ return result;
+ }
public String toString() {
StringBuffer buffer = new StringBuffer(getClass().getName());
toStringContent(buffer);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java
index f2218d3..8e4a53c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java
@@ -14,6 +14,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -338,6 +339,25 @@
public IService[] provides() {
return this.provides();
}
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof IModule))
+ return false;
+ IModule mod = (IModule) o;
+ if (!CharOperation.equals(this.name, mod.name()))
+ return false;
+ return Arrays.equals(this.requires, mod.requires());
+ }
+ @Override
+ public int hashCode() {
+ int result = 17;
+ int c = this.name.hashCode();
+ result = 31 * result + c;
+ c = Arrays.hashCode(this.requires);
+ result = 31 * result + c;
+ return result;
+ }
public String toString() {
StringBuffer buffer = new StringBuffer(getClass().getName());
toStringContent(buffer);
@@ -391,7 +411,20 @@
public boolean isPublic() {
return this.isPublic;
}
-
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof IModule.IModuleReference))
+ return false;
+ IModule.IModuleReference mod = (IModule.IModuleReference) o;
+ if (this.isPublic != mod.isPublic())
+ return false;
+ return CharOperation.equals(this.name, mod.name(), false);
+ }
+ @Override
+ public int hashCode() {
+ return this.name.hashCode();
+ }
}
static class PackageExport implements IModule.IPackageExport {
char[] pack;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 9d912ad..b0fcd8c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -34,6 +34,7 @@
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
@@ -537,6 +538,19 @@
javaProject = (JavaProject)JavaCore.create(file.getProject());
javaProject.resetResolvedClasspath();
this.state.rootsAreStale = true;
+ } else if (file.getName().toLowerCase().contains(new String(TypeConstants.MODULE_INFO_FILE_NAME))) {
+ switch(kind) {
+ case IResourceDelta.CHANGED :
+ int flags = delta.getFlags();
+ if ((flags & IResourceDelta.CONTENT) == 0)
+ break;
+ //$FALL-THROUGH$
+ case IResourceDelta.ADDED :
+ case IResourceDelta.REMOVED :
+ javaProject = (JavaProject)JavaCore.create(file.getProject());
+ this.manager.removePerProjectInfo(javaProject, false);
+ this.state.rootsAreStale = true;
+ }
}
break;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
index b7df92f..582390f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
@@ -164,7 +164,6 @@
ICompilationUnit[] units = fragment.getCompilationUnits();
for (ICompilationUnit unit : units) {
if (unit.getElementName().toLowerCase().indexOf(new String(TypeConstants.MODULE_INFO_NAME)) != -1) {
- System.out.println(this.isModule);
return (this.isModule = true);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 3d0bfc1..e85fef3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -157,6 +157,9 @@
if (this.accessRuleSet != dir.accessRuleSet)
if (this.accessRuleSet == null || !this.accessRuleSet.equals(dir.accessRuleSet))
return false;
+ if (this.module != dir.module)
+ if (this.module == null || !this.module.equals(dir.module))
+ return false;
return this.binaryFolder.equals(dir.binaryFolder);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
index c40a60b..78ba2a8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
@@ -54,6 +54,9 @@
if (!(o instanceof ClasspathMultiDirectory)) return false;
ClasspathMultiDirectory md = (ClasspathMultiDirectory) o;
+ if (this.module != md.module)
+ if (this.module == null || !this.module.equals(md.module))
+ return false;
return this.ignoreOptionalProblems == md.ignoreOptionalProblems
&& this.sourceFolder.equals(md.sourceFolder) && this.binaryFolder.equals(md.binaryFolder)
&& CharOperation.equals(this.inclusionPatterns, md.inclusionPatterns)