8151102: Cleanup javadoc exception handling

Reviewed-by: jjg
This commit is contained in:
Kumar Srinivasan 2016-10-10 06:47:47 -07:00
parent a53b8b8a5d
commit 6f16c4713d
39 changed files with 881 additions and 568 deletions

View file

@ -40,7 +40,6 @@ import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder;
import jdk.javadoc.internal.doclets.toolkit.builders.BuilderFactory;
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.InternalException;
import jdk.javadoc.internal.doclets.toolkit.util.PackageListWriter;
import jdk.javadoc.internal.doclets.toolkit.util.ResourceIOException;
@ -112,8 +111,6 @@ public abstract class AbstractDoclet implements Doclet {
return false;
}
boolean dumpOnError = false; // set true to always show stack traces
try {
startGeneration(docEnv);
return true;
@ -128,16 +125,16 @@ public abstract class AbstractDoclet implements Doclet {
messages.error("doclet.exception.write.file",
e.fileName.getPath(), e.getCause());
}
dumpStack(dumpOnError, e);
dumpStack(configuration.dumpOnError, e);
} catch (ResourceIOException e) {
messages.error("doclet.exception.read.resource",
e.resource.getPath(), e.getCause());
dumpStack(dumpOnError, e);
dumpStack(configuration.dumpOnError, e);
} catch (SimpleDocletException e) {
configuration.reporter.print(ERROR, e.getMessage());
dumpStack(dumpOnError, e);
dumpStack(configuration.dumpOnError, e);
} catch (InternalException e) {
configuration.reporter.print(ERROR, e.getMessage());

View file

@ -281,6 +281,8 @@ public abstract class Configuration {
private String pkglistUrlForLinkOffline;
public boolean dumpOnError = false;
private List<GroupContainer> groups;
public abstract Messages getMessages();
@ -616,6 +618,13 @@ public abstract class Configuration {
showversion = true;
return true;
}
},
new Hidden(resources, "--dump-on-error") {
@Override
public boolean process(String opt, ListIterator<String> args) {
dumpOnError = true;
return true;
}
}
};
Set<Doclet.Option> set = new TreeSet<>();

View file

@ -75,6 +75,7 @@ import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.DocletEnvironment.ModuleMode;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static jdk.javadoc.internal.tool.Main.Result.*;
import static jdk.javadoc.internal.tool.JavadocTool.isValidClassName;
/**
@ -158,6 +159,7 @@ public class ElementsTable {
private final Location location;
private final Modules modules;
private final Map<ToolOption, Object> opts;
private final Messager messager;
private final Map<String, Entry> entries = new LinkedHashMap<>();
@ -201,6 +203,8 @@ public class ElementsTable {
this.fm = toolEnv.fileManager;
this.modules = Modules.instance(context);
this.opts = opts;
this.messager = Messager.instance0(context);
this.location = modules.multiModuleMode
? StandardLocation.MODULE_SOURCE_PATH
: toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
@ -339,9 +343,9 @@ public class ElementsTable {
* This is a terminal operation, thus no further modifications
* are allowed to the specified data sets.
*
* @throws IOException if an error occurs
* @throws ToolException if an error occurs
*/
void analyze() throws IOException {
void analyze() throws ToolException {
// compute the specified element, by expanding module dependencies
computeSpecifiedModules();
@ -354,7 +358,6 @@ public class ElementsTable {
// compute the packages belonging to all the specified modules
Set<PackageElement> expandedModulePackages = computeModulePackages();
initializeIncludedSets(expandedModulePackages);
}
ElementsTable classTrees(com.sun.tools.javac.util.List<JCCompilationUnit> classTrees) {
@ -363,16 +366,17 @@ public class ElementsTable {
}
@SuppressWarnings("unchecked")
ElementsTable scanSpecifiedItems() throws IOException {
ElementsTable scanSpecifiedItems() throws ToolException {
// scan modules specified on the command line
List<String> moduleNames = (List<String>) opts.computeIfAbsent(ToolOption.MODULE,
s -> Collections.EMPTY_LIST);
List<String> mlist = new ArrayList<>();
for (String m : moduleNames) {
Location moduleLoc = fm.getModuleLocation(location, m);
Location moduleLoc = getModuleLocation(location, m);
if (moduleLoc == null) {
toolEnv.error("main.module_not_found", m);
String text = messager.getText("main.module_not_found", m);
throw new ToolException(CMDERR, text);
} else {
mlist.add(m);
ModuleSymbol msym = syms.enterModule(names.fromString(m));
@ -457,7 +461,7 @@ public class ElementsTable {
}
@SuppressWarnings("unchecked")
private void computeSubpackages() throws IOException {
private void computeSubpackages() throws ToolException {
((List<String>) opts.computeIfAbsent(ToolOption.EXCLUDE, v -> Collections.EMPTY_LIST))
.stream()
.map((packageName) -> new ModulePackage(packageName))
@ -469,7 +473,14 @@ public class ElementsTable {
for (ModulePackage modpkg : subPackages) {
Location packageLocn = getLocation(modpkg);
for (JavaFileObject fo : fm.list(packageLocn, modpkg.packageName, sourceKinds, true)) {
Iterable<JavaFileObject> list = null;
try {
list = fm.list(packageLocn, modpkg.packageName, sourceKinds, true);
} catch (IOException ioe) {
String text = messager.getText("main.file.manager.list", modpkg.packageName);
throw new ToolException(SYSERR, text, ioe);
}
for (JavaFileObject fo : list) {
String binaryName = fm.inferBinaryName(packageLocn, fo);
String pn = getPackageName(binaryName);
String simpleName = getSimpleName(binaryName);
@ -554,22 +565,28 @@ public class ElementsTable {
specifiedModuleElements = Collections.unmodifiableSet(result);
}
private Set<PackageElement> getAllModulePackages(ModuleElement mdle) throws IOException {
private Set<PackageElement> getAllModulePackages(ModuleElement mdle) throws ToolException {
Set<PackageElement> result = new HashSet<>();
ModuleSymbol msym = (ModuleSymbol)mdle;
Location msymloc = fm.getModuleLocation(location, msym.name.toString());
for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) {
if (fo.getName().endsWith("module-info.java"))
continue;
String binaryName = fm.inferBinaryName(msymloc, fo);
String pn = getPackageName(binaryName);
PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn));
result.add((PackageElement)psym);
ModuleSymbol msym = (ModuleSymbol) mdle;
Location msymloc = getModuleLocation(location, msym.name.toString());
try {
for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) {
if (fo.getName().endsWith("module-info.java"))
continue;
String binaryName = fm.inferBinaryName(msymloc, fo);
String pn = getPackageName(binaryName);
PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn));
result.add((PackageElement) psym);
}
} catch (IOException ioe) {
String text = messager.getText("main.file.manager.list", msymloc.getName());
throw new ToolException(SYSERR, text, ioe);
}
return result;
}
private Set<PackageElement> computeModulePackages() throws IOException {
private Set<PackageElement> computeModulePackages() throws ToolException {
final AccessKind accessValue = accessFilter.getAccessValue(ElementKind.PACKAGE);
final boolean documentAllModulePackages = (accessValue == AccessKind.PACKAGE ||
accessValue == AccessKind.PRIVATE);
@ -662,10 +679,10 @@ public class ElementsTable {
includedTypeElements = Collections.unmodifiableSet(iclasses);
}
/**
/*
* Computes the included packages and freezes the specified packages list.
*/
private void computeSpecifiedPackages() throws IOException {
private void computeSpecifiedPackages() throws ToolException {
computeSubpackages();
@ -683,7 +700,7 @@ public class ElementsTable {
if (pkg != null) {
packlist.add(pkg);
} else {
toolEnv.warning("main.package_not_found", modpkg.toString());
messager.printWarningUsingKey("main.package_not_found", modpkg.toString());
}
});
specifiedPackageElements = Collections.unmodifiableSet(packlist);
@ -693,7 +710,7 @@ public class ElementsTable {
* Adds all classes as well as inner classes, to the specified
* list.
*/
private void computeSpecifiedTypes() {
private void computeSpecifiedTypes() throws ToolException {
Set<TypeElement> classes = new LinkedHashSet<>();
classDecList.stream().filter((def) -> (shouldDocument(def.sym))).forEach((def) -> {
TypeElement te = (TypeElement) def.sym;
@ -701,24 +718,28 @@ public class ElementsTable {
addAllClasses(classes, te, true);
}
});
classArgList.forEach((className) -> {
for (String className : classArgList) {
TypeElement te = toolEnv.loadClass(className);
if (te == null) {
toolEnv.error("javadoc.class_not_found", className);
String text = messager.getText("javadoc.class_not_found", className);
throw new ToolException(CMDERR, text);
} else {
addAllClasses(classes, te, true);
}
});
}
specifiedTypeElements = Collections.unmodifiableSet(classes);
}
private void addFilesForParser(Collection<JavaFileObject> result,
Collection<ModulePackage> collection, boolean recurse) throws IOException {
Collection<ModulePackage> collection,
boolean recurse) throws ToolException {
for (ModulePackage modpkg : collection) {
toolEnv.notice("main.Loading_source_files_for_package", modpkg.toString());
List<JavaFileObject> files = getFiles(modpkg, recurse);
if (files.isEmpty()) {
toolEnv.error("main.no_source_files_for_package", modpkg.toString());
String text = messager.getText("main.no_source_files_for_package",
modpkg.toString());
throw new ToolException(CMDERR, text);
} else {
result.addAll(files);
}
@ -732,7 +753,7 @@ public class ElementsTable {
* @return a list of java file objects
* @throws IOException if an error occurs
*/
List<JavaFileObject> getFilesToParse() throws IOException {
List<JavaFileObject> getFilesToParse() throws ToolException {
List<JavaFileObject> result = new ArrayList<>();
addFilesForParser(result, cmdLinePackages, false);
addFilesForParser(result, subPackages, true);
@ -744,9 +765,10 @@ public class ElementsTable {
*
* @param packageName the specified package
* @return the set of file objects for the specified package
* @throws IOException if an error occurs while accessing the files
* @throws ToolException if an error occurs while accessing the files
*/
private List<JavaFileObject> getFiles(ModulePackage modpkg, boolean recurse) throws IOException {
private List<JavaFileObject> getFiles(ModulePackage modpkg,
boolean recurse) throws ToolException {
Entry e = getEntry(modpkg);
// The files may have been found as a side effect of searching for subpackages
if (e.files != null) {
@ -759,12 +781,18 @@ public class ElementsTable {
return Collections.emptyList();
}
String pname = modpkg.packageName;
for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) {
String binaryName = fm.inferBinaryName(packageLocn, fo);
String simpleName = getSimpleName(binaryName);
if (isValidClassName(simpleName)) {
lb.append(fo);
try {
for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) {
String binaryName = fm.inferBinaryName(packageLocn, fo);
String simpleName = getSimpleName(binaryName);
if (isValidClassName(simpleName)) {
lb.append(fo);
}
}
} catch (IOException ioe) {
String text = messager.getText("main.file.manager.list", pname);
throw new ToolException(SYSERR, text, ioe);
}
return lb.toList();
@ -781,20 +809,30 @@ public class ElementsTable {
return null;
}
private Location getLocation(ModulePackage modpkg) throws IOException {
private Location getLocation(ModulePackage modpkg) throws ToolException {
if (location != StandardLocation.MODULE_SOURCE_PATH) {
return location;
}
if (modpkg.hasModule()) {
return fm.getModuleLocation(location, modpkg.moduleName);
return getModuleLocation(location, modpkg.moduleName);
}
// TODO: handle invalid results better.
ModuleSymbol msym = findModuleOfPackageName(modpkg.packageName);
if (msym == null) {
return null;
}
return fm.getModuleLocation(location, msym.name.toString());
return getModuleLocation(location, msym.name.toString());
}
private Location getModuleLocation(Location location, String msymName)
throws ToolException {
try {
return fm.getModuleLocation(location, msymName);
} catch (IOException ioe) {
String text = messager.getText("main.doclet_could_not_get_location", msymName);
throw new ToolException(ERROR, text, ioe);
}
}
private Entry getEntry(String name) {
@ -841,7 +879,10 @@ public class ElementsTable {
}
}
} catch (CompletionFailure e) {
// quietly ignore completion failures
if (e.getMessage() != null)
messager.printWarning(e.getMessage());
else
messager.printWarningUsingKey("main.unexpected.exception", e);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 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 jdk.javadoc.internal.tool;
import static jdk.javadoc.internal.tool.Main.Result.CMDERR;
/**
* Provides a mechanism for the javadoc tool to indicate an option
* decoding issue, arising from command line error.
*
* <p><b>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.</b>
*/
class IllegalOptionValue extends OptionException {
private static final long serialVersionUID = 0;
/**
* Constructs an object containing a runnable and a message.
* @param method a method to display suitable usage text
* @param message the detailed message
*/
IllegalOptionValue(Runnable method, String message) {
super(CMDERR, method, message);
}
}

View file

@ -27,7 +27,6 @@ package jdk.javadoc.internal.tool;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
@ -51,6 +50,8 @@ import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Position;
import jdk.javadoc.doclet.DocletEnvironment;
import static jdk.javadoc.internal.tool.Main.Result.*;
/**
* This class could be the main entry point for Javadoc when Javadoc is used as a
* component in a larger software system. It provides operations to
@ -120,9 +121,10 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
}
}
public DocletEnvironment getEnvironment(Map<ToolOption, Object> jdtoolOpts,
List<String> javaNames,
Iterable<? extends JavaFileObject> fileObjects) throws IOException {
public DocletEnvironment getEnvironment(Map<ToolOption,
Object> jdtoolOpts,
List<String> javaNames,
Iterable<? extends JavaFileObject> fileObjects) throws ToolException {
toolEnv = ToolEnvironment.instance(context);
toolEnv.initialize(jdtoolOpts);
ElementsTable etable = new ElementsTable(context, jdtoolOpts);
@ -133,10 +135,12 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
if (etable.xclasses) {
// If -Xclasses is set, the args should be a list of class names
for (String arg: javaNames) {
if (!isValidPackageName(arg)) // checks
toolEnv.error("main.illegal_class_name", arg);
if (!isValidPackageName(arg)) { // checks
String text = messager.getText("main.illegal_class_name", arg);
throw new ToolException(CMDERR, text);
}
}
if (messager.nerrors() != 0) {
if (messager.hasErrors()) {
return null;
}
etable.setClassArgList(javaNames);
@ -157,19 +161,23 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
for (String arg: javaNames) {
if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
if (new File(arg).getName().equals("module-info.java")) {
toolEnv.warning("main.file_ignored", arg);
messager.printWarningUsingKey("main.file_ignored", arg);
} else {
parse(fm.getJavaFileObjects(arg), classTrees, true);
}
} else if (isValidPackageName(arg)) {
packageNames.add(arg);
} else if (arg.endsWith(".java")) {
if (fm == null)
throw new IllegalArgumentException();
else
toolEnv.error("main.file_not_found", arg);
if (fm == null) {
String text = messager.getText("main.assertion.error", "fm == null");
throw new ToolException(ABNORMAL, text);
} else {
String text = messager.getText("main.file_not_found", arg);
throw new ToolException(ERROR, text);
}
} else {
toolEnv.error("main.illegal_package_name", arg);
String text = messager.getText("main.illegal_package_name", arg);
throw new ToolException(CMDERR, text);
}
}
@ -185,7 +193,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
parse(etable.getFilesToParse(), packageTrees, false);
modules.enter(packageTrees.toList(), null);
if (messager.nerrors() != 0) {
if (messager.hasErrors()) {
return null;
}
@ -197,10 +205,19 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
enterDone = true;
etable.analyze();
} catch (CompletionFailure cf) {
toolEnv.printError(cf.getMessage());
} catch (Abort ex) {}
throw new ToolException(ABNORMAL, cf.getMessage(), cf);
} catch (Abort abort) {
if (messager.hasErrors()) {
// presumably a message has been emitted, keep silent
throw new ToolException(ABNORMAL, "", abort);
} else {
String text = messager.getText("main.internal.error");
Throwable t = abort.getCause() == null ? abort : abort.getCause();
throw new ToolException(ABNORMAL, text, t);
}
}
if (messager.nerrors() != 0)
if (messager.hasErrors())
return null;
toolEnv.docEnv = new DocEnvImpl(toolEnv, etable);

View file

@ -60,7 +60,7 @@ public class Main {
*/
public static int execute(String... args) {
Start jdoc = new Start();
return jdoc.begin(args);
return jdoc.begin(args).exitCode;
}
/**
@ -72,7 +72,7 @@ public class Main {
*/
public static int execute(String[] args, PrintWriter writer) {
Start jdoc = new Start(writer, writer);
return jdoc.begin(args);
return jdoc.begin(args).exitCode;
}
/**
@ -85,6 +85,36 @@ public class Main {
*/
public static int execute(String[] args, PrintWriter outWriter, PrintWriter errWriter) {
Start jdoc = new Start(outWriter, errWriter);
return jdoc.begin(args);
return jdoc.begin(args).exitCode;
}
public static enum Result {
/** completed with no errors */
OK(0),
/** Completed with reported errors */
ERROR(1),
/** Bad command-line arguments */
CMDERR(2),
/** System error or resource exhaustion */
SYSERR(3),
/** Terminated abnormally */
ABNORMAL(4);
private static final long serialVersionUID = 1L;
Result(int exitCode) {
this.exitCode = exitCode;
}
public boolean isOK() {
return (exitCode == 0);
}
public final int exitCode;
@Override
public String toString() {
return name() + '(' + exitCode + ')';
}
}
}

View file

@ -48,10 +48,8 @@ import com.sun.tools.javac.util.Log;
/**
* Utility for integrating with javadoc tools and for localization.
* Handle Resources. Access to error and warning counts.
* Message formatting.
* <br>
* Also provides implementation for DocErrorReporter.
* Handle resources, access to error and warning counts and
* message formatting.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
@ -139,10 +137,6 @@ public class Messager extends Log implements Reporter {
}
}
public static class ExitJavadoc extends Error {
private static final long serialVersionUID = 0;
}
final String programName;
private Locale locale;
@ -240,7 +234,7 @@ public class Messager extends Log implements Reporter {
report(DiagnosticType.ERROR, prefix, msg);
return;
}
incrementErrorCount(prefix, msg);
printError(prefix, msg);
}
public void printError(Element e, String msg) {
@ -249,10 +243,15 @@ public class Messager extends Log implements Reporter {
report(DiagnosticType.ERROR, prefix, msg);
return;
}
incrementErrorCount(prefix, msg);
printError(prefix, msg);
}
private void incrementErrorCount(String prefix, String msg) {
public void printErrorUsingKey(String key, Object... args) {
printError((Element)null, getText(key, args));
}
// print the error and increment count
private void printError(String prefix, String msg) {
if (nerrors < MaxErrors) {
PrintWriter errWriter = getWriter(WriterKind.ERROR);
printRawLines(errWriter, prefix + ": " + getText("javadoc.error") + " - " + msg);
@ -272,13 +271,21 @@ public class Messager extends Log implements Reporter {
printWarning((DocTreePath)null, msg);
}
public void printWarningUsingKey(String key, Object... args) {
printWarning((Element)null, getText(key, args));
}
public void printWarning(Element e, String key, Object... args) {
printWarning(getText(key, args));
}
public void printWarning(DocTreePath path, String msg) {
String prefix = getDiagSource(path);
if (diagListener != null) {
report(DiagnosticType.WARNING, prefix, msg);
return;
}
incrementWarningCount(prefix, msg);
printWarning(prefix, msg);
}
public void printWarning(Element e, String msg) {
@ -287,10 +294,11 @@ public class Messager extends Log implements Reporter {
report(DiagnosticType.WARNING, prefix, msg);
return;
}
incrementWarningCount(prefix, msg);
printWarning(prefix, msg);
}
private void incrementWarningCount(String prefix, String msg) {
// print the warning and increment count
private void printWarning(String prefix, String msg) {
if (nwarnings < MaxWarnings) {
PrintWriter warnWriter = getWriter(WriterKind.WARNING);
printRawLines(warnWriter, prefix + ": " + getText("javadoc.warning") + " - " + msg);
@ -341,50 +349,6 @@ public class Messager extends Log implements Reporter {
noticeWriter.flush();
}
/**
* Print error message, increment error count.
*
* @param key selects message from resource
*/
public void error(Element e, String key, Object... args) {
printError(e, getText(key, args));
}
/**
* Print error message, increment error count.
*
* @param key selects message from resource
*/
public void error(DocTreePath path, String key, Object... args) {
printError(path, getText(key, args));
}
public void error(String key, Object... args) {
printError((Element)null, getText(key, args));
}
public void warning(String key, Object... args) {
printWarning((Element)null, getText(key, args));
}
/**
* Print warning message, increment warning count.
*
* @param key selects message from resource
*/
public void warning(Element e, String key, Object... args) {
printWarning(e, getText(key, args));
}
/**
* Print warning message, increment warning count.
*
* @param key selects message from resource
*/
public void warning(DocTreePath path, String key, Object... args) {
printWarning(path, getText(key, args));
}
/**
* Print a message.
*
@ -395,21 +359,23 @@ public class Messager extends Log implements Reporter {
}
/**
* Return total number of errors, including those recorded
* in the compilation log.
* Returns true if errors have been recorded.
*/
public int nerrors() { return nerrors; }
public boolean hasErrors() {
return nerrors != 0;
}
/**
* Return total number of warnings, including those recorded
* in the compilation log.
* Returns true if warnings have been recorded.
*/
public int nwarnings() { return nwarnings; }
public boolean hasWarnings() {
return nwarnings != 0;
}
/**
* Print exit message.
*/
public void exitNotice() {
public void printErrorWarningCounts() {
if (nerrors > 0) {
notice((nerrors > 1) ? "main.errors" : "main.error",
"" + nerrors);

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 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 jdk.javadoc.internal.tool;
import jdk.javadoc.internal.tool.Main.Result;
/**
* Provides a general mechanism for the javadoc tool to indicate an option
* decoding issue.
*
* <p><b>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.</b>
*/
class OptionException extends Exception {
private static final long serialVersionUID = 0;
public final Result result;
public final String message;
public final Runnable m;
/**
* Constructs an object with a result, runnable and a message
* to be printed out by the catcher. The runnable can be invoked
* by the catcher to display the usage text.
* @param result the exit code
* @param method the method to invoke
* @param message the detailed message
*/
public OptionException(Result result, Runnable method, String message) {
this.result = result;
this.m = method;
this.message = message;
if (result == null || result.isOK() || method == null || message == null) {
throw new AssertionError("result == null || result.isOK() || " +
"method == null || message == null");
}
}
/**
* Constructs an object with a result and a runnable.
* The runnable can be invoked by the catcher to display the usage text.
* @param result the exit code
* @param method the method to invoke
*/
public OptionException(Result result, Runnable method) {
this.result = result;
this.m = method;
this.message = null;
if (result == null || method == null) {
throw new AssertionError("result == null || method == null");
}
}
}

View file

@ -26,7 +26,6 @@
package jdk.javadoc.internal.tool;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
@ -65,11 +64,12 @@ import com.sun.tools.javac.util.Options;
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.Doclet.Option;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.tool.Main.Result;
import static javax.tools.DocumentationTool.Location.*;
import static com.sun.tools.javac.main.Option.*;
import static jdk.javadoc.internal.tool.Main.Result.*;
/**
* Main program of Javadoc.
@ -170,41 +170,28 @@ public class Start extends ToolOption.Helper {
*/
@Override
void usage() {
usage(true);
}
void usage(boolean exit) {
usage("main.usage", "-help", "main.usage.foot");
if (exit)
throw new Messager.ExitJavadoc();
usage("main.usage", OptionKind.STANDARD, "main.usage.foot");
}
@Override
void Xusage() {
Xusage(true);
usage("main.Xusage", OptionKind.EXTENDED, "main.Xusage.foot");
}
void Xusage(boolean exit) {
usage("main.Xusage", "-X", "main.Xusage.foot");
if (exit)
throw new Messager.ExitJavadoc();
}
private void usage(String header, String option, String footer) {
messager.notice(header);
showToolOptions(option.equals("-X") ? OptionKind.EXTENDED : OptionKind.STANDARD);
private void usage(String headerKey, OptionKind kind, String footerKey) {
messager.notice(headerKey);
showToolOptions(kind);
// let doclet print usage information
if (docletClass != null) {
String name = doclet.getName();
messager.notice("main.doclet.usage.header", name);
showDocletOptions(option.equals("-X") ? Option.Kind.EXTENDED : Option.Kind.STANDARD);
showDocletOptions(kind == OptionKind.EXTENDED
? Option.Kind.EXTENDED
: Option.Kind.STANDARD);
}
if (footer != null)
messager.notice(footer);
if (footerKey != null)
messager.notice(footerKey);
}
void showToolOptions(OptionKind kind) {
@ -326,25 +313,23 @@ public class Start extends ToolOption.Helper {
* of class loader creation, needed to detect the doclet/taglet class variants.
*/
@SuppressWarnings("deprecation")
int begin(String... argv) {
Result begin(String... argv) {
// Preprocess @file arguments
try {
argv = CommandLine.parse(argv);
} catch (FileNotFoundException e) {
messager.error("main.cant.read", e.getMessage());
throw new Messager.ExitJavadoc();
} catch (IOException e) {
e.printStackTrace(System.err);
throw new Messager.ExitJavadoc();
error("main.cant.read", e.getMessage());
return ERROR;
}
if (argv.length > 0 && "-Xold".equals(argv[0])) {
messager.warning("main.legacy_api");
warn("main.legacy_api");
String[] nargv = Arrays.copyOfRange(argv, 1, argv.length);
return com.sun.tools.javadoc.Main.execute(nargv);
return com.sun.tools.javadoc.Main.execute(nargv) == 0
? OK
: ERROR;
}
boolean ok = begin(Arrays.asList(argv), Collections.<JavaFileObject> emptySet());
return ok ? 0 : 1;
return begin(Arrays.asList(argv), Collections.<JavaFileObject> emptySet());
}
// Called by 199 API.
@ -356,11 +341,11 @@ public class Start extends ToolOption.Helper {
for (String opt: options)
opts.add(opt);
return begin(opts, fileObjects);
return begin(opts, fileObjects).isOK();
}
@SuppressWarnings("deprecation")
private boolean begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
private Result begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
fileManager = context.get(JavaFileManager.class);
if (fileManager == null) {
JavacFileManager.preRegister(context);
@ -369,8 +354,28 @@ public class Start extends ToolOption.Helper {
((BaseFileManager) fileManager).autoClose = true;
}
}
// locale, doclet and maybe taglet, needs to be determined first
docletClass = preProcess(fileManager, options);
try {
docletClass = preprocess(fileManager, options);
} catch (ToolException te) {
if (!te.result.isOK()) {
if (te.message != null) {
messager.printError(te.message);
}
Throwable t = te.getCause();
dumpStack(t == null ? te : t);
}
return te.result;
} catch (OptionException oe) {
if (oe.message != null) {
messager.printError(oe.message);
}
oe.m.run();
Throwable t = oe.getCause();
dumpStack(t == null ? oe : t);
return oe.result;
}
if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
// no need to dispatch to old, safe to init now
initMessager();
@ -379,43 +384,62 @@ public class Start extends ToolOption.Helper {
Object o = docletClass.getConstructor().newInstance();
doclet = (Doclet) o;
} catch (ReflectiveOperationException exc) {
exc.printStackTrace();
if (!apiMode) {
error("main.could_not_instantiate_class", docletClass);
throw new Messager.ExitJavadoc();
if (apiMode) {
throw new ClientCodeException(exc);
}
throw new ClientCodeException(exc);
error("main.could_not_instantiate_class", docletClass);
return ERROR;
}
} else {
if (this.apiMode) {
if (apiMode) {
com.sun.tools.javadoc.main.Start ostart
= new com.sun.tools.javadoc.main.Start(context);
return ostart.begin(docletClass, options, fileObjects);
return ostart.begin(docletClass, options, fileObjects)
? OK
: ERROR;
}
warn("main.legacy_api");
String[] array = options.toArray(new String[options.size()]);
return com.sun.tools.javadoc.Main.execute(array) == 0;
return com.sun.tools.javadoc.Main.execute(array) == 0
? OK
: ERROR;
}
boolean failed = false;
Result result = OK;
try {
failed = !parseAndExecute(options, fileObjects);
} catch (Messager.ExitJavadoc exc) {
// ignore, we just exit this way
result = parseAndExecute(options, fileObjects)
? OK
: ERROR;
} catch (OptionException toe) {
if (toe.message != null)
messager.printError(toe.message);
toe.m.run();
Throwable t = toe.getCause();
dumpStack(t == null ? toe : t);
return toe.result;
} catch (ToolException exc) {
if (exc.message != null) {
messager.printError(exc.message);
}
Throwable t = exc.getCause();
if (result == ABNORMAL) {
reportInternalError(t == null ? exc : t);
} else {
dumpStack(t == null ? exc : t);
}
return exc.result;
} catch (OutOfMemoryError ee) {
messager.error("main.out.of.memory");
failed = true;
error("main.out.of.memory");
result = SYSERR;
dumpStack(ee);
} catch (ClientCodeException e) {
// simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl
throw e;
} catch (Error ee) {
ee.printStackTrace(System.err);
messager.error("main.fatal.error");
failed = true;
} catch (Exception ee) {
ee.printStackTrace(System.err);
messager.error("main.fatal.exception");
failed = true;
} catch (Error | Exception ee) {
error("main.fatal.error", ee);
reportInternalError(ee);
result = ABNORMAL;
} finally {
if (fileManager != null
&& fileManager instanceof BaseFileManager
@ -424,17 +448,34 @@ public class Start extends ToolOption.Helper {
fileManager.close();
} catch (IOException ignore) {}
}
boolean haveErrorWarnings = messager.nerrors() > 0 ||
(rejectWarnings && messager.nwarnings() > 0);
if (failed && !haveErrorWarnings) {
boolean haveErrorWarnings = messager.hasErrors()
|| (rejectWarnings && messager.hasWarnings());
if (!result.isOK() && !haveErrorWarnings) {
// the doclet failed, but nothing reported, flag it!.
messager.error("main.unknown.error");
error("main.unknown.error");
}
failed |= haveErrorWarnings;
messager.exitNotice();
if (haveErrorWarnings && result.isOK()) {
result = ERROR;
}
messager.printErrorWarningCounts();
messager.flush();
}
return !failed;
return result;
}
private void reportInternalError(Throwable t) {
messager.printErrorUsingKey("doclet.internal.report.bug");
dumpStack(true, t);
}
private void dumpStack(Throwable t) {
dumpStack(false, t);
}
private void dumpStack(boolean enabled, Throwable t) {
if (t != null && (enabled || dumpOnError)) {
t.printStackTrace(System.err);
}
}
/**
@ -442,7 +483,7 @@ public class Start extends ToolOption.Helper {
*/
@SuppressWarnings("unchecked")
private boolean parseAndExecute(List<String> argList,
Iterable<? extends JavaFileObject> fileObjects) throws IOException {
Iterable<? extends JavaFileObject> fileObjects) throws ToolException, OptionException {
long tm = System.currentTimeMillis();
List<String> javaNames = new ArrayList<>();
@ -463,17 +504,21 @@ public class Start extends ToolOption.Helper {
if (platformString != null) {
if (compOpts.isSet("-source")) {
usageError("main.release.bootclasspath.conflict", "-source");
String text = messager.getText("main.release.bootclasspath.conflict", "-source");
throw new ToolException(CMDERR, text);
}
if (fileManagerOpts.containsKey(BOOT_CLASS_PATH)) {
usageError("main.release.bootclasspath.conflict", BOOT_CLASS_PATH.getPrimaryName());
String text = messager.getText("main.release.bootclasspath.conflict",
BOOT_CLASS_PATH.getPrimaryName());
throw new ToolException(CMDERR, text);
}
PlatformDescription platformDescription =
PlatformUtils.lookupPlatformDescription(platformString);
if (platformDescription == null) {
usageError("main.unsupported.release.version", platformString);
String text = messager.getText("main.unsupported.release.version", platformString);
throw new IllegalArgumentException(text);
}
compOpts.put(SOURCE, platformDescription.getSourceVersion());
@ -485,10 +530,15 @@ public class Start extends ToolOption.Helper {
if (platformCP != null) {
if (fileManager instanceof StandardJavaFileManager) {
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
try {
sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
} catch (IOException ioe) {
throw new ToolException(SYSERR, ioe.getMessage(), ioe);
}
} else {
usageError("main.release.not.standard.file.manager", platformString);
String text = messager.getText("main.release.not.standard.file.manager",
platformString);
throw new ToolException(ABNORMAL, text);
}
}
}
@ -502,7 +552,8 @@ public class Start extends ToolOption.Helper {
s -> Collections.EMPTY_LIST);
if (subpkgs.isEmpty()) {
if (javaNames.isEmpty() && isEmpty(fileObjects)) {
usageError("main.No_modules_packages_or_classes_specified");
String text = messager.getText("main.No_modules_packages_or_classes_specified");
throw new ToolException(CMDERR, text);
}
}
}
@ -535,7 +586,8 @@ public class Start extends ToolOption.Helper {
}
Set<Doclet.Option> docletOptions = null;
int handleDocletOptions(int idx, List<String> args, boolean isToolOption) {
int handleDocletOptions(int idx, List<String> args, boolean isToolOption)
throws OptionException {
if (docletOptions == null) {
docletOptions = doclet.getSupportedOptions();
}
@ -549,24 +601,25 @@ public class Start extends ToolOption.Helper {
argBase = arg;
argVal = null;
}
String text = null;
for (Doclet.Option opt : docletOptions) {
if (opt.matches(argBase)) {
if (argVal != null) {
switch (opt.getArgumentCount()) {
case 0:
usageError("main.unnecessary_arg_provided", argBase);
break;
text = messager.getText("main.unnecessary_arg_provided", argBase);
throw new OptionException(ERROR, this::usage, text);
case 1:
opt.process(arg, Arrays.asList(argVal).listIterator());
break;
default:
usageError("main.only_one_argument_with_equals", argBase);
break;
text = messager.getText("main.only_one_argument_with_equals", argBase);
throw new OptionException(ERROR, this::usage, text);
}
} else {
if (args.size() - idx -1 < opt.getArgumentCount()) {
usageError("main.requires_argument", arg);
text = messager.getText("main.requires_argument", arg);
throw new OptionException(ERROR, this::usage, text);
}
opt.process(arg, args.listIterator(idx + 1));
idx += opt.getArgumentCount();
@ -575,12 +628,15 @@ public class Start extends ToolOption.Helper {
}
}
// check if arg is accepted by the tool before emitting error
if (!isToolOption)
usageError("main.invalid_flag", arg);
if (!isToolOption) {
text = messager.getText("main.invalid_flag", arg);
throw new OptionException(ERROR, this::usage, text);
}
return idx;
}
private Class<?> preProcess(JavaFileManager jfm, List<String> argv) {
private Class<?> preprocess(JavaFileManager jfm,
List<String> argv) throws ToolException, OptionException {
// doclet specifying arguments
String userDocletPath = null;
String userDocletName = null;
@ -593,19 +649,31 @@ public class Start extends ToolOption.Helper {
// Step 1: loop through the args, set locale early on, if found.
for (int i = 0 ; i < argv.size() ; i++) {
String arg = argv.get(i);
if (arg.equals(ToolOption.LOCALE.primaryName)) {
if (arg.equals(ToolOption.DUMPONERROR.primaryName)) {
dumpOnError = true;
} else if (arg.equals(ToolOption.LOCALE.primaryName)) {
checkOneArg(argv, i++);
String lname = argv.get(i);
locale = getLocale(lname);
} else if (arg.equals(ToolOption.DOCLET.primaryName)) {
checkOneArg(argv, i++);
if (userDocletName != null) {
usageError("main.more_than_one_doclet_specified_0_and_1",
if (apiMode) {
throw new IllegalArgumentException("More than one doclet specified (" +
userDocletName + " and " + argv.get(i) + ").");
}
String text = messager.getText("main.more_than_one_doclet_specified_0_and_1",
userDocletName, argv.get(i));
throw new ToolException(CMDERR, text);
}
if (docletName != null) {
usageError("main.more_than_one_doclet_specified_0_and_1",
if (apiMode) {
throw new IllegalArgumentException("More than one doclet specified (" +
docletName + " and " + argv.get(i) + ").");
}
String text = messager.getText("main.more_than_one_doclet_specified_0_and_1",
docletName, argv.get(i));
throw new ToolException(CMDERR, text);
}
userDocletName = argv.get(i);
} else if (arg.equals(ToolOption.DOCLETPATH.primaryName)) {
@ -644,23 +712,37 @@ public class Start extends ToolOption.Helper {
try {
((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
} catch (IOException ioe) {
error("main.doclet_could_not_set_location", paths);
throw new Messager.ExitJavadoc();
if (apiMode) {
throw new IllegalArgumentException("Could not set location for " +
userDocletPath, ioe);
}
String text = messager.getText("main.doclet_could_not_set_location",
userDocletPath);
throw new ToolException(CMDERR, text, ioe);
}
}
cl = fileManager.getClassLoader(DOCLET_PATH);
if (cl == null) {
// despite doclet specified on cmdline no classloader found!
error("main.doclet_no_classloader_found", userDocletName);
throw new Messager.ExitJavadoc();
if (apiMode) {
throw new IllegalArgumentException("Could not obtain classloader to load "
+ userDocletPath);
}
String text = messager.getText("main.doclet_no_classloader_found",
userDocletName);
throw new ToolException(CMDERR, text);
}
}
try {
Class<?> klass = cl.loadClass(userDocletName);
return klass;
} catch (ClassNotFoundException cnfe) {
error("main.doclet_class_not_found", userDocletName);
throw new Messager.ExitJavadoc();
if (apiMode) {
throw new IllegalArgumentException("Cannot find doclet class " + userDocletName,
cnfe);
}
String text = messager.getText("main.doclet_class_not_found", userDocletName);
throw new ToolException(CMDERR, text, cnfe);
}
}
@ -669,8 +751,11 @@ public class Start extends ToolOption.Helper {
try {
return Class.forName(docletName, true, getClass().getClassLoader());
} catch (ClassNotFoundException cnfe) {
error("main.doclet_class_not_found", userDocletName);
throw new Messager.ExitJavadoc();
if (apiMode) {
throw new IllegalArgumentException("Cannot find doclet class " + userDocletName);
}
String text = messager.getText("main.doclet_class_not_found", userDocletName);
throw new ToolException(CMDERR, text, cnfe);
}
}
@ -690,20 +775,20 @@ public class Start extends ToolOption.Helper {
* nature to take its own course.
*/
@SuppressWarnings("deprecation")
private boolean hasOldTaglet(List<String> tagletNames, List<File> tagletPaths) {
private boolean hasOldTaglet(List<String> tagletNames, List<File> tagletPaths) throws ToolException {
if (!fileManager.hasLocation(TAGLET_PATH)) {
try {
((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, tagletPaths);
} catch (IOException ioe) {
error("main.doclet_could_not_set_location", tagletPaths);
throw new Messager.ExitJavadoc();
String text = messager.getText("main.doclet_could_not_set_location", tagletPaths);
throw new ToolException(CMDERR, text, ioe);
}
}
ClassLoader cl = fileManager.getClassLoader(TAGLET_PATH);
if (cl == null) {
// no classloader found!
error("main.doclet_no_classloader_found", tagletNames.get(0));
throw new Messager.ExitJavadoc();
String text = messager.getText("main.doclet_no_classloader_found", tagletNames.get(0));
throw new ToolException(CMDERR, text);
}
for (String tagletName : tagletNames) {
try {
@ -712,14 +797,15 @@ public class Start extends ToolOption.Helper {
return true;
}
} catch (ClassNotFoundException cnfe) {
error("main.doclet_class_not_found", tagletName);
throw new Messager.ExitJavadoc();
String text = messager.getText("main.doclet_class_not_found", tagletName);
throw new ToolException(CMDERR, text, cnfe);
}
}
return false;
}
private void parseArgs(List<String> args, List<String> javaNames) {
private void parseArgs(List<String> args, List<String> javaNames) throws ToolException,
OptionException {
for (int i = 0 ; i < args.size() ; i++) {
String arg = args.get(i);
ToolOption o = ToolOption.get(arg);
@ -727,7 +813,6 @@ public class Start extends ToolOption.Helper {
// handle a doclet argument that may be needed however
// don't increment the index, and allow the tool to consume args
handleDocletOptions(i, args, true);
if (o.hasArg) {
if (arg.startsWith("--") && arg.contains("=")) {
o.process(this, arg.substring(arg.indexOf('=') + 1));
@ -763,24 +848,19 @@ public class Start extends ToolOption.Helper {
* Check the one arg option.
* Error and exit if one argument is not provided.
*/
private void checkOneArg(List<String> args, int index) {
private void checkOneArg(List<String> args, int index) throws OptionException {
if ((index + 1) >= args.size() || args.get(index + 1).startsWith("-d")) {
usageError("main.requires_argument", args.get(index));
String text = messager.getText("main.requires_argument", args.get(index));
throw new OptionException(CMDERR, this::usage, text);
}
}
@Override
void usageError(String key, Object... args) {
error(key, args);
usage(true);
}
void error(String key, Object... args) {
messager.error(key, args);
messager.printErrorUsingKey(key, args);
}
void warn(String key, Object... args) {
messager.warning(key, args);
messager.printWarningUsingKey(key, args);
}
/**
@ -788,7 +868,7 @@ public class Start extends ToolOption.Helper {
* else return null and if locale option is not used
* then return default locale.
*/
private Locale getLocale(String localeName) {
private Locale getLocale(String localeName) throws ToolException {
Locale userlocale = null;
if (localeName == null || localeName.isEmpty()) {
return Locale.getDefault();
@ -804,8 +884,8 @@ public class Start extends ToolOption.Helper {
if (seconduscore > 0) {
if (seconduscore != firstuscore + 3
|| localeName.length() <= seconduscore + 1) {
usageError("main.malformed_locale_name", localeName);
return null;
String text = messager.getText("main.malformed_locale_name", localeName);
throw new ToolException(CMDERR, text);
}
country = localeName.substring(firstuscore + 1,
seconduscore);
@ -813,19 +893,19 @@ public class Start extends ToolOption.Helper {
} else if (localeName.length() == firstuscore + 3) {
country = localeName.substring(firstuscore + 1);
} else {
usageError("main.malformed_locale_name", localeName);
return null;
String text = messager.getText("main.malformed_locale_name", localeName);
throw new ToolException(CMDERR, text);
}
} else if (firstuscore == -1 && localeName.length() == 2) {
language = localeName;
} else {
usageError("main.malformed_locale_name", localeName);
return null;
String text = messager.getText("main.malformed_locale_name", localeName);
throw new ToolException(CMDERR, text);
}
userlocale = searchLocale(language, country, variant);
if (userlocale == null) {
usageError("main.illegal_locale_name", localeName);
return null;
String text = messager.getText("main.illegal_locale_name", localeName);
throw new ToolException(CMDERR, text);
} else {
return userlocale;
}
@ -861,4 +941,9 @@ public class Start extends ToolOption.Helper {
}
};
}
@Override
String getLocalizedMessage(String msg, Object... args) {
return messager.getText(msg, args);
}
}

View file

@ -87,7 +87,7 @@ public class ToolEnvironment {
return instance;
}
private final Messager messager;
final Messager messager;
/** Predefined symbols known to the compiler. */
public final Symtab syms;
@ -204,182 +204,8 @@ public class ToolEnvironment {
return path != null;
}
//---------------- print forwarders ----------------//
// ERRORS
/**
* Print error message, increment error count.
*
* @param msg message to print.
*/
public void printError(String msg) {
messager.printError(msg);
}
// /**
// * Print error message, increment error count.
// *
// * @param key selects message from resource
// */
// public void error(Element element, String key) {
// if (element == null)
// messager.error(key);
// else
// messager.error(element, key);
// }
//
// public void error(String prefix, String key) {
// printError(prefix + ":" + messager.getText(key));
// }
//
// /**
// * Print error message, increment error count.
// *
// * @param path the path to the source
// * @param key selects message from resource
// */
// public void error(DocTreePath path, String key) {
// messager.error(path, key);
// }
//
// /**
// * Print error message, increment error count.
// *
// * @param path the path to the source
// * @param msg message to print.
// */
// public void printError(DocTreePath path, String msg) {
// messager.printError(path, msg);
// }
//
// /**
// * Print error message, increment error count.
// * @param e the target element
// * @param msg message to print.
// */
// public void printError(Element e, String msg) {
// messager.printError(e, msg);
// }
/**
* Print error message, increment error count.
* @param key selects message from resource
* @param args replacement arguments
*/
public void error(String key, String... args) {
error(null, key, args);
}
/**
* Print error message, increment error count.
*
* @param element the source element
* @param key selects message from resource
* @param args replacement arguments
*/
public void error(Element element, String key, String... args) {
if (element == null)
messager.error(key, (Object[]) args);
else
messager.error(element, key, (Object[]) args);
}
// WARNINGS
// /**
// * Print warning message, increment warning count.
// *
// * @param msg message to print.
// */
// public void printWarning(String msg) {
// messager.printWarning(msg);
// }
//
// public void warning(String key) {
// warning((Element)null, key);
// }
public void warning(String key, String... args) {
warning((Element)null, key, args);
}
// /**
// * Print warning message, increment warning count.
// *
// * @param element the source element
// * @param key selects message from resource
// */
// public void warning(Element element, String key) {
// if (element == null)
// messager.warning(key);
// else
// messager.warning(element, key);
// }
//
// /**
// * Print warning message, increment warning count.
// *
// * @param path the path to the source
// * @param msg message to print.
// */
// public void printWarning(DocTreePath path, String msg) {
// messager.printWarning(path, msg);
// }
//
// /**
// * Print warning message, increment warning count.
// *
// * @param e the source element
// * @param msg message to print.
// */
// public void printWarning(Element e, String msg) {
// messager.printWarning(e, msg);
// }
/**
* Print warning message, increment warning count.
*
* @param e the source element
* @param key selects message from resource
* @param args the replace arguments
*/
public void warning(Element e, String key, String... args) {
if (e == null)
messager.warning(key, (Object[]) args);
else
messager.warning(e, key, (Object[]) args);
}
// Note: no longer required
// /**
// * Print a message.
// *
// * @param msg message to print.
// */
// public void printNotice(String msg) {
// if (quiet) {
// return;
// }
// messager.printNotice(msg);
// }
// Note: no longer required
// /**
// * Print a message.
// *
// * @param e the source element
// * @param msg message to print.
// */
// public void printNotice(Element e, String msg) {
// if (quiet) {
// return;
// }
// messager.printNotice(e, msg);
// }
// NOTICES
/**
* Print a message.
* Print a notice, iff <em>quiet</em> is not specified.
*
* @param key selects message from resource
*/
@ -390,22 +216,8 @@ public class ToolEnvironment {
messager.notice(key);
}
// Note: not used anymore
// /**
// * Print a message.
// *
// * @param path the path to the source
// * @param msg message to print.
// */
// public void printNotice(DocTreePath path, String msg) {
// if (quiet) {
// return;
// }
// messager.printNotice(path, msg);
// }
/**
* Print a message.
* Print a notice, iff <em>quiet</em> is not specified.
*
* @param key selects message from resource
* @param a1 first argument
@ -417,48 +229,6 @@ public class ToolEnvironment {
messager.notice(key, a1);
}
// Note: not used anymore
// /**
// * Print a message.
// *
// * @param key selects message from resource
// * @param a1 first argument
// * @param a2 second argument
// */
// public void notice(String key, String a1, String a2) {
// if (quiet) {
// return;
// }
// messager.notice(key, a1, a2);
// }
//
// Note: not used anymore
// /**
// * Print a message.
// *
// * @param key selects message from resource
// * @param a1 first argument
// * @param a2 second argument
// * @param a3 third argument
// */
// public void notice(String key, String a1, String a2, String a3) {
// if (quiet) {
// return;
// }
// messager.notice(key, a1, a2, a3);
// }
/**
* Exit, reporting errors and warnings.
*/
public void exit() {
// Messager should be replaced by a more general
// compilation environment. This can probably
// subsume DocEnv as well.
throw new Messager.ExitJavadoc();
}
TreePath getTreePath(JCCompilationUnit tree) {
TreePath p = treePaths.get(tree);
if (p == null)

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 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 jdk.javadoc.internal.tool;
import jdk.javadoc.internal.tool.Main.Result;
/**
* Provides a mechanism for the javadoc tool to terminate execution.
* This class is constructed with a result and an error message,
* that can be printed out before termination, a cause can also
* be wrapped to supply extended information about the exception.
*
* <p><b>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.</b>
*/
class ToolException extends Exception {
private static final long serialVersionUID = 0;
final String message;
final Result result;
/**
* Constructs an object containing a result and a message to be
* printed out by the catcher.
* @param result the exit code
* @param message the detailed message
*/
ToolException(Result result, String message) {
this.message = message;
this.result = result;
if (result == null || result.isOK() || message == null) {
throw new AssertionError("result == null || result.isOK() || message == null");
}
}
/**
* Constructs an object containing a result, a messages and an underlying cause.
* @param result the exit code
* @param message the detailed message
* @param cause the underlying cause
*/
ToolException(Result result, String message, Throwable cause) {
super(cause);
this.message = message;
this.result = result;
if (result == null || message == null || cause == null || result.isOK()) {
throw new AssertionError("result == null || message == null"
+ " || cause == null || result.isOK()");
}
}
}

View file

@ -40,6 +40,7 @@ import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.util.Options;
import static com.sun.tools.javac.main.Option.OptionKind.*;
import static jdk.javadoc.internal.tool.Main.Result.*;
/**
* javadoc tool options.
@ -226,63 +227,63 @@ public enum ToolOption {
PACKAGE("-package", STANDARD) {
@Override
public void process(Helper helper) {
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("package");
}
},
PRIVATE("-private", STANDARD) {
@Override
public void process(Helper helper) {
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("private");
}
},
PROTECTED("-protected", STANDARD) {
@Override
public void process(Helper helper) {
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("protected");
}
},
PUBLIC("-public", STANDARD) {
@Override
public void process(Helper helper) {
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("public");
}
},
SHOW_MEMBERS("--show-members", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
public void process(Helper helper, String arg) throws OptionException {
helper.setFilter(this, arg);
}
},
SHOW_TYPES("--show-types", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
public void process(Helper helper, String arg) throws OptionException {
helper.setFilter(this, arg);
}
},
SHOW_PACKAGES("--show-packages", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
public void process(Helper helper, String arg) throws OptionException {
helper.setShowPackageAccess(SHOW_PACKAGES, arg);
}
},
SHOW_MODULE_CONTENTS("--show-module-contents", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
public void process(Helper helper, String arg) throws OptionException {
helper.setShowModuleContents(SHOW_MODULE_CONTENTS, arg);
}
},
EXPAND_REQUIRES("--expand-requires", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
public void process(Helper helper, String arg) throws OptionException {
helper.setExpandRequires(EXPAND_REQUIRES, arg);
}
},
@ -342,19 +343,26 @@ public enum ToolOption {
}
},
DUMPONERROR("--dump-on-error", HIDDEN) {
@Override
public void process(Helper helper) {
helper.dumpOnError = true;
}
},
// ----- help options -----
HELP("--help -help", STANDARD) {
@Override
public void process(Helper helper) {
helper.usage();
public void process(Helper helper) throws OptionException {
throw new OptionException(OK, helper::usage);
}
},
X("-X", STANDARD) {
@Override
public void process(Helper helper) {
helper.Xusage();
public void process(Helper helper) throws OptionException {
throw new OptionException(OK, helper::Xusage);
}
},
@ -395,9 +403,9 @@ public enum ToolOption {
this.hasSuffix = lastChar == ':' || lastChar == '=';
}
void process(Helper helper, String arg) { }
void process(Helper helper, String arg) throws OptionException { }
void process(Helper helper) { }
void process(Helper helper) throws OptionException { }
List<String> getNames() {
return names;
@ -451,6 +459,9 @@ public enum ToolOption {
/** Javadoc tool options */
final Map<ToolOption, Object> jdtoolOpts = new EnumMap<>(ToolOption.class);
/** dump stack traces for debugging etc.*/
boolean dumpOnError = false;
/** Set by -breakiterator. */
boolean breakiterator = false;
@ -470,7 +481,8 @@ public enum ToolOption {
abstract void usage();
abstract void Xusage();
abstract void usageError(String msg, Object... args);
abstract String getLocalizedMessage(String msg, Object... args);
abstract OptionHelper getOptionHelper();
@SuppressWarnings("unchecked")
@ -480,7 +492,7 @@ public enum ToolOption {
jdtoolOpts.put(opt, list);
}
void setExpandRequires(ToolOption opt, String arg) {
void setExpandRequires(ToolOption opt, String arg) throws OptionException {
switch (arg) {
case "public":
jdtoolOpts.put(opt, AccessKind.PUBLIC);
@ -489,11 +501,12 @@ public enum ToolOption {
jdtoolOpts.put(opt, AccessKind.PRIVATE);
break;
default:
usageError("main.illegal_option_value", arg);
String text = getLocalizedMessage("main.illegal_option_value", arg);
throw new IllegalOptionValue(this::usage, text);
}
}
void setShowModuleContents(ToolOption opt, String arg) {
void setShowModuleContents(ToolOption opt, String arg) throws OptionException {
switch (arg) {
case "api":
jdtoolOpts.put(opt, AccessKind.PUBLIC);
@ -502,11 +515,12 @@ public enum ToolOption {
jdtoolOpts.put(opt, AccessKind.PRIVATE);
break;
default:
usageError("main.illegal_option_value", arg);
String text = getLocalizedMessage("main.illegal_option_value", arg);
throw new IllegalOptionValue(this::usage, text);
}
}
void setShowPackageAccess(ToolOption opt, String arg) {
void setShowPackageAccess(ToolOption opt, String arg) throws OptionException {
switch (arg) {
case "exported":
jdtoolOpts.put(opt, AccessKind.PUBLIC);
@ -515,16 +529,17 @@ public enum ToolOption {
jdtoolOpts.put(opt, AccessKind.PRIVATE);
break;
default:
usageError("main.illegal_option_value", arg);
String text = getLocalizedMessage("main.illegal_option_value", arg);
throw new IllegalOptionValue(this::usage, text);
}
}
void setFilter(ToolOption opt, String arg) {
void setFilter(ToolOption opt, String arg) throws OptionException {
jdtoolOpts.put(opt, getAccessValue(arg));
}
void setSimpleFilter(String arg) {
void setSimpleFilter(String arg) throws OptionException {
handleSimpleOption(arg);
}
@ -532,7 +547,7 @@ public enum ToolOption {
fileManagerOpts.put(opt, arg);
}
void handleSimpleOption(String arg) {
void handleSimpleOption(String arg) throws OptionException {
populateSimpleAccessMap(getAccessValue(arg));
}
@ -541,7 +556,7 @@ public enum ToolOption {
* -private, so on, in addition to the new ones such as
* --show-types:public and so on.
*/
private AccessKind getAccessValue(String arg) {
private AccessKind getAccessValue(String arg) throws OptionException {
int colon = arg.indexOf(':');
String value = (colon > 0)
? arg.substring(colon + 1)
@ -556,8 +571,8 @@ public enum ToolOption {
case "private":
return AccessKind.PRIVATE;
default:
usageError("main.illegal_option_value", value);
return null;
String text = getLocalizedMessage("main.illegal_option_value", value);
throw new IllegalOptionValue(this::usage, text);
}
}

View file

@ -265,13 +265,13 @@ main.Loading_source_file=Loading source file {0}...
main.Building_tree=Constructing Javadoc information...
main.no_source_files_for_package=No source files for package {0}
main.package_not_found=Package {0} not found
main.fatal.error=fatal error
main.fatal.exception=fatal exception
main.fatal.error=fatal error encountered: {0}
main.out.of.memory=java.lang.OutOfMemoryError: Please increase memory.\n\
For example, on the JDK Classic or HotSpot VMs, add the option -J-Xmx\n\
such as -J-Xmx32m.
main.done_in=[done in {0} ms]
main.more_than_one_doclet_specified_0_and_1=More than one doclet specified ({0} and {1}).
main.doclet_could_not_get_location=Could not get location for {0}
main.doclet_could_not_set_location=Could not set location for {0}
main.doclet_no_classloader_found=Could not obtain classloader to load {0}
main.could_not_instantiate_class=Could not instantiate class {0}
@ -286,7 +286,15 @@ main.illegal_option_value=Illegal option value: "{0}"
main.release.bootclasspath.conflict=option {0} cannot be used together with -release
main.unsupported.release.version=release version {0} not supported
main.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager.
main.file.manager.list=FileManager error listing files: "{0}"
main.assertion.error=assertion failed: "{0}}"
main.unknown.error=an unknown error has occurred
main.internal.error=an internal error has occurred
main.unexpected.exception=an unexpected exception was caught: {0}
doclet.internal.report.bug=\
Please file a bug against the javadoc tool via the Java bug reporting page\n\
(http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com)\n\
for duplicates. Include error messages and the following diagnostic in your report. Thank you.
main.legacy_api=The old Doclet and Taglet APIs in the packages\n\
com.sun.javadoc, com.sun.tools.doclets and their implementations\n\
are planned to be removed in a future JDK release. These\n\

View file

@ -42,7 +42,7 @@ public class T6735320 extends JavadocTester {
void test() {
javadoc("-d", "out",
testSrc("SerialFieldTest.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.STDERR, false,
"OutOfBoundsException");
}

View file

@ -42,7 +42,7 @@ public class TestDupThrowsTags extends JavadocTester {
void test() {
javadoc("-d", "out",
testSrc("TestDupThrowsTags.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput("TestDupThrowsTags.html", true,
"Test 1 passes",

View file

@ -327,15 +327,27 @@ public abstract class JavadocTester {
outputDirectoryCheck = c;
}
/**
* The exit codes returned by the javadoc tool.
* @see jdk.javadoc.internal.tool.Main.Result
*/
public enum Exit {
OK(0),
FAILED(1);
OK(0), // Javadoc completed with no errors.
ERROR(1), // Completed but reported errors.
CMDERR(2), // Bad command-line arguments
SYSERR(3), // System error or resource exhaustion.
ABNORMAL(4); // Javadoc terminated abnormally
Exit(int code) {
this.code = code;
}
final int code;
@Override
public String toString() {
return name() + '(' + code + ')';
}
}
/**
@ -349,7 +361,7 @@ public abstract class JavadocTester {
if (exitCode == expected.code) {
passed("return code " + exitCode);
} else {
failed("return code " + exitCode +"; expected " + expected.code + " (" + expected + ")");
failed("return code " + exitCode +"; expected " + expected);
}
}

View file

@ -50,6 +50,6 @@ public class TestBadSourceFile extends JavadocTester {
javadoc("-Xdoclint:none",
"-d", "out",
testSrc("C2.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
}
}

View file

@ -45,7 +45,7 @@ public class TestConstantValuesPage extends JavadocTester {
javadoc("-d", "out",
"-sourcepath", testSrc,
"foo");
checkExit(Exit.FAILED);
checkExit(Exit.CMDERR);
checkOutput(Output.OUT, false,
"constant-values.html...");

View file

@ -52,6 +52,8 @@ public class TestDocErrorReporter extends JavadocTester {
"-encoding", "xyz",
testSrc("TestDocErrorReporter.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true, "error: unsupported encoding: xyz");
}
}

View file

@ -111,7 +111,7 @@ public class TestHelpOption extends JavadocTester {
"-helpfile", testSrc("test-help.html"),
"-helpfile", testSrc("test-help.html"),
testSrc("Sample.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
}
@Test
@ -121,7 +121,7 @@ public class TestHelpOption extends JavadocTester {
"-helpfile", testSrc("test-help.html"),
"-nohelp",
testSrc("Sample.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
}
private void checkOutput(boolean withOption) {

View file

@ -57,7 +57,7 @@ public class TestIOException extends JavadocTester {
try {
javadoc("-d", outDir.toString(),
new File(testSrc, "TestIOException.java").getPath());
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true,
"Destination directory not writable: " + outDir);
} finally {
@ -85,7 +85,7 @@ public class TestIOException extends JavadocTester {
javadoc("-d", outDir.toString(),
new File(testSrc, "TestIOException.java").getPath());
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true,
"Error writing file: " + index);
} finally {
@ -123,7 +123,7 @@ public class TestIOException extends JavadocTester {
setOutputDirectoryCheck(DirectoryCheck.NONE);
javadoc("-d", outDir.toString(),
src_p_C.getPath());
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true,
"Error writing file: " + new File(pkgOutDir, "C.html"));
} finally {
@ -167,7 +167,7 @@ public class TestIOException extends JavadocTester {
javadoc("-d", outDir.toString(),
"-sourcepath", srcDir.getPath(),
"p");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true,
"Error writing file: " + new File(docFilesOutDir, "info.txt"));
} finally {

View file

@ -42,7 +42,7 @@ public class TestPackageHtml extends JavadocTester {
javadoc("-d", "out-pkg-html",
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true, "package.html:10: error: bad use of '>'");
}
}

View file

@ -46,7 +46,7 @@ public class TestParamTaglet extends JavadocTester {
javadoc("-d", "out",
"-sourcepath", testSrc,
"pkg");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput("pkg/C.html", true,
//Regular param tags.

View file

@ -73,7 +73,7 @@ public class TestSearch extends JavadocTester {
void test2a() {
javadoc("-d", "out-2a", "-Xdoclint:all", "-sourcepath", testSrc,
"-use", "pkg", "pkg1", "pkg2", "pkg3");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkDocLintErrors();
checkSearchOutput(true);
checkSingleIndex(true);

View file

@ -44,7 +44,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester {
javadoc("-d", "out-default",
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.FAILED); // TODO: should be OK
checkExit(Exit.OK);
checkCommentDeprecated(true);
checkNoComment(false);
@ -56,7 +56,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester {
"-nocomment",
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.FAILED); // TODO: should be OK
checkExit(Exit.OK);
checkNoComment(true);
checkCommentDeprecated(false);
@ -68,7 +68,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester {
"-nodeprecated",
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.FAILED); // TODO: should be OK
checkExit(Exit.OK);
checkNoDeprecated(true);
checkNoCommentNoDeprecated(false);
@ -81,7 +81,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester {
"-nodeprecated",
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.FAILED); // TODO: should be OK
checkExit(Exit.OK);
checkNoCommentNoDeprecated(true);
checkNoDeprecated(false);
}
@ -93,7 +93,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester {
"<dl>\n"
+ "<dt><span class=\"throwsLabel\">Throws:</span></dt>\n"
+ "<dd><code>"
+ "java.io.IOException</code></dd>\n"
+ "java.io.IOException</code> - on error</dd>\n"
+ "<dt><span class=\"seeLabel\">See Also:</span>"
+ "</dt>\n"
+ "<dd><a href=\"pkg1/C1.html#setUndecorated-boolean-\">"
@ -121,7 +121,7 @@ public class TestSerializedFormDeprecationInfo extends JavadocTester {
+ "<div class=\"block\">Reads the object stream.</div>\n"
+ "<dl>\n"
+ "<dt><span class=\"throwsLabel\">Throws:</span></dt>\n"
+ "<dd><code>java.io.IOException</code></dd>\n"
+ "<dd><code>java.io.IOException</code> - on error</dd>\n"
+ "</dl>",
"<span class=\"deprecatedLabel\">Deprecated.</span>"
+ "&nbsp;</div>\n"

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 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
@ -75,7 +75,6 @@ public class C1 implements Serializable {
* @param test boolean value
* @exception IllegalArgumentException if the <code>owner</code>'s
* <code>GraphicsConfiguration</code> is not from a screen device
* @exception HeadlessException
*/
public C1(String title, boolean test) {
@ -98,6 +97,7 @@ public class C1 implements Serializable {
}
/**
* @throws java.io.IOException on error
* @see #setUndecorated(boolean)
*/
public void readObject() throws IOException {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 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
@ -74,7 +74,7 @@ public class C2 implements Serializable {
* Reads the object stream.
*
* @param s ObjectInputStream
* @throws IOException
* @throws IOException on error
* @deprecated As of JDK version 1.5, replaced by
* {@link C1#setUndecorated(boolean) setUndecorated(boolean)}.
*/

View file

@ -45,7 +45,7 @@ public class TestSinceTag extends JavadocTester {
javadoc("-d", "out-since",
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.FAILED); // TODO: investigate
checkExit(Exit.OK);
checkSince(true);
}
@ -56,7 +56,7 @@ public class TestSinceTag extends JavadocTester {
"-sourcepath", testSrc,
"-nosince",
"pkg1");
checkExit(Exit.FAILED); // TODO: investigate
checkExit(Exit.OK);
checkSince(false);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -72,7 +72,6 @@ public class C1 implements Serializable {
* @param test boolean value
* @exception IllegalArgumentException if the <code>owner</code>'s
* <code>GraphicsConfiguration</code> is not from a screen device
* @exception HeadlessException
*/
public C1(String title, boolean test) {
}
@ -93,6 +92,7 @@ public class C1 implements Serializable {
}
/**
* @throws java.io.IOException on error
* @see #setUndecorated(boolean)
*/
public void readObject() throws IOException {

View file

@ -52,7 +52,7 @@ public class TestSupplementary extends JavadocTester {
javadoc("-locale", "en_US",
"-d", "out",
testSrc("C.java"));
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true,
"C.java:36: error: unexpected text",

View file

@ -45,7 +45,7 @@ public class TestThrowsTag extends JavadocTester {
javadoc("-d", "out",
"-sourcepath", testSrc,
"pkg");
checkExit(Exit.FAILED); // TODO: investigate why failed
checkExit(Exit.OK);
checkOutput("pkg/C.html", true,
"<dd><code><a href=\"../pkg/T1.html\" title=\"class in pkg\">T1</a></code> - the first throws tag.</dd>\n" +

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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
@ -23,4 +23,4 @@
package pkg;
public class T1 extends Exception {}
public class T1 extends RuntimeException {}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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
@ -23,4 +23,4 @@
package pkg;
public class T2 extends Exception {}
public class T2 extends RuntimeException {}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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
@ -23,4 +23,4 @@
package pkg;
public class T3 extends Exception {}
public class T3 extends RuntimeException {}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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
@ -23,4 +23,4 @@
package pkg;
public class T4 extends Exception {}
public class T4 extends RuntimeException {}

View file

@ -46,7 +46,7 @@ public class TestValueTag extends JavadocTester {
"-sourcepath", testSrc,
"-tag", "todo",
"pkg1", "pkg2");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput("pkg1/Class1.html", true,
// Base case: using @value on a constant.

View file

@ -47,7 +47,7 @@ public class TestWarnings extends JavadocTester {
javadoc("-d", "out-default",
"-sourcepath", testSrc,
"pkg");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true,
"X.java:23: error: self-closing element not allowed");
@ -75,7 +75,7 @@ public class TestWarnings extends JavadocTester {
"-private",
"-sourcepath", testSrc,
"pkg");
checkExit(Exit.FAILED);
checkExit(Exit.ERROR);
checkOutput("pkg/X.html", true,
"<a href=\"../pkg/X.html#m--\"><code>m()</code></a><br/>",

View file

@ -28,7 +28,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import jdk.javadoc.internal.tool.Main;
import jdk.javadoc.internal.tool.Main.Result;
import static jdk.javadoc.internal.tool.Main.Result.*;
/**
* @test
@ -43,13 +47,13 @@ public class ReleaseOption {
}
void run() {
doRunTest(0, out -> out.contains("compiler.err.doesnt.exist: java.util.stream"), "--release", "7");
doRunTest(0, out -> !out.contains("compiler.err.doesnt.exist: java.util.stream"), "--release", "8");
doRunTest(1, out -> true, "--release", "7", "-source", "7");
doRunTest(1, out -> true, "--release", "7", "-bootclasspath", "any");
doRunTest(OK, out -> out.contains("compiler.err.doesnt.exist: java.util.stream"), "--release", "7");
doRunTest(OK, out -> !out.contains("compiler.err.doesnt.exist: java.util.stream"), "--release", "8");
doRunTest(CMDERR, out -> true, "--release", "7", "-source", "7");
doRunTest(CMDERR, out -> true, "--release", "7", "-bootclasspath", "any");
}
void doRunTest(int expectedResult, Predicate<String> validate, String... args) {
void doRunTest(Result expectedResult, Predicate<String> validate, String... args) {
System.err.println("running with args: " + Arrays.asList(args));
List<String> options = new ArrayList<>();
options.addAll(Arrays.asList(args));
@ -60,7 +64,7 @@ public class ReleaseOption {
int actualResult = Main.execute(options.toArray(new String[0]), pw);
System.err.println("actual result=" + actualResult);
System.err.println("actual output=" + out.toString());
if (actualResult != expectedResult)
if (actualResult != expectedResult.exitCode)
throw new Error("Exit code not as expected");
if (!validate.test(out.toString())) {
throw new Error("Output not as expected");

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 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.
*
* 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 8151102
* @summary verify that option --dump-on-error functions correctly
* @library /tools/lib
* @modules
* jdk.javadoc/jdk.javadoc.internal.api
* jdk.javadoc/jdk.javadoc.internal.tool
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* @build toolbox.ToolBox toolbox.TestRunner
* @run main TestExceptionHandling
*/
import java.io.File;
import java.io.PrintStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import toolbox.*;
/**
* This class tests if stack traces printed when
* --dump-on-error. The standard doclet is used,
* to test the doclet as well as the tool.
*/
public class TestExceptionHandling extends TestRunner {
final ToolBox tb;
final File testSrcFile;
final PrintStream ostream;
final JavadocTask cmdTask;
final JavadocTask apiTask;
public static void main(String... args) throws Exception {
TestExceptionHandling tester = new TestExceptionHandling();
tester.runTests();
}
TestExceptionHandling() {
super(System.err);
tb = new ToolBox();
ostream = System.err;
testSrcFile = new File(System.getProperty("test.src"), "TestExceptionHandling.java");
cmdTask = new JavadocTask(tb, Task.Mode.CMDLINE);
apiTask = new JavadocTask(tb, Task.Mode.API);
}
@Test
public void testDocletTrace() throws Exception {
Path out = Paths.get("out");
// create a file with the same name as the output
out.toFile().createNewFile();
cmdTask.outdir(out);
cmdTask.options("--dump-on-error");
cmdTask.files(testSrcFile.getAbsolutePath());
Task.Result tr = cmdTask.run(Task.Expect.FAIL);
String errString = "Destination directory is not a directory: " + out.toString();
// check the regular message
assertPresent("javadoc: error - " + errString, tr.getOutputLines(Task.OutputKind.DIRECT));
// check that first line of the stack trace is present
assertPresent("jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException: " +
errString, tr.getOutputLines(Task.OutputKind.STDERR));
}
@Test
public void testToolTrace() throws Exception {
Path out = Paths.get("out.dir");
cmdTask.options("--dump-on-error", "-doclet", "NonExistentDoclet");
cmdTask.outdir(out);
cmdTask.files(testSrcFile.getAbsolutePath());
Task.Result tr = cmdTask.run(Task.Expect.FAIL);
// check the regular message
assertPresent("javadoc: error - Cannot find doclet class NonExistentDoclet",
tr.getOutputLines(Task.OutputKind.DIRECT));
// check that first line of the stack trace is present
assertPresent("java.lang.ClassNotFoundException: NonExistentDoclet",
tr.getOutputLines(Task.OutputKind.STDERR));
}
@Test
public void testApiModeMissingDoclet() throws Exception {
apiTask.options("-doclet", "MissingDoclet");
try {
Task.Result result = apiTask.run(Task.Expect.FAIL);
} catch (IllegalArgumentException iae) {
// ok got the right exception
return;
}
throw new Exception("expected exception/error not found");
}
@Test
public void testApiModeMultipleDoclets() throws Exception {
apiTask.options("-doclet", "MissingDoclet",
"-doclet", "SomeDoclet");
try {
Task.Result result = apiTask.run(Task.Expect.FAIL);
} catch (IllegalArgumentException iae) {
// ok got the right exception
return;
}
throw new Exception("expected exception/error not found");
}
void assertPresent(String regex, List<String> output) throws Exception {
List<String> gresult = tb.grep(regex, output);
if (gresult.isEmpty()) {
ostream.println("Expected: " + regex);
ostream.println("Output: ");
output.forEach(s -> {
ostream.println(s);
});
throw new Exception("Test fails expected output not found: " + regex);
}
}
}