This is an automated email from the ASF dual-hosted git repository. lkishalmi pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new c90f7cd [NETBEANS-2004] Initial support for modular java project in Gradle (#1276) c90f7cd is described below commit c90f7cd496e5be8094dcb5f86c642aae6835e086 Author: Laszlo Kishalmi <laszlo.kisha...@gmail.com> AuthorDate: Tue Jun 4 07:55:10 2019 -0700 [NETBEANS-2004] Initial support for modular java project in Gradle (#1276) * [NETBEANS-2004] Added boot module patch support. * [NETBEANS-2004] Watch on module-info.java changes. * [NETBEANS-2004] First take on supporting MODULE classpaths * [NETBEANS-2004] Made Stacktrace processor module aware. --- groovy/gradle.java/nbproject/project.xml | 9 + .../gradle/java/SourceGroupResourceWatchList.java | 8 + .../classpath/AbstractGradleClassPathImpl.java | 3 - .../gradle/java/classpath/BootClassPathImpl.java | 18 +- .../java/classpath/ClassPathProviderImpl.java | 253 +++++++++++++++++++-- .../java/output/JavaCompilerProcessorFactory.java | 26 ++- java/java.api.common/nbproject/project.xml | 1 + 7 files changed, 276 insertions(+), 42 deletions(-) diff --git a/groovy/gradle.java/nbproject/project.xml b/groovy/gradle.java/nbproject/project.xml index a282767..d2f27ff 100644 --- a/groovy/gradle.java/nbproject/project.xml +++ b/groovy/gradle.java/nbproject/project.xml @@ -156,6 +156,15 @@ </run-dependency> </dependency> <dependency> + <code-name-base>org.netbeans.modules.java.api.common</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>0</release-version> + <specification-version>1.127</specification-version> + </run-dependency> + </dependency> + <dependency> <code-name-base>org.netbeans.modules.java.source.base</code-name-base> <build-prerequisite/> <compile-dependency/> diff --git a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/SourceGroupResourceWatchList.java b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/SourceGroupResourceWatchList.java index 82c4f1e..7dfe4db 100644 --- a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/SourceGroupResourceWatchList.java +++ b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/SourceGroupResourceWatchList.java @@ -28,6 +28,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.netbeans.api.project.Project; +import org.netbeans.modules.gradle.java.classpath.ClassPathProviderImpl; +import org.netbeans.spi.java.classpath.ClassPathProvider; import org.netbeans.spi.project.ProjectServiceProvider; /** @@ -51,6 +53,12 @@ public class SourceGroupResourceWatchList implements WatchedResourceProvider { ret = new HashSet<>(); for (GradleJavaSourceSet ss : gjp.getSourceSets().values()) { ret.addAll(ss.getAllDirs()); + for (File dir : ss.getJavaDirs()) { + ret.add(new File(dir, ClassPathProviderImpl.MODULE_INFO_JAVA)); + } + for (File dir : ss.getGroovyDirs()) { + ret.add(new File(dir, ClassPathProviderImpl.MODULE_INFO_JAVA)); + } } } return ret; diff --git a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java index 69f3732..e275ea5 100644 --- a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java +++ b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/AbstractGradleClassPathImpl.java @@ -24,7 +24,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; -import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; @@ -35,9 +34,7 @@ import org.netbeans.api.project.Project; import org.netbeans.spi.java.classpath.ClassPathImplementation; import org.netbeans.spi.java.classpath.PathResourceImplementation; import org.netbeans.spi.java.classpath.support.ClassPathSupport; -import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; -import org.openide.util.Utilities; import org.openide.util.WeakListeners; /** diff --git a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java index bf0dfe9..0c3599f 100644 --- a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java +++ b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/BootClassPathImpl.java @@ -39,12 +39,19 @@ import org.openide.util.WeakListeners; * @author Laszlo Kishalmi */ public final class BootClassPathImpl extends AbstractGradleClassPathImpl implements PropertyChangeListener { + private static final String PROTOCOL_NBJRT = "nbjrt"; //NOI18N JavaPlatformManager platformManager; + final boolean modulesOnly; - @SuppressWarnings("LeakingThisInConstructor") public BootClassPathImpl(Project proj) { + this(proj, false); + } + + @SuppressWarnings("LeakingThisInConstructor") + public BootClassPathImpl(Project proj, boolean modulesOnly) { super(proj); + this.modulesOnly = modulesOnly; platformManager = JavaPlatformManager.getDefault(); platformManager.addPropertyChangeListener(WeakListeners.propertyChange(this, platformManager)); NbGradleProject.getPreferences(project, false).addPreferenceChangeListener(new PreferenceChangeListener() { @@ -56,7 +63,7 @@ public final class BootClassPathImpl extends AbstractGradleClassPathImpl impleme } }); } - + @Override public void propertyChange(PropertyChangeEvent evt) { clearResourceCache(); @@ -68,11 +75,14 @@ public final class BootClassPathImpl extends AbstractGradleClassPathImpl impleme List<URL> ret = new LinkedList<>(); if (platform != null) { for (ClassPath.Entry entry : platform.getBootstrapLibraries().entries()) { - ret.add(entry.getURL()); + URL root = entry.getURL(); + if (!modulesOnly || PROTOCOL_NBJRT.equals(root.getProtocol())) { + ret.add(root); + } } } return ret; } - + } diff --git a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java index ad7839e..f527cfd 100644 --- a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java +++ b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/classpath/ClassPathProviderImpl.java @@ -24,22 +24,31 @@ import org.netbeans.modules.gradle.api.NbGradleProject; import org.netbeans.modules.gradle.java.api.GradleJavaProject; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; +import org.netbeans.modules.java.api.common.classpath.ClassPathSupportFactory; import org.netbeans.api.java.classpath.ClassPath; -import org.netbeans.api.java.classpath.JavaClassPathConstants; import org.netbeans.api.project.Project; import org.netbeans.spi.java.classpath.ClassPathFactory; import org.netbeans.spi.java.classpath.ClassPathProvider; +import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.netbeans.spi.project.ProjectServiceProvider; import org.netbeans.spi.project.ui.ProjectOpenedHook; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; +import org.openide.util.Utilities; +import static org.netbeans.api.java.classpath.ClassPath.*; +import static org.netbeans.api.java.classpath.JavaClassPathConstants.*; /** * * @author Laszlo Kishalmi @@ -48,16 +57,21 @@ import org.openide.filesystems.FileUtil; projectType = NbGradleProject.GRADLE_PLUGIN_TYPE + "/java-base") public final class ClassPathProviderImpl extends ProjectOpenedHook implements ClassPathProvider { - private static final Set<String> SUPPORTED_PATHS = new HashSet<>(); + public static final String MODULE_INFO_JAVA = "module-info.java"; // NOI18N + private static final Set<String> SUPPORTED_PATHS = new HashSet<>(Arrays.asList( + SOURCE, + BOOT, + COMPILE, + EXECUTE, + PROCESSOR_PATH, + MODULE_BOOT_PATH, + MODULE_COMPILE_PATH, + MODULE_CLASS_PATH, + MODULE_EXECUTE_PATH, + MODULE_EXECUTE_CLASS_PATH + )); - static { - SUPPORTED_PATHS.add(ClassPath.SOURCE); - SUPPORTED_PATHS.add(ClassPath.BOOT); - SUPPORTED_PATHS.add(ClassPath.COMPILE); - SUPPORTED_PATHS.add(ClassPath.EXECUTE); - SUPPORTED_PATHS.add(JavaClassPathConstants.PROCESSOR_PATH); - } private final Map<String, SourceSetCP> groups = new HashMap<>(); private final Project project; @@ -79,6 +93,18 @@ public final class ClassPathProviderImpl extends ProjectOpenedHook implements Cl } } + if (NbGradleProject.PROP_RESOURCES.endsWith(evt.getPropertyName())) { + URI uri = (URI) evt.getNewValue(); + if ((uri != null) && (uri.getPath() != null) && uri.getPath().endsWith(MODULE_INFO_JAVA)) { + GradleJavaProject gjp = GradleJavaProject.get(ClassPathProviderImpl.this.project); + if (gjp != null) { + GradleJavaSourceSet ss = gjp.containingSourceSet(Utilities.toFile(uri)); + if ((ss != null) && (groups.get(ss.getName()) != null)) { + groups.get(ss.getName()).reset(); + } + } + } + } } }; } @@ -133,29 +159,210 @@ public final class ClassPathProviderImpl extends ProjectOpenedHook implements Cl } private class SourceSetCP { - final ClassPath boot; - final ClassPath source; - final ClassPath compile; - final ClassPath runtime; + ClassPath boot; + ClassPath source; + ClassPath compile; + ClassPath runtime; + + ClassPath platformModules; + + ClassPath compileTime; + ClassPath runTime; + + ClassPath moduleBoot; + ClassPath moduleCompile; + ClassPath moduleLegacy; + ClassPath moduleExecute; + ClassPath moduleLegacyRuntime; + + final String group; + List<SourceSetAwareSelector> selectors = new ArrayList<>(); SourceSetCP(String group) { - boot = ClassPathFactory.createClassPath(new BootClassPathImpl(project)); - source = ClassPathFactory.createClassPath(new SourceClassPathImpl(project, group)); - compile = ClassPathFactory.createClassPath(new CompileClassPathImpl(project, group)); - runtime = ClassPathFactory.createClassPath(new RuntimeClassPathImpl(project, group)); + this.group = group; } public ClassPath getClassPath(String type) { switch (type) { - case ClassPath.BOOT: return boot; - case ClassPath.SOURCE: return source; - case ClassPath.COMPILE: return compile; - case ClassPath.EXECUTE: return runtime; - case JavaClassPathConstants.PROCESSOR_PATH: return compile; + case BOOT: return getBootClassPath(); + case SOURCE: return getSourcepath(); + case COMPILE: return getCompileTimeClasspath(); + case EXECUTE: return getRuntimeClassPath(); + + case MODULE_BOOT_PATH: return getModuleBoothPath(); + case MODULE_COMPILE_PATH: return getModuleCompilePath(); + case MODULE_CLASS_PATH: return getModuleLegacyClassPath(); + case MODULE_EXECUTE_PATH: return getModuleExecutePath(); + case MODULE_EXECUTE_CLASS_PATH: return getModuleLegacyRuntimeClassPath(); + + case PROCESSOR_PATH: return getCompileTimeClasspath(); + default: return null; } } - } + private synchronized ClassPath getCompileTimeClasspath() { + if (compileTime == null) { + compileTime = createMultiplexClassPath( + ClassPathFactory.createClassPath( + ClassPathSupportFactory.createModuleInfoBasedPath( + getModuleCompilePath(), + getSourcepath(), + getModuleBoothPath(), + getModuleCompilePath(), + getJava8CompileClassPath(), + null) + ), + getJava8CompileClassPath() + ); + } + return compileTime; + } + + private synchronized ClassPath getRuntimeClassPath() { + if (runTime == null) { + runTime = createMultiplexClassPath( + ClassPathFactory.createClassPath( + ClassPathSupportFactory.createModuleInfoBasedPath( + getJava8RuntimeClassPath(), + getSourcepath(), + getModuleBoothPath(), + getJava8RuntimeClassPath(), + getJava8RuntimeClassPath(), + null) + ), + getJava8CompileClassPath() + ); + } + return runTime; + } + + private synchronized ClassPath getModuleLegacyClassPath() { + if (moduleLegacy == null) { + moduleLegacy = createMultiplexClassPath(EMPTY, getJava8CompileClassPath()); + } + return moduleLegacy; + } + private synchronized ClassPath getModuleExecutePath() { + if (moduleExecute == null) { + moduleExecute = createMultiplexClassPath(getJava8RuntimeClassPath(), EMPTY); + } + return moduleExecute; + } + + private synchronized ClassPath getModuleLegacyRuntimeClassPath() { + if (moduleLegacyRuntime == null) { + moduleLegacyRuntime = createMultiplexClassPath(EMPTY, getJava8RuntimeClassPath()); + } + return moduleLegacyRuntime; + } + + private synchronized ClassPath getBootClassPath() { + if (boot == null) { + boot = ClassPathFactory.createClassPath(new BootClassPathImpl(project, false)); + } + return boot; + } + + private synchronized ClassPath getSourcepath() { + if (source == null) { + source = ClassPathFactory.createClassPath(new SourceClassPathImpl(project, group)); + } + return source; + } + + private synchronized ClassPath getJava8CompileClassPath() { + if (compile == null) { + compile = ClassPathFactory.createClassPath(new CompileClassPathImpl(project, group)); + } + return compile; + } + + private synchronized ClassPath getPlatformModulesPath() { + if (platformModules == null) { + platformModules = ClassPathFactory.createClassPath(new BootClassPathImpl(project, true)); + } + return platformModules; + } + private synchronized ClassPath getJava8RuntimeClassPath() { + if (runtime == null) { + runtime = ClassPathFactory.createClassPath(new RuntimeClassPathImpl(project, group)); + } + return runtime; + } + + private synchronized ClassPath getModuleBoothPath() { + if (moduleBoot == null) { + //TODO: Is this Ok? Made after the Maven's ClassPathProviderImpl.getModuleBootPath + moduleBoot = createMultiplexClassPath(getPlatformModulesPath(), getPlatformModulesPath()); + } + return moduleBoot; + } + + private synchronized ClassPath getModuleCompilePath() { + if (moduleCompile == null) { + moduleCompile = createMultiplexClassPath(getJava8CompileClassPath(), ClassPath.EMPTY); + } + return moduleCompile; + } + + private ClassPath createMultiplexClassPath(ClassPath modulePath, ClassPath classPath) { + SourceSetAwareSelector selector = new SourceSetAwareSelector(modulePath, classPath); + selectors.add(selector); + return org.netbeans.spi.java.classpath.support.ClassPathSupport.createMultiplexClassPath(selector); + } + + public boolean hasModuleInfo() { + GradleJavaProject gjp = GradleJavaProject.get(ClassPathProviderImpl.this.project); + GradleJavaSourceSet ss = gjp.getSourceSets().get(group); + return ss != null && ss.findResource(MODULE_INFO_JAVA, false, GradleJavaSourceSet.SourceType.JAVA) != null; + } + + public void reset() { + for (SourceSetAwareSelector selector : selectors) { + selector.reset(); + } + } + + private class SourceSetAwareSelector implements ClassPathSupport.Selector { + PropertyChangeSupport support = new PropertyChangeSupport(this); + + final ClassPath modulePath; + final ClassPath classPath; + + ClassPath active; + + public SourceSetAwareSelector(ClassPath modulePath, ClassPath classPath) { + this.modulePath = modulePath; + this.classPath = classPath; + } + + @Override + public ClassPath getActiveClassPath() { + if (active == null) { + active = hasModuleInfo() ? modulePath : classPath; + } + return active; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + support.addPropertyChangeListener(listener); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + support.removePropertyChangeListener(listener); + } + + private void reset() { + ClassPath oldActive = active; + active = hasModuleInfo() ? modulePath : classPath; + if (oldActive != active) { + support.firePropertyChange(PROP_ACTIVE_CLASS_PATH, null, null); + } + } + } + } } diff --git a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/output/JavaCompilerProcessorFactory.java b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/output/JavaCompilerProcessorFactory.java index cdc4534..c7837ed 100644 --- a/groovy/gradle.java/src/org/netbeans/modules/gradle/java/output/JavaCompilerProcessorFactory.java +++ b/groovy/gradle.java/src/org/netbeans/modules/gradle/java/output/JavaCompilerProcessorFactory.java @@ -24,10 +24,8 @@ import org.netbeans.modules.gradle.api.execute.RunConfig; import org.netbeans.modules.gradle.api.output.OutputDisplayer; import org.netbeans.modules.gradle.api.output.OutputProcessor; import org.netbeans.modules.gradle.api.output.OutputProcessorFactory; -import org.netbeans.modules.gradle.api.output.OutputListeners; import org.netbeans.modules.gradle.java.api.output.LocationOpener; import org.netbeans.modules.gradle.spi.GradleSettings; -import java.io.File; import java.net.URL; import java.util.Arrays; import java.util.HashSet; @@ -41,7 +39,6 @@ import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.netbeans.spi.project.ProjectServiceProvider; import org.openide.awt.StatusDisplayer; import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; import org.openide.filesystems.URLMapper; import org.openide.windows.IOColors; import org.netbeans.modules.gradle.java.api.ProjectSourcesClassPathProvider; @@ -60,7 +57,7 @@ public class JavaCompilerProcessorFactory implements OutputProcessorFactory { private static class StackTraceProcessor implements OutputProcessor { - private static final Pattern STACKTRACE_PATTERN = Pattern.compile("(.*)at (\\w[\\w\\.\\$<>]*)\\((\\w+)\\.java\\:([0-9]+)\\)(.*)"); + private static final Pattern STACKTRACE_PATTERN = Pattern.compile("(.*)at ((\\w[\\w\\.]*)/)?(\\w[\\w\\.\\$<>]*)\\((\\w+)\\.java\\:([0-9]+)\\)(.*)"); private static final IOColors.OutputType OUT_TYPE = IOColors.OutputType.ERROR; private final Project project; private final ClassPath classPath; @@ -81,10 +78,12 @@ public class JavaCompilerProcessorFactory implements OutputProcessorFactory { Matcher m = STACKTRACE_PATTERN.matcher(line); if (m.matches()) { String prefix = m.group(1); - String method = m.group(2); - String fileName = m.group(3); - String lineNum = m.group(4); - String postfix = m.group(5); + String modulePrefix = m.group(2); + //String module = m.group(3); + String method = m.group(4); + String fileName = m.group(5); + String lineNum = m.group(6); + String postfix = m.group(7); int ppos = method.indexOf(fileName); if ((ppos >= 0) && (project != null)) { @@ -95,7 +94,10 @@ public class JavaCompilerProcessorFactory implements OutputProcessorFactory { Runnable action = openFileAt(classPath, javaName, lineInt); - out.print(prefix).print("at ", null, OUT_TYPE ).print(method, null, OUT_TYPE).print("(", null, OUT_TYPE); + out.print(prefix).print("at ", null, OUT_TYPE) + .print(modulePrefix, null, OUT_TYPE) + .print(method, null, OUT_TYPE) + .print("(", null, OUT_TYPE); out.print(fileName + ".java:" + lineNum, action); out.print(")" + postfix, null, OUT_TYPE); return true; @@ -104,7 +106,7 @@ public class JavaCompilerProcessorFactory implements OutputProcessorFactory { return false; } } - + private static Runnable openFileAt(final ClassPath classPath, final String fileName, final int line) { return new Runnable() { @Override @@ -133,8 +135,8 @@ public class JavaCompilerProcessorFactory implements OutputProcessorFactory { StatusDisplayer.getDefault().setStatusText("Not found: " + fileName); } } - + }; } - + } diff --git a/java/java.api.common/nbproject/project.xml b/java/java.api.common/nbproject/project.xml index 094c5fe..1b16363 100644 --- a/java/java.api.common/nbproject/project.xml +++ b/java/java.api.common/nbproject/project.xml @@ -449,6 +449,7 @@ <friend>org.netbeans.modules.apisupport.ant</friend> <friend>org.netbeans.modules.avatar_js.project</friend> <friend>org.netbeans.modules.cnd.mixeddev</friend> + <friend>org.netbeans.modules.gradle.java</friend> <friend>org.netbeans.modules.groovy.grailsproject</friend> <friend>org.netbeans.modules.hudson.ant</friend> <friend>org.netbeans.modules.j2ee.archive</friend> --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists