8173596: JavaCompiler.CompilationTask should support addModules

Reviewed-by: ksrini, jlahoda
This commit is contained in:
Jonathan Gibbons 2017-02-15 14:12:29 -08:00
parent 8dfb222edf
commit 6873ceb82c
9 changed files with 280 additions and 20 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -121,7 +121,20 @@ public interface DocumentationTool extends Tool, OptionChecker {
*/
interface DocumentationTask extends Callable<Boolean> {
/**
* Set the locale to be applied when formatting diagnostics and
* Adds root modules to be taken into account during module
* resolution.
* Invalid module names may cause either
* {@code IllegalArgumentException} to be thrown,
* or diagnostics to be reported when the task is started.
* @param moduleNames the names of the root modules
* @throws IllegalArgumentException may be thrown for some
* invalid module names
* @throws IllegalStateException if the task has started
*/
void addModules(Iterable<String> moduleNames);
/**
* Sets the locale to be applied when formatting diagnostics and
* other localized data.
*
* @param locale the locale to apply; {@code null} means apply no

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,6 @@
package javax.tools;
import java.io.File;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Locale;
@ -296,6 +295,18 @@ public interface JavaCompiler extends Tool, OptionChecker {
* {@linkplain #setProcessors setProcessors} method.
*/
interface CompilationTask extends Callable<Boolean> {
/**
* Adds root modules to be taken into account during module
* resolution.
* Invalid module names may cause either
* {@code IllegalArgumentException} to be thrown,
* or diagnostics to be reported when the task is started.
* @param moduleNames the names of the root modules
* @throws IllegalArgumentException may be thrown for some
* invalid module names
* @throws IllegalStateException if the task has started
*/
void addModules(Iterable<String> moduleNames);
/**
* Sets processors (for annotation processing). This will
@ -307,7 +318,7 @@ public interface JavaCompiler extends Tool, OptionChecker {
void setProcessors(Iterable<? extends Processor> processors);
/**
* Set the locale to be applied when formatting diagnostics and
* Sets the locale to be applied when formatting diagnostics and
* other localized data.
*
* @param locale the locale to apply; {@code null} means apply no
@ -330,6 +341,7 @@ public interface JavaCompiler extends Tool, OptionChecker {
* in user code.
* @throws IllegalStateException if called more than once
*/
@Override
Boolean call();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -154,6 +154,11 @@ public class BasicJavacTask extends JavacTask {
return JavacTypes.instance(context);
}
@Override @DefinedBy(Api.COMPILER)
public void addModules(Iterable<String> moduleNames) {
throw new IllegalStateException();
}
@Override @DefinedBy(Api.COMPILER)
public void setProcessors(Iterable<? extends Processor> processors) {
throw new IllegalStateException();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,17 +33,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.processing.Processor;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.*;
import javax.tools.JavaFileObject.Kind;
import com.sun.source.tree.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.comp.*;
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.main.*;
@ -82,6 +77,7 @@ public class JavacTaskImpl extends BasicJavacTask {
private ListBuffer<Env<AttrContext>> genList;
private final AtomicBoolean used = new AtomicBoolean();
private Iterable<? extends Processor> processors;
private ListBuffer<String> addModules = new ListBuffer<>();
protected JavacTaskImpl(Context context) {
super(context, true);
@ -101,7 +97,7 @@ public class JavacTaskImpl extends BasicJavacTask {
prepareCompiler(false);
if (compiler.errorCount() > 0)
return Main.Result.ERROR;
compiler.compile(args.getFileObjects(), args.getClassNames(), processors);
compiler.compile(args.getFileObjects(), args.getClassNames(), processors, addModules);
return (compiler.errorCount() > 0) ? Main.Result.ERROR : Main.Result.OK; // FIXME?
}, Main.Result.SYSERR, Main.Result.ABNORMAL);
} finally {
@ -113,6 +109,18 @@ public class JavacTaskImpl extends BasicJavacTask {
}
}
@Override @DefinedBy(Api.COMPILER)
public void addModules(Iterable<String> moduleNames) {
Objects.requireNonNull(moduleNames);
// not mt-safe
if (used.get())
throw new IllegalStateException();
for (String m : moduleNames) {
Objects.requireNonNull(m);
addModules.add(m);
}
}
@Override @DefinedBy(Api.COMPILER)
public void setProcessors(Iterable<? extends Processor> processors) {
Objects.requireNonNull(processors);

View File

@ -888,7 +888,7 @@ public class JavaCompiler {
public void compile(List<JavaFileObject> sourceFileObject)
throws Throwable {
compile(sourceFileObject, List.nil(), null);
compile(sourceFileObject, List.nil(), null, List.nil());
}
/**
@ -898,10 +898,13 @@ public class JavaCompiler {
* @param classnames class names to process for annotations
* @param processors user provided annotation processors to bypass
* discovery, {@code null} means that no processors were provided
* @param addModules additional root modules to be used during
* module resolution.
*/
public void compile(Collection<JavaFileObject> sourceFileObjects,
Collection<String> classnames,
Iterable<? extends Processor> processors)
Iterable<? extends Processor> processors,
Collection<String> addModules)
{
if (!taskListener.isEmpty()) {
taskListener.started(new TaskEvent(TaskEvent.Kind.COMPILATION));
@ -932,6 +935,10 @@ public class JavaCompiler {
}
}
for (String moduleName : addModules) {
modules.addExtraAddModules(moduleName);
}
// These method calls must be chained to avoid memory leaks
processAnnotations(
enterTrees(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -304,7 +304,7 @@ public class Main {
}
try {
comp.compile(args.getFileObjects(), args.getClassNames(), null);
comp.compile(args.getFileObjects(), args.getClassNames(), null, List.nil());
if (log.expectDiagKeys != null) {
if (log.expectDiagKeys.isEmpty()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,15 +25,20 @@
package jdk.javadoc.internal.api;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.tools.DocumentationTool.DocumentationTask;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Options;
import jdk.javadoc.internal.tool.Start;
/**
@ -53,6 +58,7 @@ public class JavadocTaskImpl implements DocumentationTask {
private Iterable<String> options;
private Iterable<? extends JavaFileObject> fileObjects;
private Locale locale;
private List<String> addModules = new ArrayList<>();
public JavadocTaskImpl(Context context, Class<?> docletClass,
Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) {
@ -72,6 +78,16 @@ public class JavadocTaskImpl implements DocumentationTask {
this.locale = locale;
}
@Override
public void addModules(Iterable<String> moduleNames) {
nullCheck(moduleNames);
if (used.get())
throw new IllegalStateException();
for (String name : moduleNames) {
addModules.add(name);
}
}
public Boolean call() {
if (!used.getAndSet(true)) {
initContext();
@ -89,6 +105,12 @@ public class JavadocTaskImpl implements DocumentationTask {
private void initContext() {
//initialize compiler's default locale
context.put(Locale.class, locale);
if (!addModules.isEmpty()) {
String names = String.join(",", addModules);
Options opts = Options.instance(context);
String prev = opts.get(Option.ADD_MODULES);
opts.put(Option.ADD_MODULES, (prev == null) ? names : prev + "," + names);
}
}
private static <T> Iterable<T> nullCheck(Iterable<T> items) {

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8173596
* @summary DocumentationTool.DocumentationTask should support addModules
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* @library /tools/lib
* @build APITest toolbox.JavacTask toolbox.ToolBox
* @run main AddModulesTest
*/
import java.io.StringWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import javax.tools.DocumentationTool;
import javax.tools.DocumentationTool.DocumentationTask;
import javax.tools.DocumentationTool.Location;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import toolbox.Assert;
import toolbox.JavacTask;
import toolbox.ToolBox;
/**
* Tests for DocumentationTask.addModules method.
*/
public class AddModulesTest extends APITest {
public static void main(String... args) throws Exception {
new AddModulesTest().run();
}
private final ToolBox tb = new ToolBox();
/**
* Verify that addModules works as expected.
*/
@Test
public void testAddModules() throws Exception {
Path base = Paths.get("testAddModules");
Path src = base.resolve("src");
// setup some utility modules
Path src_m1 = src.resolve("m1x");
tb.writeJavaFiles(src_m1,
"module m1x { exports p1; }",
"package p1; public class C1 { }");
Path src_m2 = src.resolve("m2x");
tb.writeJavaFiles(src_m2,
"module m2x { exports p2; }",
"package p2; public class C2 { }");
Path modules = base.resolve("modules");
tb.createDirectories(modules);
new JavacTask(tb)
.options("--module-source-path", src.toString())
.outdir(modules)
.files(tb.findJavaFiles(src))
.run()
.writeAll();
// now test access to the modules
Path src2 = base.resolve("src2");
tb.writeJavaFiles(src2,
"public class Dummy { p1.C1 c1; p2.C2 c2; }");
Path api = base.resolve("api");
tb.createDirectories(api);
DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
fm.setLocationFromPaths(StandardLocation.MODULE_PATH, Arrays.asList(modules));
fm.setLocationFromPaths(Location.DOCUMENTATION_OUTPUT, Arrays.asList(api));
Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(tb.findJavaFiles(src2));
for (boolean useOption : new boolean[] { false, true }) {
System.err.println("Use --add-modules option: " + useOption);
StringWriter sw = new StringWriter();
DocumentationTask t = tool.getTask(sw, fm, null, null, null, files);
if (useOption) {
t.addModules(Arrays.asList("m1x", "m2x"));
}
String out;
boolean ok;
try {
ok = t.call();
} finally {
out = sw.toString();
System.err.println(out);
}
System.err.println("ok: " + ok);
boolean expectErrors = !useOption;
check(out, "package p1 is not visible", expectErrors);
check(out, "package p2 is not visible", expectErrors);
System.err.println();
}
}
}
void check(String out, String text, boolean expected) {
System.err.println("Checking for "
+ (expected ? "expected" : "unexpected")
+ " text: " + text);
if (expected) {
if (!out.contains(text)) {
error("expected text not found: " + text);
}
} else {
if (out.contains(text)) {
error("unexpected text found: " + text);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,17 +23,27 @@
/*
* @test
* @bug 8167975 8173596
* @summary Test the --add-modules option
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
* @build toolbox.Assert toolbox.ToolBox toolbox.JavacTask ModuleTestBase
* @run main AddModulesTest
*/
import java.nio.file.Path;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import toolbox.Assert;
import toolbox.JavacTask;
import toolbox.Task;
@ -227,5 +237,46 @@ public class AddModulesTest extends ModuleTestBase {
.run()
.writeAll();
}
@Test
public void testAddModulesAPI(Path base) throws Exception {
Path src = base.resolve("src");
// setup some utility modules
Path src_m1 = src.resolve("m1x");
tb.writeJavaFiles(src_m1,
"module m1x { exports p1; }",
"package p1; public class C1 { }");
Path src_m2 = src.resolve("m2x");
tb.writeJavaFiles(src_m2,
"module m2x { exports p2; }",
"package p2; public class C2 { }");
Path modules = base.resolve("modules");
tb.createDirectories(modules);
new JavacTask(tb)
.options("--module-source-path", src.toString())
.outdir(modules)
.files(findJavaFiles(src))
.run()
.writeAll();
// now test access to the modules
Path src2 = base.resolve("src2");
tb.writeJavaFiles(src2,
"class Dummy { p1.C1 c1; p2.C2 c2; }");
Path classes = base.resolve("classes");
tb.createDirectories(classes);
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
fm.setLocationFromPaths(StandardLocation.MODULE_PATH, Arrays.asList(modules));
fm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Arrays.asList(classes));
Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(src2));
CompilationTask t = c.getTask(null, fm, null, null, null, files);
t.addModules(Arrays.asList("m1x", "m2x"));
Assert.check(t.call());
}
}
}