diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-18 03:31:51 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-18 03:31:51 +0000 |
commit | 4e9dbd1c4e2f894ca0a909c3997391fd1fc1cfbd (patch) | |
tree | 8d915caa859e726da2e092e44df7d6fba3563e27 | |
parent | 3c3859f5c69757e597772483b0ecc57e7ae74ee4 (diff) | |
parent | a1d8f9a160fdcfebeacf53995451a253713346d0 (diff) | |
download | jdiff-android14-d1-s4-release.tar.gz |
Snap for 9959853 from a1d8f9a160fdcfebeacf53995451a253713346d0 to udc-d1-releaseandroid-14.0.0_r9android-14.0.0_r8android-14.0.0_r7android-14.0.0_r6android-14.0.0_r5android-14.0.0_r4android-14.0.0_r3android-14.0.0_r12android-14.0.0_r11android-14.0.0_r10android14-d1-s7-releaseandroid14-d1-s6-releaseandroid14-d1-s5-releaseandroid14-d1-s4-releaseandroid14-d1-s3-releaseandroid14-d1-s2-releaseandroid14-d1-s1-releaseandroid14-d1-release
Change-Id: I5b78044e1ada1f2de7982ce908675b63b8da218c
-rw-r--r-- | Android.bp | 17 | ||||
-rwxr-xr-x | src/jdiff/CommentsHandler.java | 8 | ||||
-rwxr-xr-x | src/jdiff/JDiff.java | 196 | ||||
-rwxr-xr-x | src/jdiff/Options.java | 1034 | ||||
-rwxr-xr-x | src/jdiff/RootDocToXML.java | 7 |
5 files changed, 747 insertions, 515 deletions
@@ -46,11 +46,12 @@ license { ], } -// b/246303954: jdiff is excluded from build until it is migrated to Java 17, or -// replaced by another tool -// java_library_host { -// name: "jdiff", -// srcs: ["**/*.java"], -// -// use_tools_jar: true, -// } + java_library_host { + name: "jdiff", + srcs: ["**/*.java"], + static_libs: [ + "doclava-doclet-adapter", + ], + + use_tools_jar: true, + } diff --git a/src/jdiff/CommentsHandler.java b/src/jdiff/CommentsHandler.java index 9872cb7..3ad9b0a 100755 --- a/src/jdiff/CommentsHandler.java +++ b/src/jdiff/CommentsHandler.java @@ -67,10 +67,10 @@ class CommentsHandler extends DefaultHandler { System.exit(3); } // Check the given names against the names of the APIs - int idx1 = JDiff.oldFileName.lastIndexOf('.'); - int idx2 = JDiff.newFileName.lastIndexOf('.'); - String filename2 = JDiff.oldFileName.substring(0, idx1) + - "_to_" + JDiff.newFileName.substring(0, idx2); + int idx1 = Options.oldFileName.lastIndexOf('.'); + int idx2 = Options.newFileName.lastIndexOf('.'); + String filename2 = Options.oldFileName.substring(0, idx1) + + "_to_" + Options.newFileName.substring(0, idx2); if (filename2.compareTo(commentsName) != 0) { System.out.println("Warning: API identifier in the comments XML file (" + filename2 + ") differs from the name of the file."); } diff --git a/src/jdiff/JDiff.java b/src/jdiff/JDiff.java index c5cc25a..51d4772 100755 --- a/src/jdiff/JDiff.java +++ b/src/jdiff/JDiff.java @@ -1,12 +1,19 @@ package jdiff; -import com.sun.javadoc.*; - -import java.util.*; +import com.google.doclava.javadoc.RootDocImpl; +import com.sun.javadoc.DocErrorReporter; +import com.sun.javadoc.RootDoc; import java.io.*; -import java.lang.reflect.*; // Used for invoking Javadoc indirectly -import java.lang.Runtime; import java.lang.Process; +import java.lang.Runtime; +import java.lang.reflect.*; // Used for invoking Javadoc indirectly +import java.util.*; +import java.util.HashSet; +import javax.lang.model.SourceVersion; +import javax.tools.Diagnostic.Kind; +import jdk.javadoc.doclet.Doclet; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.doclet.Reporter; /** * Generates HTML describing the changes between two sets of Java source code. @@ -14,11 +21,44 @@ import java.lang.Process; * See the file LICENSE.txt for copyright details. * @author Matthew Doar, mdoar@pobox.com. */ -public class JDiff extends Doclet { +public class JDiff implements Doclet { + + public static Reporter reporter; + + @Override + public void init(Locale locale, Reporter reporter) { + JDiff.reporter = reporter; + } + + @Override + public String getName() { + return "JDiff"; + } + + @Override + public Set<? extends Option> getSupportedOptions() { + return Options.getSupportedOptions(); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.RELEASE_5; + } + + @Override + public boolean run(DocletEnvironment environment) { + if (!Options.writeXML && !Options.compareAPIs) { + JDiff.reporter.print(Kind.ERROR, + "First use the -apiname option to generate an XML file for one API."); + JDiff.reporter.print(Kind.ERROR, + "Then use the -apiname option again to generate another XML file for a different version of the API."); + JDiff.reporter.print(Kind.ERROR, + "Finally use the -oldapi option and -newapi option to generate a report about how the APIs differ."); + return false; + } + return start(new RootDocImpl(environment)); + } - public static LanguageVersion languageVersion(){ - return LanguageVersion.JAVA_1_5; - } /** * Doclet-mandated start method. Everything begins here. * @@ -43,19 +83,19 @@ public class JDiff extends Doclet { // Open the file where the XML representing the API will be stored. // and generate the XML for the API into it. - if (writeXML) { - RootDocToXML.writeXML(newRoot); + if (Options.writeXML) { + RootDocToXML.writeXML(newRoot); } - if (compareAPIs) { - String tempOldFileName = oldFileName; - if (oldDirectory != null) { - tempOldFileName = oldDirectory; - if (!tempOldFileName.endsWith(JDiff.DIR_SEP)) { - tempOldFileName += JDiff.DIR_SEP; - } - tempOldFileName += oldFileName; - } + if (Options.compareAPIs) { + String tempOldFileName = Options.oldFileName; + if (Options.oldDirectory != null) { + tempOldFileName = Options.oldDirectory; + if (!tempOldFileName.endsWith(JDiff.DIR_SEP)) { + tempOldFileName += JDiff.DIR_SEP; + } + tempOldFileName += Options.oldFileName; + } // Check the file for the old API exists File f = new File(tempOldFileName); @@ -65,13 +105,13 @@ public class JDiff extends Doclet { } // Check the file for the new API exists - String tempNewFileName = newFileName; - if (newDirectory != null) { - tempNewFileName = newDirectory; - if (!tempNewFileName.endsWith(JDiff.DIR_SEP)) { - tempNewFileName += JDiff.DIR_SEP; - } - tempNewFileName += newFileName; + String tempNewFileName = Options.newFileName; + if (Options.newDirectory != null) { + tempNewFileName = Options.newDirectory; + if (!tempNewFileName.endsWith(JDiff.DIR_SEP)) { + tempNewFileName += JDiff.DIR_SEP; + } + tempNewFileName += Options.newFileName; } f = new File(tempNewFileName); if (!f.exists()) { @@ -83,26 +123,26 @@ public class JDiff extends Doclet { // and create an API object for it. System.out.print("JDiff: reading the old API in from file '" + tempOldFileName + "'..."); // Read the file in, but do not add any text to the global comments - API oldAPI = XMLToAPI.readFile(tempOldFileName, false, oldFileName); - + API oldAPI = XMLToAPI.readFile(tempOldFileName, false, Options.oldFileName); + // Read the file where the XML representing the new API is stored // and create an API object for it. System.out.print("JDiff: reading the new API in from file '" + tempNewFileName + "'..."); // Read the file in, and do add any text to the global comments - API newAPI = XMLToAPI.readFile(tempNewFileName, true, newFileName); - + API newAPI = XMLToAPI.readFile(tempNewFileName, true, Options.newFileName); + // Compare the old and new APIs. APIComparator comp = new APIComparator(); - + comp.compareAPIs(oldAPI, newAPI); - + // Read the file where the XML for comments about the changes between - // the old API and new API is stored and create a Comments object for + // the old API and new API is stored and create a Comments object for // it. The Comments object may be null if no file exists. - int suffix = oldFileName.lastIndexOf('.'); - String commentsFileName = "user_comments_for_" + oldFileName.substring(0, suffix); - suffix = newFileName.lastIndexOf('.'); - commentsFileName += "_to_" + newFileName.substring(0, suffix) + ".xml"; + int suffix = Options.oldFileName.lastIndexOf('.'); + String commentsFileName = "user_comments_for_" + Options.oldFileName.substring(0, suffix); + suffix = Options.newFileName.lastIndexOf('.'); + commentsFileName += "_to_" + Options.newFileName.substring(0, suffix) + ".xml"; commentsFileName = commentsFileName.replace(' ', '_'); if (HTMLReportGenerator.commentsDir !=null) { commentsFileName = HTMLReportGenerator.commentsDir + DIR_SEP + commentsFileName; @@ -113,16 +153,16 @@ public class JDiff extends Doclet { Comments existingComments = Comments.readFile(commentsFileName); if (existingComments == null) System.out.println(" (the comments file will be created)"); - + // Generate an HTML report which summarises all the API differences. HTMLReportGenerator reporter = new HTMLReportGenerator(); reporter.generate(comp, existingComments); - + // Emit messages about which comments are now unused and // which are new. Comments newComments = reporter.getNewComments(); Comments.noteDifferences(existingComments, newComments); - + // Write the new comments out to the same file, with unused comments // now commented out. System.out.println("JDiff: writing the comments out to file '" + commentsFileName + "'..."); @@ -130,46 +170,16 @@ public class JDiff extends Doclet { } System.out.print("JDiff: finished (took " + (System.currentTimeMillis() - startTime)/1000 + "s"); - if (writeXML) - System.out.println(", not including scanning the source files)."); - else if (compareAPIs) + if (Options.writeXML) + System.out.println(", not including scanning the source files)."); + else if (Options.compareAPIs) System.out.println(")."); return true; } -// -// Option processing -// - /** - * This method is called by Javadoc to - * parse the options it does not recognize. It then calls - * {@link #validOptions} to validate them. - * - * @param option a String containing an option - * @return an int telling how many components that option has - */ - public static int optionLength(String option) { - return Options.optionLength(option); - } - - /** - * After parsing the available options using {@link #optionLength}, - * Javadoc invokes this method with an array of options-arrays. - * - * @param options an array of String arrays, one per option - * @param reporter a DocErrorReporter for generating error messages - * @return true if no errors were found, and all options are - * valid - */ - public static boolean validOptions(String[][] options, - DocErrorReporter reporter) { - return Options.validOptions(options, reporter); - } - - /** * This method is only called when running JDiff as a standalone - * application, and uses ANT to execute the build configuration in the + * application, and uses ANT to execute the build configuration in the * XML configuration file passed in. */ public static void main(String[] args) { @@ -190,7 +200,7 @@ public class JDiff extends Doclet { return; } - /** + /** * Display usage information for JDiff. */ public static void showUsage() { @@ -198,8 +208,8 @@ public class JDiff extends Doclet { System.out.println("If no build file is specified, the local build.xml file is used."); } - /** - * Invoke ANT by reflection. + /** + * Invoke ANT by reflection. * * @return The integer return code from running ANT. */ @@ -240,36 +250,6 @@ public class JDiff extends Doclet { return -1; } - /** - * The name of the file where the XML representing the old API is - * stored. - */ - static String oldFileName = "old_java.xml"; - - /** - * The name of the directory where the XML representing the old API is - * stored. - */ - static String oldDirectory = null; - - /** - * The name of the file where the XML representing the new API is - * stored. - */ - static String newFileName = "new_java.xml"; - - /** - * The name of the directory where the XML representing the new API is - * stored. - */ - static String newDirectory = null; - - /** If set, then generate the XML for an API and exit. */ - static boolean writeXML = false; - - /** If set, then read in two XML files and compare their APIs. */ - static boolean compareAPIs = false; - /** * The file separator for the local filesystem, forward or backward slash. */ diff --git a/src/jdiff/Options.java b/src/jdiff/Options.java index 748da7c..43614df 100755 --- a/src/jdiff/Options.java +++ b/src/jdiff/Options.java @@ -3,6 +3,8 @@ package jdiff; import java.io.*; import java.util.*; import com.sun.javadoc.*; +import javax.tools.Diagnostic; +import jdk.javadoc.doclet.Doclet.Option; /** * Class to handle options for JDiff. @@ -12,323 +14,552 @@ import com.sun.javadoc.*; */ public class Options { - /** Default constructor. */ - public Options() { - } + public static String authorid = ""; + public static String versionid = ""; + public static boolean classlist = false; + public static String title = ""; + public static boolean docletid = false; + public static String evident = ""; + public static List<String> skippkg = new ArrayList(); + public static List<String> skipclass = new ArrayList(); + public static int execdepth = 0; + + /** + * The name of the file where the XML representing the old API is + * stored. + */ + static String oldFileName = "old_java.xml"; + + /** + * The name of the directory where the XML representing the old API is + * stored. + */ + static String oldDirectory = null; + + /** + * The name of the file where the XML representing the new API is + * stored. + */ + static String newFileName = "new_java.xml"; /** - * Returns the "length" of a given option. If an option takes no - * arguments, its length is one. If it takes one argument, its - * length is two, and so on. This method is called by Javadoc to - * parse the options it does not recognize. It then calls - * {@link #validOptions} to validate them. - * <blockquote> - * <b>Note:</b><br> - * The options arrive as case-sensitive strings. For options that - * are not case-sensitive, use toLowerCase() on the option string - * before comparing it. - * </blockquote> - * - * @param option a String containing an option - * @return an int telling how many components that option has + * The name of the directory where the XML representing the new API is + * stored. */ - public static int optionLength(String option) { - String opt = option.toLowerCase(); - + static String newDirectory = null; + + /** If set, then generate the XML for an API and exit. */ + static boolean writeXML = false; + + /** If set, then read in two XML files and compare their APIs. */ + static boolean compareAPIs = false; + + public static Set<? extends Option> getSupportedOptions() { + Set<Option> options = new HashSet<>(); + // Standard options - if (opt.equals("-authorid")) return 2; - if (opt.equals("-versionid")) return 2; - if (opt.equals("-d")) return 2; - if (opt.equals("-classlist")) return 1; - if (opt.equals("-title")) return 2; - if (opt.equals("-docletid")) return 1; - if (opt.equals("-evident")) return 2; - if (opt.equals("-skippkg")) return 2; - if (opt.equals("-skipclass")) return 2; - if (opt.equals("-execdepth")) return 2; - if (opt.equals("-help")) return 1; - if (opt.equals("-version")) return 1; - if (opt.equals("-package")) return 1; - if (opt.equals("-protected")) return 1; - if (opt.equals("-public")) return 1; - if (opt.equals("-private")) return 1; - if (opt.equals("-sourcepath")) return 2; - + + options.add( + new Option() { + private final List<String> names = List.of("-authorid"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<author>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.authorid = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-versionid"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<version>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.versionid = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-d"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Destination directory for output HTML files"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<directory>"; } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.outputDir = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-classlist"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + Options.classlist = true; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-title"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<title>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.title = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-docletid"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + Options.docletid = true; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-evident"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<evident>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.evident = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-skippkg"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<package>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.skippkg.add(arguments.get(0)); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-skipclass"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<class>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.skipclass.add(arguments.get(0)); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-execdepth"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<depth>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.execdepth = Integer.parseInt(arguments.get(0)); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-version"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + System.out.println("JDiff version: " + JDiff.version); + System.exit(0); + return true; + } + } + ); + // Options to control JDiff - if (opt.equals("-apiname")) return 2; - if (opt.equals("-oldapi")) return 2; - if (opt.equals("-newapi")) return 2; + + options.add( + new Option() { + private final List<String> names = List.of("-apiname"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<Name of a version>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.skipclass.add(arguments.get(0)); + String filename = arguments.get(0); + RootDocToXML.apiIdentifier = filename; + filename = filename.replace(' ', '_'); + RootDocToXML.outputFileName = filename + ".xml"; + Options.writeXML = true; + Options.compareAPIs = false; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-oldapi"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<Name of a version>"; } + @Override public boolean process(String opt, List<String> arguments) { + String filename = arguments.get(0); + filename = filename.replace(' ', '_'); + Options.oldFileName = filename + ".xml"; + Options.writeXML = false; + Options.compareAPIs = true; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-newapi"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<Name of a version>"; } + @Override public boolean process(String opt, List<String> arguments) { + String filename = arguments.get(0); + filename = filename.replace(' ', '_'); + Options.newFileName = filename + ".xml"; + Options.writeXML = false; + Options.compareAPIs = true; + return true; + } + } + ); // Options to control the location of the XML files - if (opt.equals("-apidir")) return 2; - if (opt.equals("-oldapidir")) return 2; - if (opt.equals("-newapidir")) return 2; - if (opt.equals("-usercommentsdir")) return 2; + options.add( + new Option() { + private final List<String> names = List.of("-apidir"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<directory>"; } + @Override public boolean process(String opt, List<String> arguments) { + RootDocToXML.outputDirectory = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-oldapidir"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Location of the XML file for the old API"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<directory>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.oldDirectory = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-newapidir"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Location of the XML file for the new API"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<directory>"; } + @Override public boolean process(String opt, List<String> arguments) { + Options.newDirectory = arguments.get(0); + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-usercommentsdir"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Path to dir containing the user_comments* file(s)"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<directory>"; } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.commentsDir = arguments.get(0); + return true; + } + } + ); // Options for the exclusion level for classes and members - if (opt.equals("-excludeclass")) return 2; - if (opt.equals("-excludemember")) return 2; - if (opt.equals("-firstsentence")) return 1; - if (opt.equals("-docchanges")) return 1; - if (opt.equals("-packagesonly")) return 1; - if (opt.equals("-showallchanges")) return 1; + options.add( + new Option() { + private final List<String> names = List.of("-excludeclass"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Exclude classes which are not public, protected etc"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { + return "[public|protected|package|private]"; + } + @Override public boolean process(String opt, List<String> arguments) { + String level = arguments.get(0); + if (level.compareTo("public") != 0 && + level.compareTo("protected") != 0 && + level.compareTo("package") != 0 && + level.compareTo("private") != 0) { + JDiff.reporter.print(Diagnostic.Kind.ERROR, + "Level specified after -excludeclass option must be one of (public|protected|package|private)."); + return false; + } + RootDocToXML.classVisibilityLevel = level; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-excludemember"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Exclude members which are not public, protected etc"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { + return "[public|protected|package|private]"; + } + @Override public boolean process(String opt, List<String> arguments) { + String level = arguments.get(0); + if (level.compareTo("public") != 0 && + level.compareTo("protected") != 0 && + level.compareTo("package") != 0 && + level.compareTo("private") != 0) { + JDiff.reporter.print(Diagnostic.Kind.ERROR, + "Level specified after -excludemember option must be one of (public|protected|package|private)."); + return false; + } + RootDocToXML.memberVisibilityLevel = level; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-firstsentence"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { + return "Save only the first sentence of each comment block with the API."; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + RootDocToXML.saveAllDocs = false; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-docchanges"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { + return "Report changes in Javadoc comments between the APIs"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.reportDocChanges = true; + Diff.noDocDiffs = false; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-packagesonly"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + RootDocToXML.packagesOnly = true; + return true; + } + } + ); + + options.add( + new Option() { + private final List<String> names = List.of("-showallchanges"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + Diff.showAllChanges = true; + return true; + } + } + ); // Option to change the location for the existing Javadoc // documentation for the new API. Default is "../" - if (opt.equals("-javadocnew")) return 2; + + options.add( + new Option() { + private final List<String> names = List.of("-javadocnew"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { + return "<location of existing Javadoc files for the new API>"; + } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.newDocPrefix = arguments.get(0); + return true; + } + } + ); + // Option to change the location for the existing Javadoc // documentation for the old API. Default is null. - if (opt.equals("-javadocold")) return 2; - if (opt.equals("-baseuri")) return 2; + options.add( + new Option() { + private final List<String> names = List.of("-javadocold"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { + return "<location of existing Javadoc files for the old API>"; + } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.oldDocPrefix = arguments.get(0); + return true; + } + } + ); - // Option not to suggest comments at all - if (opt.equals("-nosuggest")) return 2; + options.add( + new Option() { + private final List<String> names = List.of("-baseuri"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Use \"base\" as the base location of the various DTDs and Schemas used by JDiff"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<base>"; } + @Override public boolean process(String opt, List<String> arguments) { + RootDocToXML.baseURI = arguments.get(0); + return true; + } + } + ); - // Option to enable checking that the comments end with a period. - if (opt.equals("-checkcomments")) return 1; - // Option to retain non-printing characters in comments. - if (opt.equals("-retainnonprinting")) return 1; - // Option for the name of the exclude tag - if (opt.equals("-excludetag")) return 2; - // Generate statistical output - if (opt.equals("-stats")) return 1; + // Option not to suggest comments at all - // Set the browser window title - if (opt.equals("-windowtitle")) return 2; - // Set the report title - if (opt.equals("-doctitle")) return 2; - - return 0; - }//optionLength() - - /** - * After parsing the available options using {@link #optionLength}, - * Javadoc invokes this method with an array of options-arrays, where - * the first item in any array is the option, and subsequent items in - * that array are its arguments. So, if -print is an option that takes - * no arguments, and -copies is an option that takes 1 argument, then - * <pre> - * -print -copies 3 - * </pre> - * produces an array of arrays that looks like: - * <pre> - * option[0][0] = -print - * option[1][0] = -copies - * option[1][1] = 3 - * </pre> - * (By convention, command line switches start with a "-", but - * they don't have to.) - * <p> - * <b>Note:</b><br> - * Javadoc passes <i>all</i>parameters to this method, not just - * those that Javadoc doesn't recognize. The only way to - * identify unexpected arguments is therefore to check for every - * Javadoc parameter as well as doclet parameters. - * - * @param options an array of String arrays, one per option - * @param reporter a DocErrorReporter for generating error messages - * @return true if no errors were found, and all options are - * valid - */ - public static boolean validOptions(String[][] options, - DocErrorReporter reporter) { - final DocErrorReporter errOut = reporter; - - // A nice object-oriented way of handling errors. An instance of this - // class puts out an error message and keeps track of whether or not - // an error was found. - class ErrorHandler { - boolean noErrorsFound = true; - void msg(String msg) { - noErrorsFound = false; - errOut.printError(msg); - } - } - - ErrorHandler err = new ErrorHandler(); - if (trace) - System.out.println("Command line arguments: "); - for (int i = 0; i < options.length; i++) { - for (int j = 0; j < options[i].length; j++) { - Options.cmdOptions += " " + options[i][j]; - if (trace) - System.out.print(" " + options[i][j]); - } - } - if (trace) - System.out.println(); - - for (int i = 0; i < options.length; i++) { - if (options[i][0].toLowerCase().equals("-apiname")) { - if (options[i].length < 2) { - err.msg("No version identifier specified after -apiname option."); - } else if (JDiff.compareAPIs) { - err.msg("Use the -apiname option, or the -oldapi and -newapi options, but not both."); - } else { - String filename = options[i][1]; - RootDocToXML.apiIdentifier = filename; - filename = filename.replace(' ', '_'); - RootDocToXML.outputFileName = filename + ".xml"; - JDiff.writeXML = true; - JDiff.compareAPIs = false; - } - continue; - } - if (options[i][0].toLowerCase().equals("-apidir")) { - if (options[i].length < 2) { - err.msg("No directory specified after -apidir option."); - } else { - RootDocToXML.outputDirectory = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-oldapi")) { - if (options[i].length < 2) { - err.msg("No version identifier specified after -oldapi option."); - } else if (JDiff.writeXML) { - err.msg("Use the -apiname or -oldapi option, but not both."); - } else { - String filename = options[i][1]; - filename = filename.replace(' ', '_'); - JDiff.oldFileName = filename + ".xml"; - JDiff.writeXML = false; - JDiff.compareAPIs = true; - } - continue; - } - if (options[i][0].toLowerCase().equals("-oldapidir")) { - if (options[i].length < 2) { - err.msg("No directory specified after -oldapidir option."); - } else { - JDiff.oldDirectory = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-newapi")) { - if (options[i].length < 2) { - err.msg("No version identifier specified after -newapi option."); - } else if (JDiff.writeXML) { - err.msg("Use the -apiname or -newapi option, but not both."); - } else { - String filename = options[i][1]; - filename = filename.replace(' ', '_'); - JDiff.newFileName = filename + ".xml"; - JDiff.writeXML = false; - JDiff.compareAPIs = true; - } - continue; - } - if (options[i][0].toLowerCase().equals("-newapidir")) { - if (options[i].length < 2) { - err.msg("No directory specified after -newapidir option."); - } else { - JDiff.newDirectory = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-usercommentsdir")) { - if (options[i].length < 2) { - err.msg("Android: No directory specified after -usercommentsdir option."); - } else { - HTMLReportGenerator.commentsDir = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-d")) { - if (options[i].length < 2) { - err.msg("No directory specified after -d option."); - } else { - HTMLReportGenerator.outputDir = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-javadocnew")) { - if (options[i].length < 2) { - err.msg("No location specified after -javadocnew option."); - } else { - HTMLReportGenerator.newDocPrefix = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-javadocold")) { - if (options[i].length < 2) { - err.msg("No location specified after -javadocold option."); - } else { - HTMLReportGenerator.oldDocPrefix = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-baseuri")) { - if (options[i].length < 2) { - err.msg("No base location specified after -baseURI option."); - } else { - RootDocToXML.baseURI = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-excludeclass")) { - if (options[i].length < 2) { - err.msg("No level (public|protected|package|private) specified after -excludeclass option."); - } else { - String level = options[i][1]; - if (level.compareTo("public") != 0 && - level.compareTo("protected") != 0 && - level.compareTo("package") != 0 && - level.compareTo("private") != 0) { - err.msg("Level specified after -excludeclass option must be one of (public|protected|package|private)."); - } else { - RootDocToXML.classVisibilityLevel = level; + options.add( + new Option() { + private final List<String> names = List.of("-nosuggest"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Do not add suggested comments to all, or the removed, added or changed sections"; } - } - continue; - } - if (options[i][0].toLowerCase().equals("-excludemember")) { - if (options[i].length < 2) { - err.msg("No level (public|protected|package|private) specified after -excludemember option."); - } else { - String level = options[i][1]; - if (level.compareTo("public") != 0 && - level.compareTo("protected") != 0 && - level.compareTo("package") != 0 && - level.compareTo("private") != 0) { - err.msg("Level specified after -excludemember option must be one of (public|protected|package|private)."); - } else { - RootDocToXML.memberVisibilityLevel = level; + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { + return "[all|remove|add|change]"; } - } - continue; - } - if (options[i][0].toLowerCase().equals("-firstsentence")) { - RootDocToXML.saveAllDocs = false; - continue; - } - if (options[i][0].toLowerCase().equals("-docchanges")) { - HTMLReportGenerator.reportDocChanges = true; - Diff.noDocDiffs = false; - continue; - } - if (options[i][0].toLowerCase().equals("-packagesonly")) { - RootDocToXML.packagesOnly = true; - continue; - } - if (options[i][0].toLowerCase().equals("-showallchanges")) { - Diff.showAllChanges = true; - continue; - } - if (options[i][0].toLowerCase().equals("-nosuggest")) { - if (options[i].length < 2) { - err.msg("No level (all|remove|add|change) specified after -nosuggest option."); - } else { - String level = options[i][1]; - if (level.compareTo("all") != 0 && - level.compareTo("remove") != 0 && - level.compareTo("add") != 0 && - level.compareTo("change") != 0) { - err.msg("Level specified after -nosuggest option must be one of (all|remove|add|change)."); - } else { + @Override public boolean process(String opt, List<String> arguments) { + String level = arguments.get(0); + if (level.compareTo("all") != 0 && + level.compareTo("remove") != 0 && + level.compareTo("add") != 0 && + level.compareTo("change") != 0) { + JDiff.reporter.print(Diagnostic.Kind.ERROR, + "Level specified after -nosuggest option must be one of (all|remove|add|change)."); + return false; + } if (level.compareTo("removal") == 0) HTMLReportGenerator.noCommentsOnRemovals = true; else if (level.compareTo("add") == 0) @@ -340,104 +571,123 @@ public class Options { HTMLReportGenerator.noCommentsOnAdditions = true; HTMLReportGenerator.noCommentsOnChanges = true; } + return true; } } - continue; - } - if (options[i][0].toLowerCase().equals("-checkcomments")) { - APIHandler.checkIsSentence = true; - continue; - } - if (options[i][0].toLowerCase().equals("-retainnonprinting")) { - RootDocToXML.stripNonPrintables = false; - continue; - } - if (options[i][0].toLowerCase().equals("-excludetag")) { - if (options[i].length < 2) { - err.msg("No exclude tag specified after -excludetag option."); - } else { - RootDocToXML.excludeTag = options[i][1]; - RootDocToXML.excludeTag = RootDocToXML.excludeTag.trim(); - RootDocToXML.doExclude = true; - } - continue; - } - if (options[i][0].toLowerCase().equals("-stats")) { - HTMLReportGenerator.doStats = true; - continue; - } - if (options[i][0].toLowerCase().equals("-doctitle")) { - if (options[i].length < 2) { - err.msg("No HTML text specified after -doctitle option."); - } else { - HTMLReportGenerator.docTitle = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-windowtitle")) { - if (options[i].length < 2) { - err.msg("No text specified after -windowtitle option."); - } else { - HTMLReportGenerator.windowTitle = options[i][1]; - } - continue; - } - if (options[i][0].toLowerCase().equals("-version")) { - System.out.println("JDiff version: " + JDiff.version); - System.exit(0); - } - if (options[i][0].toLowerCase().equals("-help")) { - usage(); - System.exit(0); - } - }//for - if (!JDiff.writeXML && !JDiff.compareAPIs) { - err.msg("First use the -apiname option to generate an XML file for one API."); - err.msg("Then use the -apiname option again to generate another XML file for a different version of the API."); - err.msg("Finally use the -oldapi option and -newapi option to generate a report about how the APIs differ."); - } - return err.noErrorsFound; - }// validOptions() - - /** Display the arguments for JDiff. */ - public static void usage() { - System.err.println("JDiff version: " + JDiff.version); - System.err.println(""); - System.err.println("Valid JDiff arguments:"); - System.err.println(""); - System.err.println(" -apiname <Name of a version>"); - System.err.println(" -oldapi <Name of a version>"); - System.err.println(" -newapi <Name of a version>"); - - System.err.println(" Optional Arguments"); - System.err.println(); - System.err.println(" -d <directory> Destination directory for output HTML files"); - System.err.println(" -oldapidir <directory> Location of the XML file for the old API"); - System.err.println(" -newapidir <directory> Location of the XML file for the new API"); - System.err.println(" -sourcepath <location of Java source files>"); - System.err.println(" -javadocnew <location of existing Javadoc files for the new API>"); - System.err.println(" -javadocold <location of existing Javadoc files for the old API>"); - System.err.println(" -usercommentsdir <directory> Path to dir containing the user_comments* file(s)"); - - System.err.println(" -baseURI <base> Use \"base\" as the base location of the various DTDs and Schemas used by JDiff"); - System.err.println(" -excludeclass [public|protected|package|private] Exclude classes which are not public, protected etc"); - System.err.println(" -excludemember [public|protected|package|private] Exclude members which are not public, protected etc"); - - System.err.println(" -firstsentence Save only the first sentence of each comment block with the API."); - System.err.println(" -docchanges Report changes in Javadoc comments between the APIs"); - System.err.println(" -nosuggest [all|remove|add|change] Do not add suggested comments to all, or the removed, added or chabged sections"); - System.err.println(" -checkcomments Check that comments are sentences"); - System.err.println(" -stripnonprinting Remove non-printable characters from comments."); - System.err.println(" -excludetag <tag> Define the Javadoc tag which implies exclusion"); - System.err.println(" -stats Generate statistical output"); - System.err.println(" -help (generates this output)"); - System.err.println(""); - System.err.println("For more help, see jdiff.html"); - } - - /** All the options passed on the command line. Logged to XML. */ - public static String cmdOptions = ""; + ); + + // Option to enable checking that the comments end with a period. + + options.add( + new Option() { + private final List<String> names = List.of("-checkcomments"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { + return "Check that comments are sentences"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + APIHandler.checkIsSentence = true; + return true; + } + } + ); - /** Set to enable increased logging verbosity for debugging. */ - private static boolean trace = false; + // Option to retain non-printing characters in comments. + + options.add( + new Option() { + private final List<String> names = List.of("-retainnonprinting"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { + return "Keep non-printable characters from comments."; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + RootDocToXML.stripNonPrintables = false; + return true; + } + } + ); + + // Option for the name of the exclude tag + + options.add( + new Option() { + private final List<String> names = List.of("-excludetag"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { + return "Define the Javadoc tag which implies exclusion"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<tag>"; } + @Override public boolean process(String opt, List<String> arguments) { + RootDocToXML.excludeTag = arguments.get(0); + RootDocToXML.excludeTag = RootDocToXML.excludeTag.trim(); + RootDocToXML.doExclude = true; + return true; + } + } + ); + + // Generate statistical output + + options.add( + new Option() { + private final List<String> names = List.of("-stats"); + @Override public int getArgumentCount() { return 0; } + @Override public String getDescription() { + return "Generate statistical output"; + } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return ""; } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.doStats = true; + return true; + } + } + ); + + // Set the browser window title + + options.add( + new Option() { + private final List<String> names = List.of("-windowtitle"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<title>"; } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.windowTitle = arguments.get(0); + return true; + } + } + ); + + // Set the report title + + options.add( + new Option() { + private final List<String> names = List.of("-doctitle"); + @Override public int getArgumentCount() { return 1; } + @Override public String getDescription() { return ""; } + @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } + @Override public List<String> getNames() { return names; } + @Override public String getParameters() { return "<title>"; } + @Override public boolean process(String opt, List<String> arguments) { + HTMLReportGenerator.docTitle = arguments.get(0); + return true; + } + } + ); + + return options; + } } diff --git a/src/jdiff/RootDocToXML.java b/src/jdiff/RootDocToXML.java index cb2f0e2..587d3ab 100755 --- a/src/jdiff/RootDocToXML.java +++ b/src/jdiff/RootDocToXML.java @@ -214,9 +214,10 @@ public class RootDocToXML { * out as XML comments. */ public void logOptions() { - outputFile.print("<!-- "); - outputFile.print(" Command line arguments = " + Options.cmdOptions); - outputFile.println(" -->"); + // TODO: Get options from javadoc if possible. + // outputFile.print("<!-- "); + // outputFile.print(" Command line arguments = " + Options.cmdOptions); + // outputFile.println(" -->"); } /** |