mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8154482: javadoc tool must support legacy doclet and taglet
Reviewed-by: jjg
This commit is contained in:
parent
9290ce0c7b
commit
4be9fb29fa
9 changed files with 564 additions and 131 deletions
|
@ -1,4 +1,4 @@
|
||||||
doclet.build_version=Standard Doclet version {0}
|
doclet.build_version=Standard Doclet (Old) version {0}
|
||||||
doclet.Contents=Contents
|
doclet.Contents=Contents
|
||||||
doclet.Overview=Overview
|
doclet.Overview=Overview
|
||||||
doclet.Window_Overview=Overview List
|
doclet.Window_Overview=Overview List
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
doclet.build_version=Standard Doclet (Next) version {0}
|
doclet.build_version=Standard Doclet version {0}
|
||||||
doclet.Contents=Contents
|
doclet.Contents=Contents
|
||||||
doclet.Overview=Overview
|
doclet.Overview=Overview
|
||||||
doclet.Window_Overview=Overview List
|
doclet.Window_Overview=Overview List
|
||||||
|
|
|
@ -550,7 +550,7 @@ public class DocEnv {
|
||||||
// Messager should be replaced by a more general
|
// Messager should be replaced by a more general
|
||||||
// compilation environment. This can probably
|
// compilation environment. This can probably
|
||||||
// subsume DocEnv as well.
|
// subsume DocEnv as well.
|
||||||
messager.exit();
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,13 +59,6 @@ public class Main {
|
||||||
* @return The return code.
|
* @return The return code.
|
||||||
*/
|
*/
|
||||||
public static int execute(String... args) {
|
public static int execute(String... args) {
|
||||||
// NOTE: the following should be removed when the old doclet
|
|
||||||
// is removed.
|
|
||||||
if (args != null && args.length > 0 && "-Xold".equals(args[0])) {
|
|
||||||
String[] nargs = new String[args.length - 1];
|
|
||||||
System.arraycopy(args, 1, nargs, 0, nargs.length);
|
|
||||||
return com.sun.tools.javadoc.Main.execute(nargs);
|
|
||||||
}
|
|
||||||
Start jdoc = new Start();
|
Start jdoc = new Start();
|
||||||
return jdoc.begin(args);
|
return jdoc.begin(args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -139,7 +139,7 @@ public class Messager extends Log implements Reporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ExitJavadoc extends Error {
|
public static class ExitJavadoc extends Error {
|
||||||
private static final long serialVersionUID = 0;
|
private static final long serialVersionUID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,15 +416,6 @@ public class Messager extends Log implements Reporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Force program exit, e.g., from a fatal error.
|
|
||||||
* <p>
|
|
||||||
* TODO: This method does not really belong here.
|
|
||||||
*/
|
|
||||||
public void exit() {
|
|
||||||
throw new ExitJavadoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void report(DiagnosticType type, String pos, String msg) {
|
private void report(DiagnosticType type, String pos, String msg) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ERROR:
|
case ERROR:
|
||||||
|
|
|
@ -66,6 +66,7 @@ import jdk.javadoc.doclet.Doclet.Option;
|
||||||
import jdk.javadoc.doclet.DocletEnvironment;
|
import jdk.javadoc.doclet.DocletEnvironment;
|
||||||
|
|
||||||
import static com.sun.tools.javac.main.Option.*;
|
import static com.sun.tools.javac.main.Option.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main program of Javadoc.
|
* Main program of Javadoc.
|
||||||
* Previously named "Main".
|
* Previously named "Main".
|
||||||
|
@ -79,6 +80,12 @@ import static com.sun.tools.javac.main.Option.*;
|
||||||
* @author Neal Gafter (rewrite)
|
* @author Neal Gafter (rewrite)
|
||||||
*/
|
*/
|
||||||
public class Start extends ToolOption.Helper {
|
public class Start extends ToolOption.Helper {
|
||||||
|
|
||||||
|
private static final Class<?> OldStdDoclet =
|
||||||
|
com.sun.tools.doclets.standard.Standard.class;
|
||||||
|
|
||||||
|
private static final Class<?> StdDoclet =
|
||||||
|
jdk.javadoc.internal.doclets.standard.Standard.class;
|
||||||
/** Context for this invocation. */
|
/** Context for this invocation. */
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
|
@ -193,18 +200,26 @@ public class Start extends ToolOption.Helper {
|
||||||
if (foot != null)
|
if (foot != null)
|
||||||
messager.notice(foot);
|
messager.notice(foot);
|
||||||
|
|
||||||
if (exit) exit();
|
if (exit)
|
||||||
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Exit
|
|
||||||
*/
|
|
||||||
private void exit() {
|
|
||||||
messager.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main program - external wrapper
|
* Main program - external wrapper. In order to maintain backward
|
||||||
|
* CLI compatibility, we dispatch to the old tool or the old doclet's
|
||||||
|
* Start mechanism, based on the options present on the command line
|
||||||
|
* with the following precedence:
|
||||||
|
* 1. presence of -Xold, dispatch to old tool
|
||||||
|
* 2. doclet variant, if old, dispatch to old Start
|
||||||
|
* 3. taglet variant, if old, dispatch to old Start
|
||||||
|
*
|
||||||
|
* Thus the presence of -Xold switches the tool, soon after command files
|
||||||
|
* if any, are expanded, this is performed here, noting that the messager
|
||||||
|
* is available at this point in time.
|
||||||
|
* The doclet/taglet tests are performed in the begin method, further on,
|
||||||
|
* this is to minimize argument processing and most importantly the impact
|
||||||
|
* of class loader creation, needed to detect the doclet/taglet class variants.
|
||||||
*/
|
*/
|
||||||
int begin(String... argv) {
|
int begin(String... argv) {
|
||||||
// Preprocess @file arguments
|
// Preprocess @file arguments
|
||||||
|
@ -212,14 +227,18 @@ public class Start extends ToolOption.Helper {
|
||||||
argv = CommandLine.parse(argv);
|
argv = CommandLine.parse(argv);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
messager.error("main.cant.read", e.getMessage());
|
messager.error("main.cant.read", e.getMessage());
|
||||||
exit();
|
throw new Messager.ExitJavadoc();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace(System.err);
|
e.printStackTrace(System.err);
|
||||||
exit();
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> argList = Arrays.asList(argv);
|
if (argv.length > 0 && "-Xold".equals(argv[0])) {
|
||||||
boolean ok = begin(argList, Collections.<JavaFileObject> emptySet());
|
messager.warning("main.legacy_api");
|
||||||
|
String[] nargv = Arrays.copyOfRange(argv, 1, argv.length);
|
||||||
|
return com.sun.tools.javadoc.Main.execute(nargv);
|
||||||
|
}
|
||||||
|
boolean ok = begin(Arrays.asList(argv), Collections.<JavaFileObject> emptySet());
|
||||||
return ok ? 0 : 1;
|
return ok ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,11 +250,11 @@ public class Start extends ToolOption.Helper {
|
||||||
List<String> opts = new ArrayList<>();
|
List<String> opts = new ArrayList<>();
|
||||||
for (String opt: options)
|
for (String opt: options)
|
||||||
opts.add(opt);
|
opts.add(opt);
|
||||||
|
|
||||||
return begin(opts, fileObjects);
|
return begin(opts, fileObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
|
private boolean begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
|
||||||
|
|
||||||
fileManager = context.get(JavaFileManager.class);
|
fileManager = context.get(JavaFileManager.class);
|
||||||
if (fileManager == null) {
|
if (fileManager == null) {
|
||||||
JavacFileManager.preRegister(context);
|
JavacFileManager.preRegister(context);
|
||||||
|
@ -244,9 +263,8 @@ public class Start extends ToolOption.Helper {
|
||||||
((BaseFileManager) fileManager).autoClose = true;
|
((BaseFileManager) fileManager).autoClose = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// locale and doclet needs to be determined first
|
// locale, doclet and maybe taglet, needs to be determined first
|
||||||
docletClass = preProcess(fileManager, options);
|
docletClass = preProcess(fileManager, options);
|
||||||
|
|
||||||
if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
|
if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
|
||||||
// no need to dispatch to old, safe to init now
|
// no need to dispatch to old, safe to init now
|
||||||
initMessager();
|
initMessager();
|
||||||
|
@ -257,7 +275,7 @@ public class Start extends ToolOption.Helper {
|
||||||
exc.printStackTrace();
|
exc.printStackTrace();
|
||||||
if (!apiMode) {
|
if (!apiMode) {
|
||||||
error("main.could_not_instantiate_class", docletClass);
|
error("main.could_not_instantiate_class", docletClass);
|
||||||
messager.exit();
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
}
|
||||||
throw new ClientCodeException(exc);
|
throw new ClientCodeException(exc);
|
||||||
}
|
}
|
||||||
|
@ -267,6 +285,7 @@ public class Start extends ToolOption.Helper {
|
||||||
= new com.sun.tools.javadoc.Start(context);
|
= new com.sun.tools.javadoc.Start(context);
|
||||||
return ostart.begin(docletClass, options, fileObjects);
|
return ostart.begin(docletClass, options, fileObjects);
|
||||||
}
|
}
|
||||||
|
warn("main.legacy_api");
|
||||||
String[] array = options.toArray(new String[options.size()]);
|
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;
|
||||||
}
|
}
|
||||||
|
@ -459,6 +478,11 @@ public class Start extends ToolOption.Helper {
|
||||||
String userDocletPath = null;
|
String userDocletPath = null;
|
||||||
String userDocletName = null;
|
String userDocletName = null;
|
||||||
|
|
||||||
|
// taglet specifying arguments, since tagletpath is a doclet
|
||||||
|
// functionality, assume they are repeated and inspect all.
|
||||||
|
List<File> userTagletPath = new ArrayList<>();
|
||||||
|
List<String> userTagletNames = new ArrayList<>();
|
||||||
|
|
||||||
// Step 1: loop through the args, set locale early on, if found.
|
// Step 1: loop through the args, set locale early on, if found.
|
||||||
for (int i = 0 ; i < argv.size() ; i++) {
|
for (int i = 0 ; i < argv.size() ; i++) {
|
||||||
String arg = argv.get(i);
|
String arg = argv.get(i);
|
||||||
|
@ -470,7 +494,7 @@ public class Start extends ToolOption.Helper {
|
||||||
oneArg(argv, i++);
|
oneArg(argv, i++);
|
||||||
if (userDocletName != null) {
|
if (userDocletName != null) {
|
||||||
usageError("main.more_than_one_doclet_specified_0_and_1",
|
usageError("main.more_than_one_doclet_specified_0_and_1",
|
||||||
userDocletName, argv.get(i));
|
userDocletName, argv.get(i));
|
||||||
}
|
}
|
||||||
if (docletName != null) {
|
if (docletName != null) {
|
||||||
usageError("main.more_than_one_doclet_specified_0_and_1",
|
usageError("main.more_than_one_doclet_specified_0_and_1",
|
||||||
|
@ -484,13 +508,20 @@ public class Start extends ToolOption.Helper {
|
||||||
} else {
|
} else {
|
||||||
userDocletPath += File.pathSeparator + argv.get(i);
|
userDocletPath += File.pathSeparator + argv.get(i);
|
||||||
}
|
}
|
||||||
|
} else if ("-taglet".equals(arg)) {
|
||||||
|
userTagletNames.add(argv.get(i + 1));
|
||||||
|
} else if ("-tagletpath".equals(arg)) {
|
||||||
|
for (String pathname : argv.get(i + 1).split(File.pathSeparator)) {
|
||||||
|
userTagletPath.add(new File(pathname));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Step 2: a doclet has already been provided,
|
|
||||||
// nothing more to do.
|
// Step 2: a doclet is provided, nothing more to do.
|
||||||
if (docletClass != null) {
|
if (docletClass != null) {
|
||||||
return docletClass;
|
return docletClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: doclet name specified ? if so find a ClassLoader,
|
// Step 3: doclet name specified ? if so find a ClassLoader,
|
||||||
// and load it.
|
// and load it.
|
||||||
if (userDocletName != null) {
|
if (userDocletName != null) {
|
||||||
|
@ -506,38 +537,80 @@ public class Start extends ToolOption.Helper {
|
||||||
try {
|
try {
|
||||||
((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
|
((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
panic("main.doclet_no_classloader_found", ioe);
|
error("main.doclet_could_not_set_location", paths);
|
||||||
return null; // keep compiler happy
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cl = fileManager.getClassLoader(DOCLET_PATH);
|
cl = fileManager.getClassLoader(DOCLET_PATH);
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
// despite doclet specified on cmdline no classloader found!
|
// despite doclet specified on cmdline no classloader found!
|
||||||
panic("main.doclet_no_classloader_found", userDocletName);
|
error("main.doclet_no_classloader_found", userDocletName);
|
||||||
return null; // keep compiler happy
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
|
||||||
try {
|
|
||||||
Class<?> klass = cl.loadClass(userDocletName);
|
|
||||||
ensureReadable(klass);
|
|
||||||
return klass;
|
|
||||||
} catch (ClassNotFoundException cnfe) {
|
|
||||||
panic("main.doclet_class_not_found", userDocletName);
|
|
||||||
return null; // keep compiler happy
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
Class<?> klass = cl.loadClass(userDocletName);
|
||||||
|
ensureReadable(klass);
|
||||||
|
return klass;
|
||||||
|
} catch (ClassNotFoundException cnfe) {
|
||||||
|
error("main.doclet_class_not_found", userDocletName);
|
||||||
|
throw new Messager.ExitJavadoc();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Step 4: we have a doclet, try loading it, otherwise
|
|
||||||
// return back the standard doclet
|
// Step 4: we have a doclet, try loading it
|
||||||
if (docletName != null) {
|
if (docletName != null) {
|
||||||
try {
|
try {
|
||||||
return Class.forName(docletName, true, getClass().getClassLoader());
|
return Class.forName(docletName, true, getClass().getClassLoader());
|
||||||
} catch (ClassNotFoundException cnfe) {
|
} catch (ClassNotFoundException cnfe) {
|
||||||
panic("main.doclet_class_not_found", userDocletName);
|
error("main.doclet_class_not_found", userDocletName);
|
||||||
return null; // happy compiler, should not happen
|
throw new Messager.ExitJavadoc();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return jdk.javadoc.internal.doclets.standard.Standard.class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 5: we don't have a doclet specified, do we have taglets ?
|
||||||
|
if (!userTagletNames.isEmpty() && hasOldTaglet(userTagletNames, userTagletPath)) {
|
||||||
|
// found a bogey, return the old doclet
|
||||||
|
return OldStdDoclet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally
|
||||||
|
return StdDoclet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method returns true iff it finds a legacy taglet, but for
|
||||||
|
* all other conditions including errors it returns false, allowing
|
||||||
|
* nature to take its own course.
|
||||||
|
*/
|
||||||
|
private boolean hasOldTaglet(List<String> tagletNames, List<File> tagletPaths) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
for (String tagletName : tagletNames) {
|
||||||
|
try {
|
||||||
|
Class<?> klass = cl.loadClass(tagletName);
|
||||||
|
ensureReadable(klass);
|
||||||
|
if (com.sun.tools.doclets.Taglet.class.isAssignableFrom(klass)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException cnfe) {
|
||||||
|
error("main.doclet_class_not_found", tagletName);
|
||||||
|
throw new Messager.ExitJavadoc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseArgs(List<String> args, List<String> javaNames) {
|
private void parseArgs(List<String> args, List<String> javaNames) {
|
||||||
|
@ -595,16 +668,14 @@ public class Start extends ToolOption.Helper {
|
||||||
usage(true);
|
usage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a terminal call, will not return
|
|
||||||
void panic(String key, Object... args) {
|
|
||||||
error(key, args);
|
|
||||||
messager.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void error(String key, Object... args) {
|
void error(String key, Object... args) {
|
||||||
messager.error(key, args);
|
messager.error(key, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void warn(String key, Object... args) {
|
||||||
|
messager.warning(key, args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* indicate an option with no arguments was given.
|
* indicate an option with no arguments was given.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,7 +73,8 @@ main.Xusage=\
|
||||||
\ given module. <other-module> may be ALL-UNNAMED to require\n\
|
\ given module. <other-module> may be ALL-UNNAMED to require\n\
|
||||||
\ the unnamed module.\n\
|
\ the unnamed module.\n\
|
||||||
\ -Xmodule:<module-name> Specify a module to which the classes being compiled belong.\n\
|
\ -Xmodule:<module-name> Specify a module to which the classes being compiled belong.\n\
|
||||||
\ -Xpatch:<path> Specify location of module class files to patch\n
|
\ -Xpatch:<path> Specify location of module class files to patch\n\
|
||||||
|
\ -Xold Invoke the legacy javadoc tool\n
|
||||||
|
|
||||||
main.Xusage.foot=\
|
main.Xusage.foot=\
|
||||||
These options are non-standard and subject to change without notice.
|
These options are non-standard and subject to change without notice.
|
||||||
|
@ -96,6 +97,7 @@ For example, on the JDK Classic or HotSpot VMs, add the option -J-Xmx\n\
|
||||||
such as -J-Xmx32m.
|
such as -J-Xmx32m.
|
||||||
main.done_in=[done in {0} ms]
|
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.more_than_one_doclet_specified_0_and_1=More than one doclet specified ({0} and {1}).
|
||||||
|
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.doclet_no_classloader_found=Could not obtain classloader to load {0}
|
||||||
main.could_not_instantiate_class=Could not instantiate class {0}
|
main.could_not_instantiate_class=Could not instantiate class {0}
|
||||||
main.doclet_class_not_found=Cannot find doclet class {0}
|
main.doclet_class_not_found=Cannot find doclet class {0}
|
||||||
|
@ -109,10 +111,15 @@ main.release.bootclasspath.conflict=option {0} cannot be used together with -rel
|
||||||
main.unsupported.release.version=release version {0} not supported
|
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.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager.
|
||||||
main.unknown.error=an unknown error has occurred
|
main.unknown.error=an unknown error has occurred
|
||||||
|
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\
|
||||||
|
components have been superseded by the new APIs in jdk.javadoc.doclet.\n\
|
||||||
|
Users are strongly recommended to migrate to the new APIs.\n
|
||||||
|
|
||||||
javadoc.class_not_found=Class {0} not found.
|
javadoc.class_not_found=Class {0} not found.
|
||||||
javadoc.error=error
|
javadoc.error=error
|
||||||
javadoc.warning=warning
|
javadoc.warning=warning
|
||||||
|
|
||||||
javadoc.error.msg={0}: error - {1}
|
javadoc.error.msg={0}: error - {1}
|
||||||
javadoc.warning.msg={0}: warning - {1}
|
javadoc.warning.msg={0}: warning - {1}
|
||||||
javadoc.note.msg = {1}
|
javadoc.note.msg = {1}
|
||||||
|
|
|
@ -23,96 +23,349 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8035473
|
* @bug 8035473 8154482
|
||||||
* @summary make sure the new doclet is invoked by default, and -Xold
|
* @summary make sure the javadoc tool responds correctly to Xold,
|
||||||
|
* old doclets and taglets.
|
||||||
|
* @library /tools/lib
|
||||||
|
* @build toolbox.ToolBox toolbox.TestRunner
|
||||||
|
* @run main EnsureNewOldDoclet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.sun.javadoc.Tag;
|
||||||
|
import com.sun.source.doctree.DocTree;
|
||||||
|
|
||||||
|
import toolbox.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dummy javadoc comment.
|
* This test ensures the doclet responds correctly when given
|
||||||
|
* various conditions that force a fall back to the old javadoc
|
||||||
|
* tool. The following condition in the order described will
|
||||||
|
* force a dispatch to the old tool, -Xold, old doclet and old taglet.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class EnsureNewOldDoclet {
|
public class EnsureNewOldDoclet extends TestRunner {
|
||||||
|
|
||||||
final File javadoc;
|
final ToolBox tb;
|
||||||
final File testSrc;
|
final File testSrc;
|
||||||
final String thisClassName;
|
final Path javadocPath;
|
||||||
|
final ExecTask task;
|
||||||
|
final String testClasses;
|
||||||
|
final PrintStream ostream;
|
||||||
|
|
||||||
final static Pattern Expected1 = Pattern.compile("^Standard Doclet \\(Next\\) version.*");
|
final static String CLASS_NAME = "EnsureNewOldDoclet";
|
||||||
final static Pattern Expected2 = Pattern.compile("^Standard Doclet version.*");
|
final static String OLD_DOCLET_CLASS_NAME = CLASS_NAME + "$OldDoclet";
|
||||||
|
final static String NEW_DOCLET_CLASS_NAME = CLASS_NAME + "$NewDoclet"; //unused
|
||||||
|
final static String OLD_TAGLET_CLASS_NAME = CLASS_NAME + "$OldTaglet";
|
||||||
|
final static String NEW_TAGLET_CLASS_NAME = CLASS_NAME + "$NewTaglet";
|
||||||
|
|
||||||
public EnsureNewOldDoclet() {
|
final static Pattern OLD_HEADER = Pattern.compile("^Standard Doclet \\(Old\\) version.*");
|
||||||
File javaHome = new File(System.getProperty("java.home"));
|
final static Pattern NEW_HEADER = Pattern.compile("^Standard Doclet version.*");
|
||||||
if (javaHome.getName().endsWith("jre"))
|
|
||||||
javaHome = javaHome.getParentFile();
|
|
||||||
javadoc = new File(new File(javaHome, "bin"), "javadoc");
|
final static String OLD_DOCLET_MARKER = "OLD_DOCLET_MARKER";
|
||||||
testSrc = new File(System.getProperty("test.src"));
|
final static String OLD_TAGLET_MARKER = "Registered: OldTaglet";
|
||||||
thisClassName = EnsureNewOldDoclet.class.getName();
|
|
||||||
|
final static String NEW_DOCLET_MARKER = "NEW_DOCLET_MARKER";
|
||||||
|
final static String NEW_TAGLET_MARKER = "Registered Taglet " + CLASS_NAME + "\\$NewTaglet";
|
||||||
|
|
||||||
|
final static Pattern WARN_TEXT = Pattern.compile("Users are strongly recommended to migrate" +
|
||||||
|
" to the new APIs.");
|
||||||
|
final static String OLD_DOCLET_ERROR = "java.lang.NoSuchMethodException: " +
|
||||||
|
CLASS_NAME +"\\$NewTaglet";
|
||||||
|
final static Pattern NEW_DOCLET_ERROR = Pattern.compile(".*java.lang.ClassCastException.*Taglet " +
|
||||||
|
CLASS_NAME + "\\$OldTaglet.*");
|
||||||
|
|
||||||
|
final static String OLD_STDDOCLET = "com.sun.tools.doclets.standard.Standard";
|
||||||
|
final static String NEW_STDDOCLET = "jdk.javadoc.internal.doclets.standard.Standard";
|
||||||
|
|
||||||
|
|
||||||
|
public EnsureNewOldDoclet() throws Exception {
|
||||||
|
super(System.err);
|
||||||
|
ostream = System.err;
|
||||||
|
testClasses = System.getProperty("test.classes");
|
||||||
|
tb = new ToolBox();
|
||||||
|
javadocPath = tb.getJDKTool("javadoc");
|
||||||
|
task = new ExecTask(tb, javadocPath);
|
||||||
|
testSrc = new File("Foo.java");
|
||||||
|
generateSample(testSrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateSample(File testSrc) throws Exception {
|
||||||
|
String nl = System.getProperty("line.separator");
|
||||||
|
String src = Arrays.asList(
|
||||||
|
"/**",
|
||||||
|
" * A test class to test javadoc. Nothing more nothing less.",
|
||||||
|
" */",
|
||||||
|
" public class Foo{}").stream().collect(Collectors.joining(nl));
|
||||||
|
tb.writeFile(testSrc.getPath(), src);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws Exception {
|
public static void main(String... args) throws Exception {
|
||||||
EnsureNewOldDoclet test = new EnsureNewOldDoclet();
|
new EnsureNewOldDoclet().runTests();
|
||||||
test.run1();
|
|
||||||
test.run2();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure new doclet is invoked by default
|
// input: nothing, default mode
|
||||||
void run1() throws Exception {
|
// outcome: new tool and new doclet
|
||||||
List<String> output = doTest(javadoc.getPath(),
|
@Test
|
||||||
"-classpath", ".", // insulates us from ambient classpath
|
public void testDefault() throws Exception {
|
||||||
"-Xdoclint:none",
|
setArgs("-classpath", ".", // insulates us from ambient classpath
|
||||||
"-package",
|
testSrc.toString());
|
||||||
new File(testSrc, thisClassName + ".java").getPath());
|
Task.Result tr = task.run(Task.Expect.SUCCESS);
|
||||||
System.out.println(output);
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
for (String x : output) {
|
checkOutput(testName, out, NEW_HEADER);
|
||||||
if (Expected1.matcher(x).matches()) {
|
}
|
||||||
|
|
||||||
|
// input: -Xold
|
||||||
|
// outcome: old tool
|
||||||
|
@Test
|
||||||
|
public void testXold() throws Exception {
|
||||||
|
setArgs("-Xold",
|
||||||
|
"-classpath", ".", // ambient classpath insulation
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.SUCCESS);
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, OLD_HEADER);
|
||||||
|
checkOutput(testName, err, WARN_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input: old doclet
|
||||||
|
// outcome: old tool
|
||||||
|
@Test
|
||||||
|
public void testOldDoclet() throws Exception {
|
||||||
|
setArgs("-classpath", ".", // ambient classpath insulation
|
||||||
|
"-doclet",
|
||||||
|
OLD_DOCLET_CLASS_NAME,
|
||||||
|
"-docletpath",
|
||||||
|
testClasses,
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.SUCCESS);
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, OLD_DOCLET_MARKER);
|
||||||
|
checkOutput(testName, err, WARN_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input: old taglet
|
||||||
|
// outcome: old tool
|
||||||
|
@Test
|
||||||
|
public void testOldTaglet() throws Exception {
|
||||||
|
setArgs("-classpath", ".", // ambient classpath insulation
|
||||||
|
"-taglet",
|
||||||
|
OLD_TAGLET_CLASS_NAME,
|
||||||
|
"-tagletpath",
|
||||||
|
testClasses,
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.SUCCESS);
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, OLD_TAGLET_MARKER);
|
||||||
|
checkOutput(testName, err, WARN_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input: new doclet and old taglet
|
||||||
|
// outcome: new doclet with failure
|
||||||
|
@Test
|
||||||
|
public void testNewDocletOldTaglet() throws Exception {
|
||||||
|
setArgs("-classpath", ".", // ambient classpath insulation
|
||||||
|
"-doclet",
|
||||||
|
NEW_STDDOCLET,
|
||||||
|
"-taglet",
|
||||||
|
OLD_TAGLET_CLASS_NAME,
|
||||||
|
"-tagletpath",
|
||||||
|
testClasses,
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.FAIL, 1);
|
||||||
|
//Task.Result tr = task.run();
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, NEW_HEADER);
|
||||||
|
checkOutput(testName, err, NEW_DOCLET_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input: old doclet and old taglet
|
||||||
|
// outcome: old doclet and old taglet should register
|
||||||
|
@Test
|
||||||
|
public void testOldDocletOldTaglet() throws Exception {
|
||||||
|
setArgs("-classpath", ".", // ambient classpath insulation
|
||||||
|
"-doclet",
|
||||||
|
OLD_STDDOCLET,
|
||||||
|
"-taglet",
|
||||||
|
OLD_TAGLET_CLASS_NAME,
|
||||||
|
"-tagletpath",
|
||||||
|
testClasses,
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.SUCCESS);
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, OLD_HEADER);
|
||||||
|
checkOutput(testName, out, OLD_TAGLET_MARKER);
|
||||||
|
checkOutput(testName, err, WARN_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input: new doclet and new taglet
|
||||||
|
// outcome: new doclet and new taglet should register
|
||||||
|
@Test
|
||||||
|
public void testNewDocletNewTaglet() throws Exception {
|
||||||
|
setArgs("-classpath", ".", // ambient classpath insulation
|
||||||
|
"-doclet",
|
||||||
|
NEW_STDDOCLET,
|
||||||
|
"-taglet",
|
||||||
|
NEW_TAGLET_CLASS_NAME,
|
||||||
|
"-tagletpath",
|
||||||
|
testClasses,
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.SUCCESS);
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, NEW_HEADER);
|
||||||
|
checkOutput(testName, out, NEW_TAGLET_MARKER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input: old doclet and new taglet
|
||||||
|
// outcome: old doclet and error
|
||||||
|
@Test
|
||||||
|
public void testOldDocletNewTaglet() throws Exception {
|
||||||
|
setArgs("-classpath", ".", // ambient classpath insulation
|
||||||
|
"-doclet",
|
||||||
|
OLD_STDDOCLET,
|
||||||
|
"-taglet",
|
||||||
|
NEW_TAGLET_CLASS_NAME,
|
||||||
|
"-tagletpath",
|
||||||
|
testClasses,
|
||||||
|
testSrc.toString());
|
||||||
|
Task.Result tr = task.run(Task.Expect.FAIL, 1);
|
||||||
|
List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
|
||||||
|
checkOutput(testName, out, OLD_HEADER);
|
||||||
|
checkOutput(testName, err, WARN_TEXT);
|
||||||
|
checkOutput(testName, err, OLD_DOCLET_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setArgs(String... args) {
|
||||||
|
ostream.println("cmds: " + Arrays.asList(args));
|
||||||
|
task.args(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkOutput(String testCase, List<String> content, String toFind) throws Exception {
|
||||||
|
checkOutput(testCase, content, Pattern.compile(".*" + toFind + ".*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkOutput(String testCase, List<String> content, Pattern toFind) throws Exception {
|
||||||
|
ostream.println("---" + testCase + "---");
|
||||||
|
content.stream().forEach(x -> System.out.println(x));
|
||||||
|
for (String x : content) {
|
||||||
|
ostream.println(x);
|
||||||
|
if (toFind.matcher(x).matches()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Exception("run1: Expected string not found:");
|
throw new Exception(testCase + ": Expected string not found: " + toFind);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the old doclet is invoked with -Xold
|
public static class OldDoclet extends com.sun.javadoc.Doclet {
|
||||||
void run2() throws Exception {
|
public static boolean start(com.sun.javadoc.RootDoc root) {
|
||||||
List<String> output = doTest(javadoc.getPath(),
|
System.out.println(OLD_DOCLET_MARKER);
|
||||||
"-Xold",
|
return true;
|
||||||
"-classpath", ".", // insulates us from ambient classpath
|
|
||||||
"-Xdoclint:none",
|
|
||||||
"-package",
|
|
||||||
new File(testSrc, thisClassName + ".java").getPath());
|
|
||||||
|
|
||||||
for (String x : output) {
|
|
||||||
if (Expected2.matcher(x).matches()) {
|
|
||||||
throw new Exception("run2: Expected string not found");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static class OldTaglet implements com.sun.tools.doclets.Taglet {
|
||||||
* More dummy comments.
|
|
||||||
*/
|
public static void register(Map map) {
|
||||||
List<String> doTest(String... args) throws Exception {
|
EnsureNewOldDoclet.OldTaglet tag = new OldTaglet();
|
||||||
List<String> output = new ArrayList<>();
|
com.sun.tools.doclets.Taglet t = (com.sun.tools.doclets.Taglet) map.get(tag.getName());
|
||||||
// run javadoc in separate process to ensure doclet executed under
|
System.out.println(OLD_TAGLET_MARKER);
|
||||||
// normal user conditions w.r.t. classloader
|
|
||||||
Process p = new ProcessBuilder()
|
|
||||||
.command(args)
|
|
||||||
.redirectErrorStream(true)
|
|
||||||
.start();
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
|
|
||||||
String line = in.readLine();
|
|
||||||
while (line != null) {
|
|
||||||
output.add(line.trim());
|
|
||||||
line = in.readLine();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int rc = p.waitFor();
|
|
||||||
if (rc != 0)
|
@Override
|
||||||
throw new Exception("javadoc failed, rc:" + rc);
|
public boolean inField() {
|
||||||
return output;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inConstructor() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inMethod() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inOverview() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inPackage() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inType() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInlineTag() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "OldTaglet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(Tag tag) {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(Tag[] tags) {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NewTaglet implements jdk.javadoc.doclet.taglet.Taglet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Location> getAllowedLocations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInlineTag() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "NewTaglet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(DocTree tag) {
|
||||||
|
return tag.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(List<? extends DocTree> tags) {
|
||||||
|
return tags.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
118
langtools/test/tools/lib/toolbox/TestRunner.java
Normal file
118
langtools/test/tools/lib/toolbox/TestRunner.java
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package toolbox;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to manage and execute sub-tests within a test.
|
||||||
|
*
|
||||||
|
* This class does the following:
|
||||||
|
* i. invokes those test methods annotated with @Test
|
||||||
|
* ii. keeps track of successful and failed tests
|
||||||
|
* iii. throws an Exception if any test fails.
|
||||||
|
* iv. provides a test summary at the end of the run.
|
||||||
|
*
|
||||||
|
* Tests must extend this class, annotate the test methods
|
||||||
|
* with @Test and call one of the runTests method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class TestRunner {
|
||||||
|
/** Marker annotation for test cases. */
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Test { }
|
||||||
|
|
||||||
|
int testCount = 0;
|
||||||
|
int errorCount = 0;
|
||||||
|
|
||||||
|
public String testName = null;
|
||||||
|
|
||||||
|
final PrintStream out;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the Object.
|
||||||
|
* @param out the PrintStream to print output to.
|
||||||
|
*/
|
||||||
|
public TestRunner(PrintStream out) {
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke all methods annotated with @Test.
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
public void runTests() throws Exception {
|
||||||
|
runTests(f -> new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke all methods annotated with @Test.
|
||||||
|
* @param f a lambda expression to specify arguments.
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
public void runTests(Function<Method, Object[]> f) throws Exception {
|
||||||
|
for (Method m : getClass().getDeclaredMethods()) {
|
||||||
|
Annotation a = m.getAnnotation(Test.class);
|
||||||
|
if (a != null) {
|
||||||
|
testName = m.getName();
|
||||||
|
try {
|
||||||
|
testCount++;
|
||||||
|
out.println("test: " + testName);
|
||||||
|
m.invoke(this, f.apply(m));
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
errorCount++;
|
||||||
|
Throwable cause = e.getCause();
|
||||||
|
out.println("Exception: " + e.getCause());
|
||||||
|
cause.printStackTrace(out);
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testCount == 0) {
|
||||||
|
throw new Error("no tests found");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder summary = new StringBuilder();
|
||||||
|
if (testCount != 1) {
|
||||||
|
summary.append(testCount).append(" tests");
|
||||||
|
}
|
||||||
|
if (errorCount > 0) {
|
||||||
|
if (summary.length() > 0) {
|
||||||
|
summary.append(", ");
|
||||||
|
}
|
||||||
|
summary.append(errorCount).append(" errors");
|
||||||
|
}
|
||||||
|
out.println(summary);
|
||||||
|
if (errorCount > 0) {
|
||||||
|
throw new Exception(errorCount + " errors found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue