This is an automated email from the ASF dual-hosted git repository.
sdedic 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 1715954033 Allow to find precise output folder for each language.
(#4287)
1715954033 is described below
commit 1715954033e443c043f2e9845d449f4fbf70d883
Author: Svatopluk Dedic <[email protected]>
AuthorDate: Mon Jul 11 10:56:40 2022 +0200
Allow to find precise output folder for each language. (#4287)
Allow to find precise output folder for each language.
---
.../gradle/tooling/NbProjectInfoBuilder.java | 96 +++++++++++++++++++---
.../modules/gradle/cache/ProjectInfoDiskCache.java | 2 +-
java/gradle.java/apichanges.xml | 13 +++
java/gradle.java/manifest.mf | 2 +-
.../gradle/java/api/GradleJavaProjectBuilder.java | 5 ++
.../gradle/java/api/GradleJavaSourceSet.java | 26 ++++++
.../gradle/java/queries/GradleSourceForBinary.java | 52 ++++++++++--
7 files changed, 176 insertions(+), 20 deletions(-)
diff --git
a/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java
b/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java
index 346fe53226..ff2e93c938 100644
---
a/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java
+++
b/extide/gradle/netbeans-gradle-tooling/src/main/java/org/netbeans/modules/gradle/tooling/NbProjectInfoBuilder.java
@@ -22,12 +22,14 @@ package org.netbeans.modules.gradle.tooling;
import groovy.lang.MissingPropertyException;
import java.io.File;
import java.io.Serializable;
+import java.nio.file.Path;
import java.util.ArrayList;
import static java.util.Arrays.asList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -58,6 +60,7 @@ import org.gradle.api.attributes.Attribute;
import org.gradle.api.attributes.AttributeContainer;
import org.gradle.api.distribution.DistributionContainer;
import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.initialization.IncludedBuild;
import org.gradle.api.plugins.JavaPlatformPlugin;
import org.gradle.api.specs.Specs;
@@ -267,6 +270,29 @@ class NbProjectInfoBuilder {
.forEach(e ->
nbprops.put(e.getKey().substring(NB_PREFIX.length()),
String.valueOf(e.getValue())));
model.getInfo().put("nbprops", nbprops);
}
+
+ private Path longestPrefixPath(List<Path> files) {
+ if (files.size() < 2) {
+ return null;
+ }
+ Path first = files.get(0);
+ Path result = null;
+ Path root = first.getRoot();
+ int count = first.getNameCount();
+ for (int i = 1; i <= count; i++) {
+ Path match = root != null ? root.resolve(first.subpath(0, i)) :
first.subpath(0, i);
+
+ for (int pi = 1; pi < files.size(); pi++) {
+ Path p = files.get(pi);
+ if (!p.startsWith(match)) {
+ return result;
+ }
+ }
+ result = match;
+ }
+ // if all paths (more than one) are the same, something is strange.
+ return null;
+ }
private void detectSources(NbProjectInfoModel model) {
long time = System.currentTimeMillis();
@@ -277,15 +303,36 @@ class NbProjectInfoBuilder {
boolean hasKotlin =
project.getPlugins().hasPlugin("org.jetbrains.kotlin.android") ||
project.getPlugins().hasPlugin("org.jetbrains.kotlin.js") ||
project.getPlugins().hasPlugin("org.jetbrains.kotlin.jvm");
-
+ Map<String, Boolean> available = new HashMap<>();
+ available.put("java", hasJava);
+ available.put("groovy", hasGroovy);
+ available.put("kotlin", hasKotlin);
+
if (hasJava) {
SourceSetContainer sourceSets = (SourceSetContainer)
getProperty(project, "sourceSets");
if (sourceSets != null) {
model.getInfo().put("sourcesets",
storeSet(sourceSets.getNames()));
for(SourceSet sourceSet: sourceSets) {
String propBase = "sourceset_" + sourceSet.getName() + "_";
+
+ Set<File> outDirs = new LinkedHashSet<>();
+ sinceGradle("4.0", () -> {
+ // classesDirs is just an iterable
+ for (File dir: (ConfigurableFileCollection)
getProperty(sourceSet, "output", "classesDirs")) {
+ outDirs.add(dir);
+ }
+ });
+ beforeGradle("4.0", () -> {
+ outDirs.add((File)getProperty(sourceSet, "output",
"classesDir"));
+ });
+
+ List<Path> outPaths =
outDirs.stream().map(File::toPath).collect(Collectors.toList());
+ // find the longest common prefix:
+ Path base = longestPrefixPath(outPaths);
+
for(String lang: new String[] {"JAVA", "GROOVY", "SCALA",
"KOTLIN"}) {
- Task compileTask =
project.getTasks().findByName(sourceSet.getCompileTaskName(lang.toLowerCase()));
+ String langId = lang.toLowerCase();
+ Task compileTask =
project.getTasks().findByName(sourceSet.getCompileTaskName(langId));
if (compileTask != null) {
model.getInfo().put(
propBase + lang + "_source_compatibility",
@@ -307,6 +354,39 @@ class NbProjectInfoBuilder {
}
model.getInfo().put(propBase + lang +
"_compiler_args", new ArrayList<>(compilerArgs));
}
+ if (Boolean.TRUE.equals(available.get(langId))) {
+ model.getInfo().put(propBase + lang,
storeSet(getProperty(sourceSet, langId, "srcDirs")));
+ DirectoryProperty dirProp =
(DirectoryProperty)getProperty(sourceSet, langId, "classesDirectory");
+ if (dirProp != null) {
+ File outDir;
+
+ if (dirProp.isPresent()) {
+ outDir = dirProp.get().getAsFile();
+ } else {
+ // kotlin plugin uses some weird late
binding, so it has the output item, but it cannot be resolved to a
+ // concrete file path at this time. Let's
make an approximation from
+ Path candidate = null;
+ if (base != null) {
+ Path prefix = base.resolve(langId);
+ // assume the language has just one
output dir in the source set:
+ for (int i = 0; i < outPaths.size();
i++) {
+ Path p = outPaths.get(i);
+ if (p.startsWith(prefix)) {
+ if (candidate != null) {
+ candidate = null;
+ break;
+ } else {
+ candidate = p;
+ }
+ }
+ }
+ }
+ outDir = candidate != null ?
candidate.toFile() : new File("");
+ }
+
+ model.getInfo().put(propBase + lang +
"_output_classes", outDir);
+ }
+ }
}
model.getInfo().put(propBase + "JAVA",
storeSet(getProperty(sourceSet, "java", "srcDirs")));
@@ -320,17 +400,7 @@ class NbProjectInfoBuilder {
if (hasKotlin) {
model.getInfo().put(propBase + "KOTLIN",
storeSet(getProperty(getProperty(sourceSet, "kotlin"), "srcDirs")));
}
- sinceGradle("4.0", () -> {
- Set<File> dirs = new LinkedHashSet<>();
- // classesDirs is just an iterable
- for (File dir: (ConfigurableFileCollection)
getProperty(sourceSet, "output", "classesDirs")) {
- dirs.add(dir);
- }
- model.getInfo().put(propBase + "output_classes", dirs);
- });
- beforeGradle("4.0", () -> {
- model.getInfo().put(propBase + "output_classes",
Collections.singleton(getProperty(sourceSet, "output", "classesDir")));
- });
+ model.getInfo().put(propBase + "output_classes", outDirs);
model.getInfo().put(propBase + "output_resources",
sourceSet.getOutput().getResourcesDir());
sinceGradle("5.2", () -> {
model.getInfo().put(propBase + "GENERATED",
storeSet(getProperty(sourceSet, "output", "generatedSourcesDirs", "files")));
diff --git
a/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
index 127130c78d..b28c2902dc 100644
---
a/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
+++
b/extide/gradle/src/org/netbeans/modules/gradle/cache/ProjectInfoDiskCache.java
@@ -45,7 +45,7 @@ import org.netbeans.modules.gradle.spi.GradleFiles;
public final class ProjectInfoDiskCache extends AbstractDiskCache<GradleFiles,
QualifiedProjectInfo> {
// Increase this number if new info is gathered from the projects.
- private static final int COMPATIBLE_CACHE_VERSION = 22;
+ private static final int COMPATIBLE_CACHE_VERSION = 23;
private static final String INFO_CACHE_FILE_NAME = "project-info.ser";
//NOI18N
private static final Map<GradleFiles, ProjectInfoDiskCache> DISK_CACHES =
Collections.synchronizedMap(new WeakHashMap<>());
diff --git a/java/gradle.java/apichanges.xml b/java/gradle.java/apichanges.xml
index f77b1ba1bd..dfd5b57876 100644
--- a/java/gradle.java/apichanges.xml
+++ b/java/gradle.java/apichanges.xml
@@ -83,6 +83,19 @@ is the proper place.
<!-- ACTUAL CHANGES BEGIN HERE: -->
<changes>
+ <change id="sourceset-lang-output">
+ <api name="gradle.java.api"/>
+ <summary>Support for per-language output directories</summary>
+ <version major="1" minor="19"/>
+ <date day="28" month="6" year="2022"/>
+ <author login="sdedic"/>
+ <compatibility semantic="compatible" addition="yes"
deprecation="no"/>
+ <description>
+ Each language plugin typically generates output to a specific
directory. The mapping
+ allows more precise output-to-source mapping.
+ </description>
+ <class package="org.netbeans.modules.gradle.java.api"
name="GradleJavaSourceSet"/>
+ </change>
<change id="nested-class-locations">
<api name="gradle.java.api"/>
<summary>Location can represent nested classes</summary>
diff --git a/java/gradle.java/manifest.mf b/java/gradle.java/manifest.mf
index 6a3ea04484..e378d4e486 100644
--- a/java/gradle.java/manifest.mf
+++ b/java/gradle.java/manifest.mf
@@ -3,4 +3,4 @@ AutoUpdate-Show-In-Client: false
OpenIDE-Module: org.netbeans.modules.gradle.java
OpenIDE-Module-Layer: org/netbeans/modules/gradle/java/layer.xml
OpenIDE-Module-Localizing-Bundle:
org/netbeans/modules/gradle/java/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.18
+OpenIDE-Module-Specification-Version: 1.19
diff --git
a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java
b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java
index cc0136ac25..652b2eca17 100644
---
a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java
+++
b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaProjectBuilder.java
@@ -99,6 +99,11 @@ final class GradleJavaProjectBuilder implements
ProjectInfoExtractor.Result {
if (compArgs != null) {
compilerArgs.put(lang,
Collections.unmodifiableList(compArgs));
}
+ // if detected, note the output dirs for individual
language(s).
+ File f = (File)info.get("sourceset_" + name + "_" +
lang.name() + "_output_classes");
+ if (f != null) {
+ sourceSet.outputs.put(lang, f);
+ }
}
sourceSet.sourcesCompatibility =
Collections.unmodifiableMap(sourceComp);
sourceSet.targetCompatibility =
Collections.unmodifiableMap(targetComp);
diff --git
a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java
b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java
index 061348190d..fad03f4e87 100644
---
a/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java
+++
b/java/gradle.java/src/org/netbeans/modules/gradle/java/api/GradleJavaSourceSet.java
@@ -78,6 +78,7 @@ public final class GradleJavaSourceSet implements
Serializable {
private static final String DEFAULT_SOURCE_COMPATIBILITY = "1.5"; //NOI18N
Map<SourceType, Set<File>> sources = new EnumMap<>(SourceType.class);
+ Map<SourceType, File> outputs = new EnumMap<>(SourceType.class);
String name;
String runtimeConfigurationName;
String compileConfigurationName;
@@ -365,6 +366,31 @@ public final class GradleJavaSourceSet implements
Serializable {
public Set<File> getOutputClassDirs() {
return outputClassDirs != null ? outputClassDirs :
Collections.<File>emptySet();
}
+
+ /**
+ * Represents an unknown value. This is different from a value that is not
present,
+ * i.e. an output directory for a language that is not used in the project.
+ * @since 1.19
+ */
+ public static final File UNKNOWN = new File("");
+
+ /**
+ * Returns output directories for the given source type in the sourceset.
Returns
+ * null, if the source type has no output directories. Returns UNKNOWN, if
the
+ * output location is not known.
+ *
+ * @param srcType language type
+ * @return location or {@code null}.
+ * @since 1.19
+ */
+ public File getOutputClassDir(SourceType srcType) {
+ File f = outputs.get(srcType);
+ if (UNKNOWN.equals(f)) {
+ // make the value canonical, so == can be used.
+ return UNKNOWN;
+ }
+ return f;
+ }
/**
* Return the directory of resources output.
diff --git
a/java/gradle.java/src/org/netbeans/modules/gradle/java/queries/GradleSourceForBinary.java
b/java/gradle.java/src/org/netbeans/modules/gradle/java/queries/GradleSourceForBinary.java
index e27921c790..962f079351 100644
---
a/java/gradle.java/src/org/netbeans/modules/gradle/java/queries/GradleSourceForBinary.java
+++
b/java/gradle.java/src/org/netbeans/modules/gradle/java/queries/GradleSourceForBinary.java
@@ -32,6 +32,7 @@ import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
@@ -53,13 +54,49 @@ import org.openide.util.WeakListeners;
* @author Laszlo Kishalmi
*/
public class GradleSourceForBinary implements
SourceForBinaryQueryImplementation2 {
+
+ private static Map<SourceType, String> sourceMimeTypes = new
EnumMap<>(SourceType.class);
+
+ static {
+ sourceMimeTypes.put(JAVA, "text/x-java");
+ sourceMimeTypes.put(GROOVY, "text/x-groovy");
+ sourceMimeTypes.put(SCALA, "text/x-scala");
+ sourceMimeTypes.put(KOTLIN, "text/x-kotlin");
+ }
private final Project project;
private final Map<URL, Res> cache = new HashMap<>();
-
+
public GradleSourceForBinary(Project project) {
this.project = project;
}
+
+ private static final EnumSet<SourceType> ALL_LANGUAGES;
+
+ static {
+ EnumSet<SourceType> s = EnumSet.allOf(SourceType.class);
+ s.remove(SourceType.RESOURCES);
+ s.remove(SourceType.GENERATED);
+
+ ALL_LANGUAGES = s;
+ }
+
+ private Result languageSourceForOutput(GradleJavaSourceSet ss, File
outputDir) {
+
+ for (SourceType st : ALL_LANGUAGES) {
+ File f = ss.getOutputClassDir(st);
+ if (outputDir.equals(f)) {
+ // special case for java here; Java replaces its classpath
entries by corresponding cache entries with
+ // indexed sources (.sig files) so that it tracks not compiled
source changes. Other languages do not generate
+ // the expected files.
+ // The proper solution will be to change java implementation
to use output folder as a fallback if nothing
+ // is found in the cache; then this special case may be
removed.
+ boolean canPreferSource = st == SourceType.JAVA;
+ return new Res(project, ss.getName(), EnumSet.of(RESOURCES),
canPreferSource);
+ }
+ }
+ return new Res(project, ss.getName(), ALL_LANGUAGES, false);
+ }
@Override
public Result findSourceRoots2(URL binaryRoot) {
@@ -76,8 +113,7 @@ public class GradleSourceForBinary implements
SourceForBinaryQueryImplementation
File outputDir =
ss.getCompilerArgs(JAVA).contains("--module-source-path") ? //NOI18N
root.getParentFile() : root;
if
(ss.getOutputClassDirs().contains(outputDir)) {
- ret = new Res(project, ss.getName(),
EnumSet.of(JAVA, GROOVY, SCALA, KOTLIN, GENERATED));
- break;
+ return languageSourceForOutput(ss,
outputDir);
}
if ((ret == null) &&
root.equals(ss.getOutputResources())) {
ret = new Res(project, ss.getName(),
EnumSet.of(RESOURCES));
@@ -122,11 +158,17 @@ public class GradleSourceForBinary implements
SourceForBinaryQueryImplementation
private final Set<SourceType> sourceTypes;
private final PropertyChangeListener listener;
private final ChangeSupport support = new ChangeSupport(this);
-
+ private final boolean preferSources;
+
public Res(Project project, String sourceSet, Set<SourceType>
sourceTypes) {
+ this(project, sourceSet, sourceTypes, true);
+ }
+
+ public Res(Project project, String sourceSet, Set<SourceType>
sourceTypes, boolean preferSources) {
this.project = project;
this.sourceSet = sourceSet;
this.sourceTypes = sourceTypes;
+ this.preferSources = preferSources;
listener = (PropertyChangeEvent evt) -> {
if
(NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) {
support.fireChange();
@@ -137,7 +179,7 @@ public class GradleSourceForBinary implements
SourceForBinaryQueryImplementation
@Override
public boolean preferSources() {
- return true;
+ return preferSources;
}
@Override
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists