diff options
author | Sasikanth Bharadwaj | 2018-01-03 05:53:59 +0000 |
---|---|---|
committer | Sasikanth Bharadwaj | 2018-02-05 08:53:43 +0000 |
commit | c680f4ac696c802eeda5ded62540b65f0c17a489 (patch) | |
tree | fb588bcaaac9a6d3b690bd81fa3d7e1aed4f74af | |
parent | b1c2a63442229d51e669de6df7b1c9d0e7e3af64 (diff) | |
download | eclipse.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
build
Change-Id: Ie2f16bb7c1177ebd091ad9797fca5935ebb0b76c
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); + } } /* |