Skip to content

Commit

Permalink
Including the support for requires.nb.javac for source > 8 in apisupp…
Browse files Browse the repository at this point in the history
…ort.ant.
  • Loading branch information
lahodaj committed Apr 9, 2024
1 parent a7e81d3 commit 3e88fb0
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 26 deletions.
1 change: 1 addition & 0 deletions apisupport/apisupport.ant/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ antsrc.cp=\
requires.nb.javac=true
javac.compilerargs=-Xlint -Xlint:-serial
javac.source=1.8
javac.release=17
javadoc.arch=${basedir}/arch.xml

test-unit-sys-prop.test.nbroot=${nb_all}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.SourceVersion;
import javax.swing.event.ChangeListener;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.platform.JavaPlatform;
Expand All @@ -70,6 +71,7 @@
import org.openide.filesystems.FileUtil;
import org.openide.modules.SpecificationVersion;
import org.openide.util.ChangeSupport;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
Expand Down Expand Up @@ -421,32 +423,43 @@ private PropertyEvaluator createEvaluator(ModuleList ml) {
if (ml != null) {
providers.add(PropertyUtils.fixedPropertyProvider(Collections.singletonMap("module.classpath", computeModuleClasspath(ml)))); // NOI18N
providers.add(PropertyUtils.fixedPropertyProvider(Collections.singletonMap("module.run.classpath", computeRuntimeModuleClasspath(ml)))); // NOI18N

baseEval = PropertyUtils.sequentialPropertyEvaluator(predefs, providers.toArray(new PropertyProvider[0]));

Map<String,String> buildDefaults = new HashMap<String,String>();
buildDefaults.put("cp.extra", ""); // NOI18N
buildDefaults.put(CP, "${module.classpath}:${cp.extra}"); // NOI18N
buildDefaults.put(RUN_CP, "${module.run.classpath}:${cp.extra}:${build.classes.dir}"); // NOI18N
if (type == NbModuleType.NETBEANS_ORG && "true".equals(projectProperties.getProperties().get("requires.nb.javac"))) {
ModuleEntry javacLibrary = ml.getEntry(JAVACAPI_CNB);
if (javacLibrary != null) {
boolean implDependencyOnJavac =
projectDependencies().filter(dep -> JAVACAPI_CNB.equals(dependencyCNB(dep)))
.map(dep -> XMLUtil.findElement(dep, "run-dependency", NbModuleProject.NAMESPACE_SHARED)) // NOI18N
.filter(runDep -> runDep != null)
.anyMatch(runDep -> XMLUtil.findElement(runDep, "implementation-version", NbModuleProject.NAMESPACE_SHARED) != null); // NOI18N
String bootcpPrepend;
if (implDependencyOnJavac) {
bootcpPrepend = javacLibrary.getClassPathExtensions();
} else {
bootcpPrepend = Stream.of(javacLibrary.getClassPathExtensions().split(Pattern.quote(File.pathSeparator)))
.filter(ext -> ext.endsWith("-api.jar"))
.collect(Collectors.joining(File.pathSeparator));
String javacRelease = baseEval.getProperty(SingleModuleProperties.JAVAC_RELEASE);
if (javacRelease == null || javacRelease.isEmpty()) {
javacRelease = baseEval.getProperty(SingleModuleProperties.JAVAC_SOURCE);
}
if (javacRelease.equals("1.6") ||
javacRelease.equals("1.7") ||
javacRelease.equals("1.8")) {
ModuleEntry javacLibrary = ml.getEntry(JAVACAPI_CNB);
if (javacLibrary != null) {
boolean implDependencyOnJavac =
projectDependencies().filter(dep -> JAVACAPI_CNB.equals(dependencyCNB(dep)))
.map(dep -> XMLUtil.findElement(dep, "run-dependency", NbModuleProject.NAMESPACE_SHARED)) // NOI18N
.filter(runDep -> runDep != null)
.anyMatch(runDep -> XMLUtil.findElement(runDep, "implementation-version", NbModuleProject.NAMESPACE_SHARED) != null); // NOI18N
String bootcpPrepend;
if (implDependencyOnJavac) {
bootcpPrepend = javacLibrary.getClassPathExtensions();
} else {
bootcpPrepend = Stream.of(javacLibrary.getClassPathExtensions().split(Pattern.quote(File.pathSeparator)))
.filter(ext -> ext.endsWith("-api.jar"))
.collect(Collectors.joining(File.pathSeparator));
}
buildDefaults.put(ClassPathProviderImpl.BOOTCLASSPATH_PREPEND, bootcpPrepend);
}
buildDefaults.put(ClassPathProviderImpl.BOOTCLASSPATH_PREPEND, bootcpPrepend);
} else {
buildDefaults.put(SingleModuleProperties.JAVAC_COMPILERARGS_INTERNAL_EXTRA, getLimitModules(javacRelease));
}
}

baseEval = PropertyUtils.sequentialPropertyEvaluator(predefs, providers.toArray(new PropertyProvider[0]));

Map<String,TestClasspath> testsCPs = computeTestingClassPaths(ml, baseEval, testTypes);
testTypes.addAll(testsCPs.keySet());
for (String testType : testTypes) {
Expand Down Expand Up @@ -874,5 +887,31 @@ private String mergePaths(Set<String> cnbs, boolean test,String testtype,File te
}
return cps.toString();
}


private static final Map<String, String> limitModulesCache = new HashMap<>();
private static String getLimitModules(String javacRelease) {
return limitModulesCache.computeIfAbsent(javacRelease, release -> {
int maxSupportedSourceVersion = SourceVersion.latest().ordinal();
try {
int javacReleaseValue = Integer.parseInt(release);
if (javacReleaseValue > maxSupportedSourceVersion) {
release = String.valueOf(maxSupportedSourceVersion);
}
} catch (NumberFormatException ex) {
//ignore
release = String.valueOf(maxSupportedSourceVersion);
}

try {
String limitModules =
SetupLimitModulesProbe.computeLimitModules(release,
"java.compiler",
"jdk.compiler");
return "--limit-modules=" + limitModules;
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
return null;
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.netbeans.modules.apisupport.project.queries.AntArtifactProviderImpl;
import org.netbeans.modules.apisupport.project.queries.BinaryForSourceImpl;
import org.netbeans.modules.apisupport.project.queries.ClassPathProviderImpl;
import org.netbeans.modules.apisupport.project.queries.CompilerOptionsQueryImpl;
import org.netbeans.modules.apisupport.project.queries.FileEncodingQueryImpl;
import org.netbeans.modules.apisupport.project.queries.JavadocForBinaryImpl;
import org.netbeans.modules.apisupport.project.queries.ModuleProjectClassPathExtender;
Expand Down Expand Up @@ -309,6 +310,7 @@ private Lookup createLookup(ProjectInformation info, AuxiliaryConfiguration aux,
ic.add(new FileEncodingQueryImpl());
ic.add(new AnnotationProcessingQueryImpl(this));
ic.add(new PlatformJarProviderImpl());
ic.add(new CompilerOptionsQueryImpl(this));

if (getModuleType() == NbModuleType.SUITE_COMPONENT) {
ic.add(new SuiteProviderImpl());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.apisupport.project;

import com.sun.source.util.JavacTask;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.ModuleElement.RequiresDirective;
import javax.lang.model.util.ElementFilter;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;

/**
* There's a copy of this class in nbbuild/antsrc/org/netbeans/nbbuild/extlibs/SetupLimitModulesProbe.java.
* Please make sure this are kept in sync.
*/
public class SetupLimitModulesProbe {

public static void main(String[] args) throws IOException {
String release = args[0];

String[] excludedModules =
Arrays.stream(args)
.skip(1)
.toArray(s -> new String[s]);

String limitModules = computeLimitModules(release, excludedModules);

System.out.println(limitModules);
}

public static String computeLimitModules(String release, String... excludedModulesIn) throws IOException {
Set<String> excludedModules = new HashSet<>(List.of(excludedModulesIn));
List<String> options;

if ("last".equals(release)) {
options = List.of("--add-modules", "ALL-SYSTEM", "-classpath", "");
} else {
options = List.of("--release", release, "-classpath", "");
}

JavacTask task = (JavacTask)
ToolProvider.getSystemJavaCompiler()
.getTask(null, null, null, options, null,
List.of(new JFOImpl(URI.create("mem://Test.java"), "")));

task.analyze();

String limitModules =
task.getElements()
.getAllModuleElements()
.stream()
.filter(m -> !m.getQualifiedName().toString().startsWith("jdk.internal."))
.filter(m -> !m.isUnnamed())
.filter(m -> canInclude(m, excludedModules))
.map(m -> m.getQualifiedName())
.collect(Collectors.joining(","));

return limitModules;
}

private static boolean canInclude(ModuleElement m, Set<String> excludes) {
return Collections.disjoint(transitiveDependencies(m), excludes);
}

private static Set<String> transitiveDependencies(ModuleElement m) {
List<ModuleElement> todo = new LinkedList<>();
Set<ModuleElement> seenModules = new HashSet<>();

todo.add(m);

while (!todo.isEmpty()) {
ModuleElement current = todo.remove(0);

if (seenModules.add(current)) {
for (RequiresDirective rd : ElementFilter.requiresIn(current.getDirectives())) {
todo.add(rd.getDependency());
}
}
}

return seenModules.stream()
.map(c -> c.getQualifiedName().toString())
.collect(Collectors.toSet());
}

private static final class JFOImpl extends SimpleJavaFileObject {

private final String content;

public JFOImpl(URI uri, String content) {
super(uri, Kind.SOURCE);
this.content = content;
}

@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return content;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.apisupport.project.queries;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import javax.swing.event.ChangeListener;
import org.netbeans.modules.apisupport.project.NbModuleProject;
import org.netbeans.modules.apisupport.project.ui.customizer.SingleModuleProperties;
import org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
import org.openide.filesystems.FileObject;
import org.openide.util.ChangeSupport;
import org.openide.util.WeakListeners;

public class CompilerOptionsQueryImpl implements CompilerOptionsQueryImplementation {

private final NbModuleProject project;
private final AtomicReference<Result> cachedResult = new AtomicReference<>();

public CompilerOptionsQueryImpl(NbModuleProject project) {
this.project = project;
}

@Override
public Result getOptions(FileObject file) {
Result result = cachedResult.get();

if (result == null) {
result = cachedResult.updateAndGet(existing -> existing != null ? existing
: new ResultImpl(project));
}

return result;
}

private static class ResultImpl extends Result implements PropertyChangeListener {

private static final Pattern SPACE_SPLIT = Pattern.compile(" +");
private final PropertyEvaluator evaluator;
private final ChangeSupport cs = new ChangeSupport(this);
private List<? extends String> cachedArguments;

public ResultImpl(NbModuleProject project) {
this.evaluator = project.evaluator();
this.evaluator.addPropertyChangeListener(WeakListeners.propertyChange(this, this.evaluator));
}


@Override
public synchronized List<? extends String> getArguments() {
List<? extends String> result = cachedArguments;

if (result == null) {
Map<String, String> properties = evaluator.getProperties();
String compilerArgs = properties.getOrDefault(SingleModuleProperties.JAVAC_COMPILERARGS, "") +
" " +
properties.getOrDefault(SingleModuleProperties.JAVAC_COMPILERARGS_INTERNAL_EXTRA, "");

compilerArgs = compilerArgs.trim();

if (compilerArgs.isEmpty()) {
result = Collections.emptyList();
} else {
result = Collections.unmodifiableList(Arrays.asList(SPACE_SPLIT.split(compilerArgs)));
}

cachedArguments = result;
}

return result;
}

@Override
public void addChangeListener(ChangeListener listener) {
cs.addChangeListener(listener);
}

@Override
public void removeChangeListener(ChangeListener listener) {
cs.removeChangeListener(listener);
}

@Override
public void propertyChange(PropertyChangeEvent pce) {
synchronized (this) {
cachedArguments = null;
}
cs.fireChange();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public final class SingleModuleProperties extends ModuleProperties {
public static final String SPEC_VERSION_BASE = "spec.version.base"; // NOI18N
/** @see "#66278" */
public static final String JAVAC_COMPILERARGS = "javac.compilerargs"; // NOI18N
public static final String JAVAC_COMPILERARGS_INTERNAL_EXTRA = "javac.internal.extra.compilerargs"; // NOI18N
private static final Map<String, String> DEFAULTS;

private static final Logger LOG = Logger.getLogger(SingleModuleProperties.class.getName());
Expand Down

0 comments on commit 3e88fb0

Please sign in to comment.