Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSasikanth Bharadwaj2018-01-03 05:53:59 +0000
committerSasikanth Bharadwaj2018-02-05 08:53:43 +0000
commitc680f4ac696c802eeda5ded62540b65f0c17a489 (patch)
treefb588bcaaac9a6d3b690bd81fa3d7e1aed4f74af
parentb1c2a63442229d51e669de6df7b1c9d0e7e3af64 (diff)
downloadeclipse.jdt.core-c680f4ac696c802eeda5ded62540b65f0c17a489.tar.gz
eclipse.jdt.core-c680f4ac696c802eeda5ded62540b65f0c17a489.tar.xz
eclipse.jdt.core-c680f4ac696c802eeda5ded62540b65f0c17a489.zip
Fixed bug 526310 - Making changes to 'Is modular' node does not trigger
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java4
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java6
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java3
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java706
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java85
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java9
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java10
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java67
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java32
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java91
13 files changed, 1004 insertions, 21 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java
index 15566b271c..56e6a51dc2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * Copyright (c) 2016, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,6 +20,7 @@ import org.eclipse.jdt.core.tests.model.Java9ElementTests;
import org.eclipse.jdt.core.tests.model.JavaConventionTests;
import org.eclipse.jdt.core.tests.model.JavaSearchBugs9Tests;
import org.eclipse.jdt.core.tests.model.ModuleBuilderTests;
+import org.eclipse.jdt.core.tests.model.ModuleOptionsTests;
import org.eclipse.jdt.core.tests.model.ResolveTests9;
import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
@@ -36,6 +37,7 @@ public class RunAllJava9Tests extends TestCase {
public static Class[] getAllTestClasses() {
return new Class[] {
ModuleBuilderTests.class,
+ ModuleOptionsTests.class,
Java9ElementTests.class,
JavaSearchBugs9Tests.class,
CompletionTests9.class,
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 74c1cdcaf1..ac0257d797 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -3257,6 +3257,10 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases {
new CompilerOptions(options).toString());
}
+ protected IPath getJRE9Path() {
+ return new Path(System.getProperty("java.home") + "/lib/jrt-fs.jar");
+ }
+
/**
* Wait for autobuild notification to occur
*/
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java
index 4c19df1418..c2ff7ff072 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -47,6 +47,7 @@ private static Class[] getAllTestClasses() {
JavaProjectTests.class,
// Modularity tests (Java 9)
ModuleBuilderTests.class,
+ ModuleOptionsTests.class,
// Compilation unit tests
CompilationUnitTests.class,
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
index 0f868ee6fb..4e29db6d52 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java
new file mode 100644
index 0000000000..543dcc7a62
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java
@@ -0,0 +1,706 @@
+/*******************************************************************************
+ * Copyright (c) 2018 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.tests.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+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.Path;
+import org.eclipse.jdt.core.IClasspathAttribute;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.core.ClasspathAttribute;
+import org.eclipse.jdt.internal.core.builder.ClasspathJrt;
+
+import junit.framework.Test;
+
+public class ModuleOptionsTests extends ModifyingResourceTests {
+
+ public ModuleOptionsTests(String name) {
+ super(name);
+ }
+
+ static {
+// TESTS_NAMES = new String[] { "testAddReads" };
+ }
+
+ private String savedModulesOption = null;
+ public static Test suite() {
+ return buildModelTestSuite(ModuleOptionsTests.class, BYTECODE_DECLARATION_ORDER);
+ }
+ public void setUpSuite() throws Exception {
+ super.setUpSuite();
+ this.savedModulesOption = System.getProperty("modules.to.load", "");
+ System.setProperty("modules.to.load", "");
+ JRTUtil.reset();
+ ClasspathJrt.resetCaches();
+ }
+ public void tearDownSuite() throws Exception {
+ System.setProperty("modules.to.load", this.savedModulesOption);
+ super.tearDownSuite();
+ }
+ // testing auto rebuild after change of limit-modules
+ public void testLimitModules3() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.LIMIT_MODULES, "java.se") // test transitive closure
+ };
+ IJavaProject project = createJava9ProjectWithJREAttributes("org.astro", new String[]{"src", "src2"}, attributes);
+
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" +
+ " requires java.sql;\n" +
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "class Test2 {\n" +
+ " java.awt.Window window;\n" +
+ "}\n",
+ "src2/org/astro/Test3.java",
+ "package org.astro;\n" +
+ "class Test3 {\n" +
+ " java.awt.datatransfer.Clipboard clippy;\n" +
+ "}\n"
+ };
+ createSourceFiles(project, sources);
+
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+
+ IClasspathAttribute[] newLimits = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.LIMIT_MODULES, "java.base,java.sql") // no more awt etc
+ };
+ setJRECPAttributes(project, newLimits);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ Arrays.sort(markers, (a,b) -> a.getAttribute(IMarker.CHAR_START, 0) - b.getAttribute(IMarker.CHAR_START, 0));
+ assertMarkers("Unexpected markers",
+ "java.awt cannot be resolved to a type\n" +
+ "java.awt cannot be resolved to a type\n" +
+ "java.desktop cannot be resolved to a module\n" +
+ "java.datatransfer cannot be resolved to a module",
+ markers);
+ } finally {
+ this.deleteProject("org.astro");
+ }
+ }
+ public void testAddExports() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" +
+ " requires java.sql;\n" +
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "public class Test2 {\n" +
+ " java.awt.Window window;\n" +
+ "}\n",
+ "src2/org/astro/Test3.java",
+ "package org.astro;\n" +
+ "class Test3 {\n" +
+ " java.awt.datatransfer.Clipboard clippy;\n" +
+ "}\n"
+ };
+ IJavaProject project = setupModuleProject("org.astro", new String[] {"src", "src2"}, sources, null);
+
+ sources = new String[] {
+ "src/module-info.java",
+ "module test {\n" +
+ " requires org.astro;\n" +
+ "}\n",
+ "src/test/Test.java",
+ "package test;\n" +
+ "class Test {\n" +
+ " org.astro.Test2 t;\n" +
+ "}\n"
+ };
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test")
+ };
+ IClasspathEntry cp = JavaCore.newProjectEntry(project.getPath(), null, false, attributes, false);
+ IJavaProject p2 = setupModuleProject("test", sources, new IClasspathEntry[] {cp});
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+
+ IClasspathAttribute[] newAttrs = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")
+ };
+ setCPAttributes(p2, newAttrs, cp);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The type org.astro.Test2 is not accessible",
+ markers);
+ } finally {
+ this.deleteProject("org.astro");
+ this.deleteProject("test");
+ }
+ }
+
+ public void testAddExports_JRE() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" +
+ " requires java.sql;\n" +
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "public class Test2 {\n" +
+ " int test(jdk.internal.misc.Unsafe unsafe) {\n" +
+ " return unsafe.addressSize();\n" +
+ " }" +
+ "}\n",
+ };
+ IClasspathAttribute[] attrs = new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "java.base/jdk.internal.misc=org.astro")
+ };
+ IJavaProject project = createJava9ProjectWithJREAttributes("org.astro", new String[] {"src"}, attrs);
+ createSourceFiles(project, sources);
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+
+ IClasspathAttribute[] newAttrs = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")
+ };
+ setJRECPAttributes(project, newAttrs);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The type jdk.internal.misc.Unsafe is not accessible",
+ markers);
+ } finally {
+ this.deleteProject("org.astro");
+ }
+ }
+ public void testAddExports_multi() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" +
+ " requires java.sql;\n" +
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "public class Test2 {\n" +
+ " java.awt.Window window;\n" +
+ "}\n",
+ "src2/org/astro/sub/Test3.java",
+ "package org.astro.sub;\n" +
+ "public class Test3 {\n" +
+ " java.awt.datatransfer.Clipboard clippy;\n" +
+ "}\n"
+ };
+ IJavaProject project = setupModuleProject("org.astro", new String[] {"src", "src2"}, sources, null);
+
+ sources = new String[] {
+ "src/module-info.java",
+ "module test {\n" +
+ " requires org.astro;\n" +
+ "}\n",
+ "src/test/Test.java",
+ "package test;\n" +
+ "class Test {\n" +
+ " org.astro.Test2 t;\n" +
+ " org.astro.sub.Test3 t3;\n" +
+ "}\n"
+ };
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test")
+ };
+ IClasspathEntry cp = JavaCore.newProjectEntry(project.getPath(), null, false, attributes, false);
+ IJavaProject p2 = setupModuleProject("test", sources, new IClasspathEntry[] {cp});
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The type org.astro.sub.Test3 is not accessible",
+ markers);
+
+ IClasspathAttribute[] newAttrs = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test:org.astro/org.astro.sub=test")
+ };
+ setCPAttributes(p2, newAttrs, cp);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+ } finally {
+ this.deleteProject("org.astro");
+ this.deleteProject("test");
+ }
+ }
+ public void testAddExports_classFolder() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" +
+ " requires java.sql;\n" +
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "public class Test2 {\n" +
+ " java.awt.Window window;\n" +
+ "}\n",
+ "src2/org/astro/sub/Test3.java",
+ "package org.astro.sub;\n" +
+ "public class Test3 {\n" +
+ " java.awt.datatransfer.Clipboard clippy;\n" +
+ "}\n"
+ };
+ IJavaProject project = setupModuleProject("org.astro", new String[] {"src", "src2"}, sources, null);
+
+ sources = new String[] {
+ "src/module-info.java",
+ "module test {\n" +
+ " requires org.astro;\n" +
+ "}\n",
+ "src/test/Test.java",
+ "package test;\n" +
+ "class Test {\n" +
+ " org.astro.Test2 t;\n" +
+ " org.astro.sub.Test3 t3;\n" +
+ "}\n"
+ };
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test")
+ };
+ IClasspathEntry cp = JavaCore.newLibraryEntry(project.getProject().findMember("bin").getFullPath(), null,
+ null, null, attributes, false);
+ IJavaProject p2 = setupModuleProject("test", sources, new IClasspathEntry[] {cp});
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The type org.astro.sub.Test3 is not accessible",
+ markers);
+
+ IClasspathAttribute[] newAttrs = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test:org.astro/org.astro.sub=test")
+ };
+ setCPAttributes(p2, newAttrs, cp);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+ } finally {
+ this.deleteProject("org.astro");
+ this.deleteProject("test");
+ }
+ }
+ public void testAddReads() throws CoreException, IOException {
+ if (!isJRE9) return;
+ String libPath = "externalLib/mod.one.jar";
+ try {
+ String[] sources = new String[] {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " exports org.astro;\n" +
+ "}",
+ "src/org/astro/World.java",
+ "package org.astro;\n" +
+ "public interface World {\n" +
+ " public String name();\n" +
+ "}"
+ };
+ IJavaProject p = setupModuleProject("org.astro", sources);
+
+ String[] src1 = new String[] {
+ "src/module-info.java",
+ "module mod.one {\n" +
+ " exports one.p;\n" +
+ "}\n",
+ "src/org/astro/World.java",
+ "package org.astro;\n" +
+ "public interface World { public String name(); }\n",
+ "src/one/p/C.java",
+ "package one.p;\n" +
+ "public class C implements org.astro.World {\n" +
+ " public String name() {\n" +
+ " return \"C\";\n" +
+ " }\n" +
+ "}\n"
+ };
+ IJavaProject p1 = setupModuleProject("mod.one", src1);
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ // jar-up without the required class, should be supplied by the other module
+ deleteFile("/mod.one/src/org/astro/World.java");
+ deleteFile("/mod.one/bin/org/astro/World.class");
+ File rootDir = new File(p1.getProject().findMember("bin").getLocation().toString());
+ Util.zip(rootDir, getExternalResourcePath(libPath));
+
+ String[] src2 = new String[] {
+ "src/module-info.java",
+ "module com.greetings {\n" +
+ " requires mod.one;\n" +
+ "}",
+ "src/com/greetings/MyTest.java",
+ "package com.greetings;\n" +
+ "public class MyTest extends one.p.C {}"
+ };
+ IClasspathEntry dep1 = JavaCore.newProjectEntry(p.getPath(), null, false,
+ new IClasspathAttribute[] {new ClasspathAttribute("module", "true")},
+ false/*not exported*/);
+ IClasspathEntry dep2 = JavaCore.newLibraryEntry(new Path(getExternalResourcePath(libPath)), null, null, null,
+ new IClasspathAttribute[] {
+ new ClasspathAttribute("module", "true"),
+ new ClasspathAttribute(IClasspathAttribute.ADD_READS, "mod.one=org.astro")
+ },
+ false/*not exported*/);
+ IJavaProject p2 = setupModuleProject("com.greetings", src2, new IClasspathEntry[] { dep1, dep2 });
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers", "", markers);
+ IClasspathAttribute[] attrs = new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")
+ };
+ setCPAttributes(p2, attrs, dep2);
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The project was not built since its build path is incomplete. Cannot find the class file for org.astro.World. Fix the build path then try building this project\n" +
+ "The type org.astro.World cannot be resolved. It is indirectly referenced from required .class files",
+ markers);
+ } finally {
+ deleteExternalResource(libPath);
+ deleteProject("mod.one");
+ deleteProject("org.astro");
+ deleteProject("com.greetings");
+ }
+ }
+ public void testAddReads2() throws CoreException, IOException {
+ if (!isJRE9) return;
+ String libPath = "externalLib/mod.one.jar";
+ try {
+ String[] sources = new String[] {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " exports org.astro;\n" +
+ "}",
+ "src/org/astro/World.java",
+ "package org.astro;\n" +
+ "public interface World {\n" +
+ " public String name();\n" +
+ "}"
+ };
+ IJavaProject p = setupModuleProject("org.astro", sources);
+
+ String[] src1 = new String[] {
+ "src/module-info.java",
+ "module mod.one {\n" +
+ " exports one.p;\n" +
+ "}\n",
+ "src/org/astro/World.java",
+ "package org.astro;\n" +
+ "public interface World { public String name(); }\n",
+ "src/one/p/C.java",
+ "package one.p;\n" +
+ "public class C implements org.astro.World {\n" +
+ " public String name() {\n" +
+ " return \"C\";\n" +
+ " }\n" +
+ "}\n"
+ };
+ IJavaProject p1 = setupModuleProject("mod.one", src1);
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ // jar-up without the required class, should be supplied by the other module
+ deleteFile("/mod.one/src/org/astro/World.java");
+ deleteFile("/mod.one/bin/org/astro/World.class");
+ File rootDir = new File(p1.getProject().findMember("bin").getLocation().toString());
+ Util.zip(rootDir, getExternalResourcePath(libPath));
+
+ String[] src2 = new String[] {
+ "src/module-info.java",
+ "module com.greetings {\n" +
+ " requires mod.one;\n" +
+ "}",
+ "src/com/greetings/MyTest.java",
+ "package com.greetings;\n" +
+ "public class MyTest extends one.p.C {}"
+ };
+ IClasspathEntry dep1 = JavaCore.newProjectEntry(p.getPath(), null, false,
+ new IClasspathAttribute[] {new ClasspathAttribute("module", "true")},
+ false/*not exported*/);
+ IClasspathEntry dep2 = JavaCore.newLibraryEntry(new Path(getExternalResourcePath(libPath)), null, null, null,
+ new IClasspathAttribute[] {
+ new ClasspathAttribute("module", "true"),
+ },
+ false/*not exported*/);
+ IJavaProject p2 = setupModuleProject("com.greetings", src2, new IClasspathEntry[] { dep1, dep2 });
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The project was not built since its build path is incomplete. Cannot find the class file for org.astro.World. Fix the build path then try building this project\n" +
+ "The type org.astro.World cannot be resolved. It is indirectly referenced from required .class files",
+ markers);
+ IClasspathAttribute[] attrs = new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_READS, "mod.one=org.astro")
+ };
+ setCPAttributes(p2, attrs, dep2);
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+ markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers", "", markers);
+ } finally {
+ deleteExternalResource(libPath);
+ deleteProject("mod.one");
+ deleteProject("org.astro");
+ deleteProject("com.greetings");
+ }
+ }
+ public void _testPatchModule() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" +
+ " requires java.sql;\n" +
+ " exports org.astro;\n" +
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "public class Test2 {\n" +
+ " java.awt.Window window;\n" +
+ "}\n"
+ };
+ IJavaProject project = setupModuleProject("org.astro", sources);
+
+ sources = new String[] {
+ "src/code/Code.java",
+ "package code;\n" +
+ "class Code {\n" +
+ "}\n",
+ "src2/org/astro/Galaxy.java",
+ "package org.astro;\n" +
+ "public class Galaxy { }\n"
+ };
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ };
+ IClasspathEntry cp = JavaCore.newProjectEntry(project.getPath(), null, false, attributes, false);
+ IJavaProject p2 = setupModuleProject("patch", new String[] {"src", "src2"}, sources, null);
+ attributes = new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "org.astro")
+ };
+ IClasspathEntry cp2 = JavaCore.newProjectEntry(p2.getPath(), null, false, attributes, false);
+ sources = new String[] {
+ "src/module-info.java",
+ "module test {\n" +
+ " requires org.astro;\n" +
+ "}\n",
+ "src/test/Test.java",
+ "package test;\n" +
+ "class Test {\n" +
+ " org.astro.World w = null;\n" +
+ " org.astro.Galaxy g = null;\n" +
+ "}\n",
+ };
+ IJavaProject p3 = setupModuleProject("test", sources, new IClasspathEntry[] {cp, cp2});
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+ } finally {
+ this.deleteProject("org.astro");
+ this.deleteProject("patch");
+ this.deleteProject("test");
+ }
+
+ }
+ public void testPatchModule() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")
+ };
+ IJavaProject patchProject = createJava9ProjectWithJREAttributes("org.astro.patch", new String[]{"src", "src2"}, attributes);
+
+ String[] patchSources = {
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "class Test2 {\n" +
+ " int test(jdk.internal.misc.Unsafe unsafe) {\n" +
+ " return unsafe.addressSize();\n" +
+ " }\n" +
+ "}\n",
+ "src2/jdk/internal/misc/Test3.java",
+ "package jdk.internal.misc;\n" +
+ "class Test3 {\n" +
+ " Signal.NativeHandler handler;\n" + // package access
+ "}\n"
+ };
+ createSourceFiles(patchProject, patchSources);
+
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = patchProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The type jdk.internal.misc.Unsafe is not accessible\n" +
+ "Signal cannot be resolved to a type",
+ markers);
+
+ attributes = new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "java.base")
+ };
+ setJRECPAttributes(patchProject, attributes);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ markers = patchProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "",
+ markers);
+ } finally {
+ this.deleteProject("org.astro.patch");
+ }
+ }
+ public void testPatchModule2() throws CoreException, IOException {
+ if (!isJRE9) return;
+ try {
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "java.base")
+ };
+ IJavaProject patchProject = createJava9ProjectWithJREAttributes("org.astro.patch", new String[]{"src", "src2"}, attributes);
+
+ String[] patchSources = {
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "class Test2 {\n" +
+ " int test(jdk.internal.misc.Unsafe unsafe) {\n" +
+ " return unsafe.addressSize();\n" +
+ " }\n" +
+ "}\n",
+ "src2/jdk/internal/misc/Test3.java",
+ "package jdk.internal.misc;\n" +
+ "class Test3 {\n" +
+ " Signal.NativeHandler handler;\n" + // package access
+ "}\n"
+ };
+ createSourceFiles(patchProject, patchSources);
+
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+ attributes = new IClasspathAttribute[] {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ };
+ setJRECPAttributes(patchProject, attributes);
+
+ getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+
+ IMarker[] markers = patchProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "The type jdk.internal.misc.Unsafe is not accessible\n" +
+ "Signal cannot be resolved to a type",
+ markers);
+ } finally {
+ this.deleteProject("org.astro.patch");
+ }
+ }
+ private void setCPAttributes(IJavaProject javaProject, IClasspathAttribute[] attributes, IClasspathEntry entryToReplace) throws JavaModelException {
+ IClasspathEntry[] oldClasspath= javaProject.getRawClasspath();
+ int nEntries= oldClasspath.length;
+ IClasspathEntry[] newEntries= Arrays.copyOf(oldClasspath, nEntries);
+ for (int i = 0; i < newEntries.length; i++) {
+ if (newEntries[i].getPath().equals(entryToReplace.getPath())) {
+ switch(entryToReplace.getEntryKind()) {
+ case IClasspathEntry.CPE_PROJECT:
+ newEntries[i] = JavaCore.newProjectEntry(entryToReplace.getPath(), entryToReplace.getAccessRules(), entryToReplace.combineAccessRules(), attributes, entryToReplace.isExported());
+ break;
+ case IClasspathEntry.CPE_LIBRARY:
+ newEntries[i] = JavaCore.newLibraryEntry(entryToReplace.getPath(), newEntries[i].getSourceAttachmentPath(), null, null, attributes, false);
+ break;
+ default:
+ // not supported
+ break;
+ }
+ break;
+ }
+ }
+ javaProject.setRawClasspath(newEntries, null);
+ }
+ private void setJRECPAttributes(IJavaProject javaProject, IClasspathAttribute[] attributes) throws JavaModelException {
+ IClasspathEntry[] oldClasspath= javaProject.getRawClasspath();
+ int nEntries= oldClasspath.length;
+ IClasspathEntry[] newEntries= Arrays.copyOf(oldClasspath, nEntries);
+ for (int i = 0; i < newEntries.length; i++) {
+ if (newEntries[i].getPath().equals(getJRE9Path())) {
+ newEntries[i] = JavaCore.newLibraryEntry(getJRE9Path(), newEntries[i].getSourceAttachmentPath(), null, null, attributes, false);
+ break;
+ }
+ }
+ javaProject.setRawClasspath(newEntries, null);
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
index 1a2d237a37..f851a342cf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 GK Software AG, and others.
+ * Copyright (c) 2017, 2018 GK Software AG, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
/**
@@ -29,6 +30,88 @@ public interface IUpdatableModule {
*/
enum UpdateKind { MODULE, PACKAGE }
+ class AddExports implements Consumer<IUpdatableModule> {
+
+ char[] name;
+ char[][] targets;
+ public AddExports(char[] pkgName, char[][] targets) {
+ this.name = pkgName;
+ this.targets = targets;
+ }
+ @Override
+ public void accept(IUpdatableModule t) {
+ // TODO Auto-generated method stub
+ t.addExports(this.name, this.targets);
+ }
+
+ public char[] getName() {
+ return this.name;
+ }
+
+ public char[][] getTargetModules() {
+ return this.targets;
+ }
+
+ public UpdateKind getKind() {
+ return UpdateKind.PACKAGE;
+ }
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) return true;
+ if (!(other instanceof AddExports)) return false;
+ AddExports pu = (AddExports) other;
+
+ if (!CharOperation.equals(this.name, pu.name))
+ return false;
+ if (!CharOperation.equals(this.targets, pu.targets))
+ return false;
+ return true;
+ }
+ @Override
+ public int hashCode() {
+ int hash = CharOperation.hashCode(this.name);
+ if (this.targets != null) {
+ for (int i = 0; i < this.targets.length; i++) {
+ hash += 17 * CharOperation.hashCode(this.targets[i]);
+ }
+ }
+ return hash;
+ }
+ }
+
+ class AddReads implements Consumer<IUpdatableModule> {
+
+ char[] targetModule;
+
+ public AddReads(char[] target) {
+ this.targetModule = target;
+ }
+ @Override
+ public void accept(IUpdatableModule t) {
+ // TODO Auto-generated method stub
+ t.addReads(this.targetModule);
+ }
+
+ public char[] getTarget() {
+ return this.targetModule;
+ }
+
+ public UpdateKind getKind() {
+ return UpdateKind.MODULE;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) return true;
+ if (!(other instanceof AddReads)) return false;
+ AddReads mu = (AddReads) other;
+ return CharOperation.equals(this.targetModule, mu.targetModule);
+ }
+ @Override
+ public int hashCode() {
+ return CharOperation.hashCode(this.targetModule);
+ }
+ }
/** Structure for update operations, sorted by {@link UpdateKind}. */
class UpdatesByKind {
List<Consumer<IUpdatableModule>> moduleUpdates = Collections.emptyList();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
index 16947f99d1..c9696d1da1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 GK Software AG, and others.
+ * Copyright (c) 2017, 2018 GK Software AG, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -62,7 +62,7 @@ public class ModuleUpdater {
String modName = value.substring(0, slash);
char[] packName = value.substring(slash+1, equals).toCharArray();
char[][] targets = CharOperation.splitOn(',', value.substring(equals+1).toCharArray());
- addModuleUpdate(modName, m -> m.addExports(packName, targets), UpdateKind.PACKAGE);
+ addModuleUpdate(modName, new IUpdatableModule.AddExports(packName, targets), UpdateKind.PACKAGE);
} else {
Util.log(IStatus.WARNING, "Invalid argument to add-exports: "+value); //$NON-NLS-1$
}
@@ -73,7 +73,7 @@ public class ModuleUpdater {
if (equals != -1) {
String srcMod = value.substring(0, equals);
char[] targetMod = value.substring(equals+1).toCharArray();
- addModuleUpdate(srcMod, m -> m.addReads(targetMod), UpdateKind.MODULE);
+ addModuleUpdate(srcMod, new IUpdatableModule.AddReads(targetMod), UpdateKind.MODULE);
} else {
Util.log(IStatus.WARNING, "Invalid argument to add-reads: "+value); //$NON-NLS-1$
}
@@ -108,4 +108,7 @@ public class ModuleUpdater {
}
}
}
+ public UpdatesByKind getUpdates(String moduleName) {
+ return this.moduleUpdates.get(moduleName);
+ }
}
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 74f3332b74..a0ea9eb5b0 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -136,10 +136,10 @@ public boolean equals(Object o) {
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);
+ if (this.isOnModulePath != dir.isOnModulePath)
+ return false;
+
+ return this.binaryFolder.equals(dir.binaryFolder) && areAllModuleOptionsEqual(dir);
}
public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
if (!doesFileExist(binaryFileName, qualifiedPackageName, qualifiedBinaryFileName)) return null; // most common case
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 210c43ce41..b433fc0804 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -207,7 +207,8 @@ public boolean equals(Object o) {
return false;
return this.zipFilename.equals(jar.zipFilename)
&& lastModified() == jar.lastModified()
- && this.isOnModulePath == jar.isOnModulePath;
+ && this.isOnModulePath == jar.isOnModulePath
+ && areAllModuleOptionsEqual(jar);
}
public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
index 855525db79..e40883856d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * Copyright (c) 2016, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -181,7 +181,8 @@ public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClasspathJrt)) return false;
ClasspathJrt jar = (ClasspathJrt) o;
- return this.zipFilename.endsWith(jar.zipFilename);
+
+ return this.zipFilename.endsWith(jar.zipFilename) && areAllModuleOptionsEqual(jar);
}
@Override
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index 938151fd31..bdbe6e5056 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,12 +12,18 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.util.Util;
@@ -25,6 +31,9 @@ public abstract class ClasspathLocation {
protected boolean isOnModulePath;
protected IModule module;
+ protected IUpdatableModule.UpdatesByKind updates;
+ protected Set<String> limitModuleNames = null;
+ protected String patchModuleName = null;
// In the following signatures, passing a null moduleName signals "don't care":
abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName);
abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly);
@@ -45,6 +54,62 @@ public abstract class ClasspathLocation {
public IModule getModule() {
return this.module;
}
+ protected boolean areAllModuleOptionsEqual(ClasspathLocation other) {
+ if (this.patchModuleName != null) {
+ if (other.patchModuleName == null)
+ return false;
+ if (!this.patchModuleName.equals(other.patchModuleName))
+ return false;
+ } else {
+ if (other.patchModuleName != null)
+ return false;
+ }
+ if (this.limitModuleNames != null) {
+ if (other.limitModuleNames == null)
+ return false;
+ if (other.limitModuleNames.size() != this.limitModuleNames.size())
+ return false;
+ if (!this.limitModuleNames.containsAll(other.limitModuleNames))
+ return false;
+ } else {
+ if (other.limitModuleNames != null)
+ return false;
+ }
+ if (this.updates != null) {
+ if (other.updates == null)
+ return false;
+ List<Consumer<IUpdatableModule>> packageUpdates = this.updates.getList(UpdateKind.PACKAGE, false);
+ List<Consumer<IUpdatableModule>> otherPackageUpdates = other.updates.getList(UpdateKind.PACKAGE, false);
+ if (packageUpdates != null) {
+ if (otherPackageUpdates == null)
+ return false;
+ if (packageUpdates.size() != otherPackageUpdates.size())
+ return false;
+ if (!packageUpdates.containsAll(otherPackageUpdates))
+ return false;
+ } else {
+ if (otherPackageUpdates != null)
+ return false;
+ }
+ List<Consumer<IUpdatableModule>> moduleUpdates = this.updates.getList(UpdateKind.MODULE, false);
+ List<Consumer<IUpdatableModule>> otherModuleUpdates = other.updates.getList(UpdateKind.MODULE, false);
+ if (moduleUpdates != null) {
+ if (otherModuleUpdates == null)
+ return false;
+ if (moduleUpdates.size() != otherModuleUpdates.size())
+ return false;
+ if (!moduleUpdates.containsAll(otherModuleUpdates))
+ return false;
+ } else {
+ if (otherModuleUpdates != null)
+ return false;
+ }
+ } else {
+ if (other.updates != null)
+ return false;
+ }
+ return true;
+ }
static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder,
char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) {
return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index bcf5f72c6c..054b11c4bb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -23,6 +23,7 @@ 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.*;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
@@ -33,6 +34,7 @@ import org.eclipse.jdt.internal.core.*;
import java.io.*;
import java.util.*;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
@SuppressWarnings({"rawtypes", "unchecked"})
@@ -162,6 +164,7 @@ private void computeClasspathLocations(
entry.ignoreOptionalProblems());
if (patchedModule != null) {
ModuleEntryProcessor.combinePatchIntoModuleEntry(sourceLocation, patchedModule, moduleEntries);
+ sourceLocation.patchModuleName = patchedModuleName;
}
sLocations.add(sourceLocation);
continue nextEntry;
@@ -221,6 +224,12 @@ private void computeClasspathLocations(
ModulePathEntry projectEntry = new ModulePathEntry(prereqJavaProject.getPath(), info,
projectLocations.toArray(new ClasspathLocation[projectLocations.size()]));
String moduleName = String.valueOf(info.name());
+ IUpdatableModule.UpdatesByKind updates = this.moduleUpdater.getUpdates(moduleName);
+ for (ClasspathLocation loc : projectLocations) {
+ loc.limitModuleNames = limitModules;
+ loc.updates = updates;
+ loc.patchModuleName = patchedModuleName;
+ }
if (limitModules == null || limitModules.contains(moduleName)) {
moduleEntries.put(moduleName, projectEntry);
if (moduleName.equals(patchedModuleName))
@@ -339,8 +348,28 @@ IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean is
String patchedModuleName, IModule patchedModule, Map<String, IModulePathEntry> moduleEntries) {
if (bLocation instanceof IMultiModuleEntry) {
IMultiModuleEntry binaryModulePathEntry = (IMultiModuleEntry) bLocation;
+ bLocation.limitModuleNames = limitModules;
+ bLocation.patchModuleName = patchedModuleName;
+ IUpdatableModule.UpdatesByKind updates = null;//new IUpdatableModule.UpdatesByKind();
+ IUpdatableModule.UpdatesByKind finalUpdates = new IUpdatableModule.UpdatesByKind();
+ List<Consumer<IUpdatableModule>> packageUpdates = null;
+ List<Consumer<IUpdatableModule>> moduleUpdates = null;
for (String moduleName : binaryModulePathEntry.getModuleNames(limitModules)) {
moduleEntries.put(moduleName, binaryModulePathEntry);
+ updates = this.moduleUpdater.getUpdates(moduleName);
+ if (updates != null) {
+ List<Consumer<IUpdatableModule>> pu = updates.getList(UpdateKind.PACKAGE, false);
+ if (pu != null) {
+ (packageUpdates = finalUpdates.getList(UpdateKind.PACKAGE, true)).addAll(pu);
+ }
+ List<Consumer<IUpdatableModule>> mu = updates.getList(UpdateKind.MODULE, false);
+ if (mu != null) {
+ (moduleUpdates = finalUpdates.getList(UpdateKind.MODULE, true)).addAll(mu);
+ }
+ }
+ }
+ if (packageUpdates != null || moduleUpdates != null) {
+ bLocation.updates = finalUpdates;
}
if (patchedModuleName != null) {
IModule module = binaryModulePathEntry.getModule(patchedModuleName.toCharArray());
@@ -353,6 +382,9 @@ IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean is
IModule module = binaryModulePathEntry.getModule();
if (module != null) {
String moduleName = String.valueOf(module.name());
+ bLocation.updates = this.moduleUpdater.getUpdates(moduleName);
+ bLocation.limitModuleNames = limitModules;
+ bLocation.patchModuleName = patchedModuleName;
if (limitModules == null || limitModules == ClasspathJrt.NO_LIMIT_MODULES || limitModules.contains(moduleName)) {
moduleEntries.put(moduleName, binaryModulePathEntry);
if (patchedModuleName != null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index a6d5695a59..2ea610af87 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,6 +17,8 @@ import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.*;
import org.eclipse.jdt.internal.compiler.env.AccessRule;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
@@ -25,6 +27,8 @@ import org.eclipse.jdt.internal.core.JavaModelManager;
import java.io.*;
import java.util.*;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
@SuppressWarnings({"rawtypes", "unchecked"})
public class State {
@@ -281,6 +285,38 @@ static State read(IProject project, DataInputStream in) throws IOException {
newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())),
readRestriction(in), new Path(in.readUTF()), in.readBoolean());
}
+ ClasspathLocation loc = newState.binaryLocations[i];
+ char[] patchName = readName(in);
+ loc.patchModuleName = patchName.length > 0 ? new String(patchName) : null;
+ int limitSize = in.readInt();
+ if (limitSize != 0) {
+ loc.limitModuleNames = new HashSet<>(limitSize);
+ for (int j = 0; j < limitSize; j++) {
+ loc.limitModuleNames.add(in.readUTF());
+ }
+ } else {
+ loc.limitModuleNames = null;
+ }
+ IUpdatableModule.UpdatesByKind updates = new IUpdatableModule.UpdatesByKind();
+ List<Consumer<IUpdatableModule>> packageUpdates = null;
+ int packageUpdatesSize = in.readInt();
+ if (packageUpdatesSize != 0) {
+ packageUpdates = updates.getList(UpdateKind.PACKAGE, true);
+ for (int j = 0; j < packageUpdatesSize; j++) {
+ char[] pkgName = readName(in);
+ char[][] targets = readNames(in);
+ packageUpdates.add(new AddExports(pkgName, targets));
+ }
+ }
+ List<Consumer<IUpdatableModule>> moduleUpdates = null;
+ int moduleUpdatesSize = in.readInt();
+ if (moduleUpdatesSize != 0) {
+ moduleUpdates = updates.getList(UpdateKind.MODULE, true);
+ char[] modName = readName(in);
+ moduleUpdates.add(new AddReads(modName));
+ }
+ if (packageUpdates != null || moduleUpdates != null)
+ loc.updates = updates;
}
newState.structuralBuildTimes = new SimpleLookupTable(length = in.readInt());
@@ -443,14 +479,14 @@ void write(DataOutputStream out) throws IOException {
* String path(s)
*/
out.writeInt(length = this.binaryLocations.length);
- next : for (int i = 0; i < length; i++) {
+ for (int i = 0; i < length; i++) {
ClasspathLocation c = this.binaryLocations[i];
if (c instanceof ClasspathMultiDirectory) {
out.writeByte(SOURCE_FOLDER);
for (int j = 0, m = this.sourceLocations.length; j < m; j++) {
if (this.sourceLocations[j] == c) {
out.writeInt(j);
- continue next;
+ //continue next;
}
}
} else if (c instanceof ClasspathDirectory) {
@@ -482,6 +518,55 @@ void write(DataOutputStream out) throws IOException {
writeRestriction(null, out);
out.writeUTF(""); //$NON-NLS-1$
}
+ char[] patchName = c.patchModuleName == null ? CharOperation.NO_CHAR : c.patchModuleName.toCharArray();
+ writeName(patchName, out);
+ if (c.limitModuleNames != null) {
+ out.writeInt(c.limitModuleNames.size());
+ for (String name : c.limitModuleNames) {
+ out.writeUTF(name);
+ }
+ } else {
+ out.writeInt(0);
+ }
+ if (c.updates != null) {
+ List<Consumer<IUpdatableModule>> pu = c.updates.getList(UpdateKind.PACKAGE, false);
+ if (pu != null) {
+ Map<String, List<Consumer<IUpdatableModule>>> map = pu.stream().
+ collect(Collectors.groupingBy(
+ update -> CharOperation.charToString(((IUpdatableModule.AddExports)update).getName())));
+ out.writeInt(map.size());
+ map.entrySet().stream().forEach(entry -> {
+ String pkgName = entry.getKey();
+ try {
+ writeName(pkgName.toCharArray(), out);
+ char[][] targetModules = entry.getValue().stream()
+ .map(consumer -> ((IUpdatableModule.AddExports) consumer).getTargetModules())
+ .filter(targets -> targets != null)
+ .reduce((f,s) -> CharOperation.arrayConcat(f,s))
+ .orElse(null);
+ writeNames(targetModules, out);
+ } catch (IOException e) {
+ // ignore
+ }
+
+ });
+ } else {
+ out.writeInt(0);
+ }
+ List<Consumer<IUpdatableModule>> mu = c.updates.getList(UpdateKind.MODULE, false);
+ if (mu != null) {
+ out.writeInt(mu.size());
+ for (Consumer<IUpdatableModule> cons : mu) {
+ AddReads m = (AddReads) cons;
+ writeName(m.getTarget(), out);
+ }
+ } else {
+ out.writeInt(0);
+ }
+ } else {
+ out.writeInt(0);
+ out.writeInt(0);
+ }
}
/*

Back to the top