com.sun.tools.sjavac.options.Options Maven / Gradle / Ivy
Show all versions of javac Show documentation
/*
* Copyright (c) 2014, 2016, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.sjavac.options;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.StringJoiner;
import com.sun.tools.sjavac.Transformer;
import com.sun.tools.sjavac.Util;
/**
* Instances of this class represent values for sjavac command line options.
*
* This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.
*/
public class Options {
// Output directories
private Path destDir, genSrcDir, headerDir, stateDir;
// Input directories
private List sources = new ArrayList<>();
private List sourceSearchPaths = new ArrayList<>();
private List classSearchPaths = new ArrayList<>();
private List moduleSearchPaths = new ArrayList<>();
private String logLevel = "info";
private Set permitted_artifacts = new HashSet<>();
private boolean permitUnidentifiedArtifacts = false;
private boolean permitSourcesInDefaultPackage = false;
private Path sourceReferenceList;
private int numCores = 4;
private String implicitPolicy = "none";
private List javacArgs = new ArrayList<>();
private Map trRules = new HashMap<>();
private boolean startServer = false;
// Server configuration string
private String serverConf;
/** Get the policy for implicit classes */
public String getImplicitPolicy() {
return implicitPolicy;
}
/** Get the path for generated sources (or null if no such path is set) */
public Path getGenSrcDir() {
return genSrcDir;
}
/** Get the path for the destination directory */
public Path getDestDir() {
return destDir;
}
/** Get the path for the header directory (or null if no such path is set) */
public Path getHeaderDir() {
return headerDir;
}
/** Get the path for the state directory, defaults to destDir. */
public Path getStateDir() {
return stateDir;
}
/** Get all source locations for files to be compiled */
public List getSources() {
return sources;
}
/**
* Get all paths to search for classes in .java format. (Java-files in
* found here should not be compiled.
*/
public List getSourceSearchPaths() {
return sourceSearchPaths;
}
/** Get all paths to search for classes in. */
public List getClassSearchPath() {
return classSearchPaths;
}
/** Get all paths to search for modules in. */
public List getModuleSearchPaths() {
return moduleSearchPaths;
}
/** Get the log level. */
public String getLogLevel() {
return logLevel;
}
/** Returns true iff the artifact is permitted in the output dir. */
public boolean isUnidentifiedArtifactPermitted(String f) {
return permitted_artifacts.contains(f);
}
/** Returns true iff artifacts in the output directories should be kept,
* even if they would not be generated in a clean build. */
public boolean areUnidentifiedArtifactsPermitted() {
return permitUnidentifiedArtifacts;
}
/** Returns true iff sources in the default package should be permitted. */
public boolean isDefaultPackagePermitted() {
return permitSourcesInDefaultPackage;
}
/** Get the path to the list of reference sources (or null if none is set) */
public Path getSourceReferenceList() {
return sourceReferenceList;
}
/** Get the number of cores to be used by sjavac */
public int getNumCores() {
return numCores;
}
/** Returns all arguments relevant to javac but irrelevant to sjavac. */
public List getJavacArgs() {
return javacArgs;
}
/**
* Get a map which maps suffixes to transformers (for example
* ".java" {@literal ->} CompileJavaPackages)
*/
public Map getTranslationRules() {
return trRules;
}
/** Return true iff a new server should be started */
public boolean startServerFlag() {
return startServer;
}
/** Return the server configuration string. */
public String getServerConf() {
return serverConf;
}
/**
* Parses the given argument array and returns a corresponding Options
* instance.
*/
public static Options parseArgs(String... args) {
Options options = new Options();
options.new ArgDecoderOptionHelper().traverse(args);
return options;
}
/** Returns true iff a .java file is among the javac arguments */
public boolean isJavaFilesAmongJavacArgs() {
for (String javacArg : javacArgs)
if (javacArg.endsWith(".java"))
return true;
return false;
}
/**
* Returns a string representation of the options that affect the result of
* the compilation. (Used for saving the state of the options used in a
* previous compile.)
*/
public String getStateArgsString() {
// Local utility class for collecting the arguments
class StateArgs {
private List args = new ArrayList<>();
void addArg(Option opt) {
args.add(opt.arg);
}
void addArg(Option opt, Object val) {
addArg(opt);
args.add(val.toString());
}
void addSourceLocations(Option opt, List locs) {
for (SourceLocation sl : locs) {
for (String pkg : sl.includes) addArg(Option.I, pkg);
for (String pkg : sl.excludes) addArg(Option.X, pkg);
addArg(opt, sl.getPath());
}
}
String getResult() {
return String.join(" ", args);
}
public void addAll(Collection toAdd) {
args.addAll(toAdd);
}
}
StateArgs args = new StateArgs();
// Directories
if (genSrcDir != null)
args.addArg(Option.S, genSrcDir.normalize());
if (headerDir != null)
args.addArg(Option.H, headerDir.normalize());
if (destDir != null)
args.addArg(Option.D, destDir.normalize());
if (stateDir != null)
args.addArg(Option.STATE_DIR, stateDir.normalize());
// Source roots
args.addSourceLocations(Option.SRC, sources);
args.addSourceLocations(Option.SOURCEPATH, sourceSearchPaths);
args.addSourceLocations(Option.CLASSPATH, classSearchPaths);
args.addSourceLocations(Option.MODULEPATH, moduleSearchPaths);
// Boolean options
if (permitSourcesInDefaultPackage)
args.addArg(Option.PERMIT_SOURCES_WITHOUT_PACKAGE);
for (String f : permitted_artifacts) {
args.addArg(Option.PERMIT_ARTIFACT, f);
}
if (permitUnidentifiedArtifacts)
args.addArg(Option.PERMIT_UNIDENTIFIED_ARTIFACTS);
// Translation rules
for (Map.Entry tr : trRules.entrySet()) {
String val = tr.getKey() + "=" + tr.getValue().getClass().getName();
args.addArg(Option.TR, val);
}
// Javac args
args.addAll(javacArgs);
return args.getResult();
}
/** Extract the arguments to be passed on to javac. */
public String[] prepJavacArgs() {
List args = new ArrayList<>();
// Output directories
args.add("-d");
args.add(destDir.toString());
if (getGenSrcDir() != null) {
args.add("-s");
args.add(genSrcDir.toString());
}
if (headerDir != null) {
args.add("-h");
args.add(headerDir.toString());
}
// Prep sourcepath
List sourcepath = new ArrayList<>();
sourcepath.addAll(sources);
sourcepath.addAll(sourceSearchPaths);
if (sourcepath.size() > 0) {
args.add("-sourcepath");
args.add(concatenateSourceLocations(sourcepath));
}
// Prep classpath
if (classSearchPaths.size() > 0) {
args.add("-classpath");
args.add(concatenateSourceLocations(classSearchPaths));
}
// Enable dependency generation
args.add("-XDcompletionDeps=source,class");
// This can't be anything but 'none'. Enforced by sjavac main method.
args.add("-implicit:" + implicitPolicy);
// If this option is not used, Object for instance is erroneously
// picked up from PLATFORM_CLASS_PATH instead of CLASS_PATH.
//
// Discussing this further led to the decision of letting bootclasspath
// be a dummy (empty) directory when building the JDK.
//args.add("-XXuserPathsFirst");
// Append javac-options (i.e. pass through options not recognized by
// sjavac to javac.)
args.addAll(javacArgs);
return args.toArray(new String[args.size()]);
}
// Helper method to join a list of source locations separated by
// File.pathSeparator
private static String concatenateSourceLocations(List locs) {
StringJoiner joiner = new StringJoiner(java.io.File.pathSeparator);
for (SourceLocation loc : locs) {
joiner.add(loc.getPath().toString());
}
return joiner.toString();
}
// OptionHelper that records the traversed options in this Options instance.
private class ArgDecoderOptionHelper extends OptionHelper {
List includes, excludes, includeFiles, excludeFiles;
{
resetFilters();
}
boolean headerProvided = false;
boolean genSrcProvided = false;
boolean stateProvided = false;
@Override
public void reportError(String msg) {
throw new IllegalArgumentException(msg);
}
@Override
public void sourceRoots(List paths) {
sources.addAll(createSourceLocations(paths));
}
@Override
public void exclude(String exclPattern) {
exclPattern = Util.normalizeDriveLetter(exclPattern);
excludes.add(exclPattern);
}
@Override
public void include(String inclPattern) {
inclPattern = Util.normalizeDriveLetter(inclPattern);
includes.add(inclPattern);
}
@Override
public void addTransformer(String suffix, Transformer tr) {
if (trRules.containsKey(suffix)) {
reportError("More than one transformer specified for " +
"suffix " + suffix + ".");
return;
}
trRules.put(suffix, tr);
}
@Override
public void sourcepath(List paths) {
sourceSearchPaths.addAll(createSourceLocations(paths));
}
@Override
public void modulepath(List paths) {
moduleSearchPaths.addAll(createSourceLocations(paths));
}
@Override
public void classpath(List paths) {
classSearchPaths.addAll(createSourceLocations(paths));
}
@Override
public void numCores(int n) {
numCores = n;
}
@Override
public void logLevel(String level) {
logLevel = level;
}
@Override
public void compareFoundSources(Path referenceList) {
sourceReferenceList = referenceList;
}
@Override
public void permitArtifact(String f) {
permitted_artifacts.add(f);
}
@Override
public void permitUnidentifiedArtifacts() {
permitUnidentifiedArtifacts = true;
}
@Override
public void permitDefaultPackage() {
permitSourcesInDefaultPackage = true;
}
@Override
public void serverConf(String conf) {
if (serverConf != null)
reportError("Can not specify more than one server configuration.");
else
serverConf = conf;
}
@Override
public void implicit(String policy) {
implicitPolicy = policy;
}
@Override
public void startServerConf(String conf) {
if (serverConf != null)
reportError("Can not specify more than one server configuration.");
else {
startServer = true;
serverConf = conf;
}
}
@Override
public void javacArg(String... arg) {
javacArgs.addAll(Arrays.asList(arg));
}
@Override
public void destDir(Path dir) {
if (destDir != null) {
reportError("Destination directory already specified.");
return;
}
destDir = dir.toAbsolutePath();
}
@Override
public void generatedSourcesDir(Path dir) {
if (genSrcProvided) {
reportError("Directory for generated sources already specified.");
return;
}
genSrcProvided = true;
genSrcDir = dir.toAbsolutePath();
}
@Override
public void headerDir(Path dir) {
if (headerProvided) {
reportError("Header directory already specified.");
return;
}
headerProvided = true;
headerDir = dir.toAbsolutePath();
}
@Override
public void stateDir(Path dir) {
if (stateProvided) {
reportError("State directory already specified.");
return;
}
stateProvided = true;
stateDir = dir.toAbsolutePath();
}
private List createSourceLocations(List paths) {
List result = new ArrayList<>();
for (Path path : paths) {
result.add(new SourceLocation(
path,
includes,
excludes));
}
resetFilters();
return result;
}
private void resetFilters() {
includes = new ArrayList<>();
excludes = new ArrayList<>();
includeFiles = new ArrayList<>();
excludeFiles = new ArrayList<>();
}
}
}