diff options
author | Xin Li <delphij@google.com> | 2019-09-04 13:33:43 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2019-09-04 13:33:43 -0700 |
commit | 3b87006375dc4ce671c11ae4488d19afa2cd3068 (patch) | |
tree | 7d97d74026f809bc4ff31ec35b4450ff35dc27d6 | |
parent | af4aca7863a81c8d82495caa47d77c4fe5dc8fa1 (diff) | |
parent | bf96a2b37fd13e3d90297cc2b442653bdb5985fb (diff) | |
download | platform_external_doclava-3b87006375dc4ce671c11ae4488d19afa2cd3068.tar.gz platform_external_doclava-3b87006375dc4ce671c11ae4488d19afa2cd3068.tar.bz2 platform_external_doclava-3b87006375dc4ce671c11ae4488d19afa2cd3068.zip |
DO NOT MERGE - Merge Android 10 into master
Bug: 139893257
Change-Id: Ide45d9cbe2c437c140f6a756c8b9b04f13ec7a07
-rw-r--r-- | OWNERS | 3 | ||||
-rw-r--r-- | build.gradle | 7 | ||||
-rw-r--r-- | res/assets/templates-sdk/assets/css/default.css | 17 | ||||
-rw-r--r-- | res/assets/templates-sdk/class.cs | 25 | ||||
-rw-r--r-- | res/assets/templates-sdk/macros_override.cs | 12 | ||||
-rw-r--r-- | res/assets/templates-sdk/page_info.cs | 7 | ||||
-rw-r--r-- | res/assets/templates/macros.cs | 15 | ||||
-rw-r--r-- | src/com/google/doclava/AndroidAuxSource.java | 40 | ||||
-rw-r--r-- | src/com/google/doclava/ClassInfo.java | 1 | ||||
-rw-r--r-- | src/com/google/doclava/Comment.java | 40 | ||||
-rw-r--r-- | src/com/google/doclava/DocInfo.java | 15 | ||||
-rw-r--r-- | src/com/google/doclava/Doclava.java | 69 | ||||
-rw-r--r-- | src/com/google/doclava/NavTree.java | 1 | ||||
-rw-r--r-- | src/com/google/doclava/Stubs.java | 49 |
14 files changed, 206 insertions, 95 deletions
@@ -2,3 +2,6 @@ # Please update this list if you find better candidates. jsharkey@android.com smain@google.com # for files under res/ +ddougherty@google.com +tiem@google.com +tnorbye@google.com diff --git a/build.gradle b/build.gradle index cf0c9d4..3096e0e 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,13 @@ apply plugin: 'maven' group = 'com.android' version = '1.0.6' +def currentJvmVersion = org.gradle.api.JavaVersion.current() +if (currentJvmVersion.getMajorVersion() != "8") { + throw new Exception("Unsupported java version '" + currentJvmVersion.toString() + "'. Please install java 8.\n" + +"\n" + +"If you have already installed java 8, you can instruct Gradle to use it by setting the environment variable JAVA_HOME equal to its file path.") +} + /* * With the build server you are given two env variables: * 1. The OUT_DIR is a temporary directory you can use to put things during the build. diff --git a/res/assets/templates-sdk/assets/css/default.css b/res/assets/templates-sdk/assets/css/default.css index 65d7fde..2abfe73 100644 --- a/res/assets/templates-sdk/assets/css/default.css +++ b/res/assets/templates-sdk/assets/css/default.css @@ -2552,25 +2552,10 @@ div.design-announce p { } .expandable { - height:34px; + height:auto; padding-left:20px; position:relative; } -.expandable:before { - content: ''; - background-image: url(../images/styles/disclosure_down.png); - background-repeat:no-repeat; - background-position: -12px -9px; - width: 20px; - height: 20px; - display: inline-block; - position: absolute; - top: 0; - left: 0; } -} -.expandable.expanded:before { - background-image: url(../images/styles/disclosure_up.png); -} /* notice box for cross links between Design/Develop docs */ a.notice-developers-video, diff --git a/res/assets/templates-sdk/class.cs b/res/assets/templates-sdk/class.cs index 9b5a370..5fb2a9d 100644 --- a/res/assets/templates-sdk/class.cs +++ b/res/assets/templates-sdk/class.cs @@ -685,31 +685,6 @@ if:subcount(class.subclasses.direct) && !class.subclasses.hidden ?> </div><!-- end jd-content --> -<?cs if:devsite ?> - -<div class="data-reference-resources-wrapper"> - <?cs if:subcount(class.package) ?> - <ul data-reference-resources> - <?cs call:list("Annotations", class.package.annotations) ?> - <?cs call:list("Interfaces", class.package.interfaces) ?> - <?cs call:list("Classes", class.package.classes) ?> - <?cs call:list("Enums", class.package.enums) ?> - <?cs call:list("Exceptions", class.package.exceptions) ?> - <?cs call:list("Errors", class.package.errors) ?> - </ul> - <?cs elif:subcount(package) ?> - <ul data-reference-resources> - <?cs call:class_link_list("Annotations", package.annotations) ?> - <?cs call:class_link_list("Interfaces", package.interfaces) ?> - <?cs call:class_link_list("Classes", package.classes) ?> - <?cs call:class_link_list("Enums", package.enums) ?> - <?cs call:class_link_list("Exceptions", package.exceptions) ?> - <?cs call:class_link_list("Errors", package.errors) ?> - </ul> - <?cs /if ?> -</div> -<?cs /if ?> - <?cs if:!devsite ?> <?cs include:"footer.cs" ?> <?cs include:"trailer.cs" ?> diff --git a/res/assets/templates-sdk/macros_override.cs b/res/assets/templates-sdk/macros_override.cs index 8ef81cf..5c0c482 100644 --- a/res/assets/templates-sdk/macros_override.cs +++ b/res/assets/templates-sdk/macros_override.cs @@ -68,6 +68,7 @@ def:aux_tag_list(tags) ?><?cs elif:tag.kind == "@permission" ?><?cs call:dump_permission(tag) ?><?cs elif:tag.kind == "@service" ?><?cs call:dump_service(tag) ?><?cs elif:tag.kind == "@feature" ?><?cs call:dump_feature(tag) ?><?cs + elif:tag.kind == "@column" ?><?cs call:dump_column(tag) ?><?cs /if ?><?cs /each ?></p><?cs /def ?><?cs @@ -143,3 +144,14 @@ def:dump_feature(tag) ?>Requires the <?cs call:tag_list(tag.values[0].commentTags) ?> feature which can be detected using <?cs call:tag_list(tag.values[1].commentTags) ?>.<?cs /def ?> + +# Print output for @column tags ?><?cs +def:dump_column(tag) ?>This constant represents a column name that can be used with a <?cs + call:tag_list(tag.values[0].commentTags) ?> through a <?cs + call:tag_list(tag.values[1].commentTags) ?> or <?cs + call:tag_list(tag.values[2].commentTags) ?> object. The values stored in this column are <?cs + call:tag_list(tag.values[3].commentTags) ?><?cs + if tag.readOnly ?>, and are read-only and cannot be mutated<?cs + else ?><?cs + /if ?>.<?cs +/def ?> diff --git a/res/assets/templates-sdk/page_info.cs b/res/assets/templates-sdk/page_info.cs index 8585ee1..5fe6f7b 100644 --- a/res/assets/templates-sdk/page_info.cs +++ b/res/assets/templates-sdk/page_info.cs @@ -27,13 +27,6 @@ elif:subcount(class) <?cs if:class.artifact ?> <br><?cs call:artifact_tags(class) ?> <?cs /if ?> - <?cs if:class.deprecatedsince ?><?cs - if:class.artifact ?><br>Deprecated since version <?cs var:class.deprecatedsince ?><?cs - else ?><br>Deprecated since - <a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html#ApiLevels">API level - <?cs var:class.deprecatedsince ?></a><?cs - /if ?> - <?cs /if ?> <?cs call:federated_refs(class) ?> </div> diff --git a/res/assets/templates/macros.cs b/res/assets/templates/macros.cs index 13a884f..db502bb 100644 --- a/res/assets/templates/macros.cs +++ b/res/assets/templates/macros.cs @@ -267,17 +267,24 @@ def:see_also_tags(also) ?><?cs def:since_tags(obj) ?><?cs if:reference.apilevels && obj.since ?><?cs if:string.slice(obj.since,0,1) > 0 ?> - added in <?cs + Added in <?cs if:string.find(obj.since,'.') > -1 ?><a href="<?cs var:toroot ?>topic/libraries/support-library/revisions.html">version<?cs else ?><a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html#ApiLevels">API level<?cs /if ?> <?cs var:obj.since ?></a><?cs - else ?> - <b><a href="<?cs var:toroot ?>preview/">Android <?cs var:obj.since ?> Developer Preview</a></b><?cs + else ?><a data-version-added="<?cs var:obj.since ?>" href="<?cs var:toroot ?>preview/"><b>Added in Android <?cs + var:obj.since ?></b></a><?cs /if?><?cs -/if ?><?cs +/if ?> + <?cs if:obj.deprecatedsince ?><?cs + if:class.artifact ?><br>Deprecated in version <?cs var:obj.deprecatedsince ?><?cs + else ?><br>Deprecated in + <a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html#ApiLevels">API level + <?cs var:obj.deprecatedsince ?></a><?cs + /if ?> + <?cs /if ?><?cs /def ?><?cs # print the artifact ?><?cs diff --git a/src/com/google/doclava/AndroidAuxSource.java b/src/com/google/doclava/AndroidAuxSource.java index 1c97b18..ca1fbd0 100644 --- a/src/com/google/doclava/AndroidAuxSource.java +++ b/src/com/google/doclava/AndroidAuxSource.java @@ -219,6 +219,46 @@ public class AndroidAuxSource implements AuxSource { valueTags.toArray(TagInfo.getArray(valueTags.size())))); } + // Document provider columns + if ((type == TYPE_FIELD) && annotation.type().qualifiedNameMatches("android", "Column")) { + String value = null; + boolean readOnly = false; + for (AnnotationValueInfo val : annotation.elementValues()) { + switch (val.element().name()) { + case "value": + value = String.valueOf(val.value()); + break; + case "readOnly": + readOnly = Boolean.parseBoolean(String.valueOf(val.value())); + break; + } + } + + ArrayList<TagInfo> valueTags = new ArrayList<>(); + valueTags.add(new ParsedTagInfo("", "", + "{@link android.content.ContentProvider}", null, SourcePositionInfo.UNKNOWN)); + valueTags.add(new ParsedTagInfo("", "", + "{@link android.content.ContentValues}", null, SourcePositionInfo.UNKNOWN)); + valueTags.add(new ParsedTagInfo("", "", + "{@link android.database.Cursor}", null, SourcePositionInfo.UNKNOWN)); + + ClassInfo cursorClass = annotation.type().findClass("android.database.Cursor"); + for (FieldInfo field : cursorClass.fields()) { + if (field.isHiddenOrRemoved()) continue; + if (String.valueOf(field.constantValue()).equals(value)) { + valueTags.add(new ParsedTagInfo("", "", + "{@link android.database.Cursor#" + field.name() + "}", + null, SourcePositionInfo.UNKNOWN)); + } + } + if (valueTags.size() < 4) continue; + + Map<String, String> args = new HashMap<>(); + if (readOnly) args.put("readOnly", "true"); + tags.add(new AuxTagInfo("@column", "@column", SourcePositionInfo.UNKNOWN, args, + valueTags.toArray(TagInfo.getArray(valueTags.size())))); + } + // The remaining annotations below always appear on return docs, and // should not be included in the method body if (type == TYPE_METHOD) continue; diff --git a/src/com/google/doclava/ClassInfo.java b/src/com/google/doclava/ClassInfo.java index dbe7783..2a5db75 100644 --- a/src/com/google/doclava/ClassInfo.java +++ b/src/com/google/doclava/ClassInfo.java @@ -39,7 +39,6 @@ import java.util.TreeMap; import java.util.function.Predicate; public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Scoped, Resolvable { - /** * Contains a ClassInfo and a TypeInfo. * <p> diff --git a/src/com/google/doclava/Comment.java b/src/com/google/doclava/Comment.java index ea09788..29154c2 100644 --- a/src/com/google/doclava/Comment.java +++ b/src/com/google/doclava/Comment.java @@ -30,9 +30,14 @@ public class Comment { private static final Set<String> KNOWN_TAGS = new HashSet<String>(Arrays.asList(new String[] { "@apiNote", "@author", - "@since", "@version", + //not used by metalava for Android docs (see @apiSince) + "@since", + //value is an Android API level (set automatically by metalava) + "@apiSince", "@deprecated", + //value is an Android API level (set automatically by metalava) + "@deprecatedSince", "@undeprecate", "@docRoot", "@sdkCurrent", @@ -45,8 +50,6 @@ public class Comment { "@implNote", "@implSpec", "@usesMathJax", - "@deprecatedSince", - "@apiSince", })); public Comment(String text, ContainerInfo base, SourcePositionInfo sp) { @@ -287,8 +290,6 @@ public class Comment { for (char c = text.charAt(index); index < endOfBlock && !isWhitespaceChar(c); c = text.charAt(index++)) {} - - // if (index == startOfBlock+1) { return; } @@ -330,6 +331,10 @@ public class Comment { mInlineTagsList.add(new TextTagInfo("Text", "Text", text, pos)); } else if (name.equals("@param")) { mParamTagsList.add(new ParamTagInfo("@param", "@param", text, mBase, pos)); + } else if (name.equals("@apiSince")) { + setApiSince(text); + } else if (name.equals("@deprecatedSince")) { + setDeprecatedSince(text); } else if (name.equals("@see")) { mSeeTagsList.add(new SeeTagInfo("@see", "@see", text, mBase, pos)); } else if (name.equals("@link")) { @@ -534,6 +539,29 @@ public class Comment { return mRemoved; } + public void setDeprecatedSince(String since) { + if (since != null) { + since = since.trim(); + } + mDeprecatedSince = since; + } + + public String getDeprecatedSince() { + return mDeprecatedSince; + } + + public void setApiSince(String since) { + if (since != null) { + since = since.trim(); + } + mApiSince = since; + } + + public String getApiSince() { + //return the value of @apiSince, an API level in Android + return mApiSince; + } + public boolean isDocOnly() { if (mDocOnly == null) { mDocOnly = (mText != null) && (mText.indexOf("@doconly") >= 0); @@ -609,6 +637,8 @@ public class Comment { Boolean mRemoved = null; Boolean mDocOnly = null; Boolean mDeprecated = null; + String mDeprecatedSince; + String mApiSince; String mText; ContainerInfo mBase; SourcePositionInfo mPosition; diff --git a/src/com/google/doclava/DocInfo.java b/src/com/google/doclava/DocInfo.java index 650ce0d..fae225f 100644 --- a/src/com/google/doclava/DocInfo.java +++ b/src/com/google/doclava/DocInfo.java @@ -101,6 +101,9 @@ public abstract class DocInfo { } public String getSince() { + if (Doclava.METALAVA_API_SINCE) { + mSince = comment().getApiSince(); + } return mSince; } @@ -129,11 +132,19 @@ public abstract class DocInfo { } public String getDeprecatedSince() { - return mDeprecatedSince; + if (Doclava.METALAVA_API_SINCE) { + return comment().getDeprecatedSince(); + } else { + return mDeprecatedSince; + } } public boolean isDeprecated() { - return mDeprecatedSince != null ? true : false; + if (Doclava.METALAVA_API_SINCE) { + return comment().isDeprecated(); + } else { + return mDeprecatedSince != null ? true : false; + } } public final void addFederatedReference(FederatedSite source) { diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java index 53afe55..f24718a 100644 --- a/src/com/google/doclava/Doclava.java +++ b/src/com/google/doclava/Doclava.java @@ -82,6 +82,7 @@ public class Doclava { public static boolean NAVTREE_ONLY = false; /* Generate reference navtree.js with all inherited members */ public static boolean AT_LINKS_NAVTREE = false; + public static boolean METALAVA_API_SINCE = false; public static String outputPathBase = "/"; public static ArrayList<String> inputPathHtmlDirs = new ArrayList<String>(); public static ArrayList<String> inputPathHtmlDir2 = new ArrayList<String>(); @@ -121,6 +122,7 @@ public class Doclava { public static boolean referenceOnly = false; public static boolean staticOnly = false; public static boolean yamlV2 = false; /* whether to build the new version of the yaml file */ + public static boolean devsite = false; /* whether to build docs for devsite */ public static AuxSource auxSource = new EmptyAuxSource(); public static Linter linter = new EmptyLinter(); public static boolean android = false; @@ -193,6 +195,7 @@ public class Doclava { HashSet<String> stubPackages = null; HashSet<String> stubImportPackages = null; boolean stubSourceOnly = false; + boolean keepStubComments = false; ArrayList<String> knownTagsFiles = new ArrayList<String>(); root = r; @@ -301,6 +304,8 @@ public class Doclava { } } else if (a[0].equals("-stubsourceonly")) { stubSourceOnly = true; + } else if (a[0].equals("-keepstubcomments")) { + keepStubComments = true; } else if (a[0].equals("-sdkvalues")) { sdkValuePath = a[1]; } else if (a[0].equals("-api")) { @@ -327,6 +332,8 @@ public class Doclava { includeDefaultAssets = false; } else if (a[0].equals("-parsecomments")) { parseComments = true; + } else if (a[0].equals("-metalavaApiSince")) { + METALAVA_API_SINCE = true; } else if (a[0].equals("-since")) { sinceTagger.addVersion(a[1], a[2]); } else if (a[0].equals("-artifact")) { @@ -377,6 +384,7 @@ public class Doclava { } else if (a[0].equals("-yamlV2")) { yamlV2 = true; } else if (a[0].equals("-devsite")) { + devsite = true; // Don't copy any assets to devsite output includeAssets = false; USE_DEVSITE_LOCALE_OUTPUT_PATHS = true; @@ -386,7 +394,8 @@ public class Doclava { System.out.println(" ... Generating static html only for devsite"); } if (yamlNavFile == null) { - yamlNavFile = "_book.yaml"; + // Use _toc.yaml as default to avoid clobbering possible manual _book.yaml files + yamlNavFile = "_toc.yaml"; } } else if (a[0].equals("-android")) { auxSource = new AndroidAuxSource(); @@ -424,9 +433,8 @@ public class Doclava { } // If no custom template path is provided, and this is a devsite build, // then use the bundled templates-sdk/ files by default - if (templates.isEmpty() && USE_DEVSITE_LOCALE_OUTPUT_PATHS) { + if (templates.isEmpty() && devsite) { resourceLoaders.add(new ClassResourceLoader(Doclava.class, "/assets/templates-sdk")); - System.out.println("\n######### OK, Using templates-sdk ############\n"); } templates = ClearPage.getBundledTemplateDirs(); @@ -447,7 +455,11 @@ public class Doclava { if (NAVTREE_ONLY) { if (AT_LINKS_NAVTREE) { AtLinksNavTree.writeAtLinksNavTree(javadocDir); + } else if (yamlV2) { + // Generate DAC-formatted left-nav for devsite + NavTree.writeYamlTree2(javadocDir, yamlNavFile); } else { + // This shouldn't happen; this is the legacy DAC left nav file NavTree.writeNavTree(javadocDir, ""); } return true; @@ -518,18 +530,6 @@ public class Doclava { } else if(gcmRef){ refPrefix = "gcm-"; } - NavTree.writeNavTree(javadocDir, refPrefix); - - // Write yaml tree. - if (yamlNavFile != null){ - NavTree.writeYamlTree(javadocDir, yamlNavFile); - if (yamlV2) { - // Generate both for good measure, to make transitions easier, but change the filename - // for the new one so there's yet another explicit opt-in required by fixing the name. - yamlNavFile = "_NEW" + yamlNavFile; - NavTree.writeYamlTree2(javadocDir, yamlNavFile); - } - } // Packages Pages writePackages(refPrefix + "packages" + htmlExtension); @@ -540,6 +540,20 @@ public class Doclava { writeHierarchy(); // writeKeywords(); + // Write yaml tree. + if (yamlNavFile != null) { + if (yamlV2) { + // Generate DAC-formatted left-nav for devsite + NavTree.writeYamlTree2(javadocDir, yamlNavFile); + } else { + // Generate legacy devsite left-nav (shows sub-classes nested under parent class) + NavTree.writeYamlTree(javadocDir, yamlNavFile); + } + } else { + // This shouldn't happen; this is the legacy DAC left nav file + NavTree.writeNavTree(javadocDir, refPrefix); + } + // Lists for JavaScript writeLists(); if (keepListFile != null) { @@ -556,7 +570,7 @@ public class Doclava { if (!sTaglist.isEmpty()) { PageMetadata.WriteListByLang(sTaglist); // For devsite (ds) reference only, write samples_metadata to out dir - if ((USE_DEVSITE_LOCALE_OUTPUT_PATHS) && (!DEVSITE_STATIC_ONLY)) { + if ((devsite) && (!DEVSITE_STATIC_ONLY)) { PageMetadata.WriteSamplesListByLang(sTaglist); } } @@ -568,7 +582,7 @@ public class Doclava { || privateApiFile != null || privateDexApiFile != null || apiMappingFile != null) { Stubs.writeStubsAndApi(stubsDir, apiFile, dexApiFile, proguardFile, removedApiFile, removedDexApiFile, exactApiFile, privateApiFile, privateDexApiFile, apiMappingFile, - stubPackages, stubImportPackages, stubSourceOnly); + stubPackages, stubImportPackages, stubSourceOnly, keepStubComments); } Errors.printErrors(); @@ -853,6 +867,9 @@ public class Doclava { if (option.equals("-stubsourceonly")) { return 1; } + if (option.equals("-keepstubcomments")) { + return 1; + } if (option.equals("-sdkvalues")) { return 2; } @@ -889,6 +906,9 @@ public class Doclava { if (option.equals("-parsecomments")) { return 1; } + if (option.equals("-metalavaApiSince")) { + return 1; + } if (option.equals("-since")) { return 3; } @@ -1040,7 +1060,11 @@ public class Doclava { data.setValue("reference.gcm", "true"); } data.setValue("reference", "1"); - data.setValue("reference.apilevels", sinceTagger.hasVersions() ? "1" : "0"); + if (METALAVA_API_SINCE) { + data.setValue("reference.apilevels", (pkg.getSince() != null) ? "1" : "0"); + } else { + data.setValue("reference.apilevels", sinceTagger.hasVersions() ? "1" : "0"); + } data.setValue("reference.artifacts", artifactTagger.hasArtifacts() ? "1" : "0"); data.setValue("docs.packages." + i + ".name", s); data.setValue("docs.packages." + i + ".link", pkg.htmlPage()); @@ -1201,7 +1225,7 @@ public class Doclava { // Write the lists for JD documents (if there are HTML directories to process) // Skip this for devsite builds - if ((inputPathHtmlDirs.size() > 0) && (!USE_DEVSITE_LOCALE_OUTPUT_PATHS)) { + if ((inputPathHtmlDirs.size() > 0) && (!devsite)) { Data jddata = makeHDF(); Iterator counter = new Iterator(); for (String htmlDir : inputPathHtmlDirs) { @@ -1563,8 +1587,11 @@ public class Doclava { setPageTitle(data, "Class Index"); ClearPage.write(data, "classes.cs", packageDir + "classes" + htmlExtension); - // Index page redirects to the classes.html page, so use the same directory - writeIndex(packageDir); + if (!devsite) { + // Index page redirects to the classes.html page, so use the same directory + // This page is not needed for devsite builds, which should instead use _redirects.yaml + writeIndex(packageDir); + } } // we use the word keywords because "index" means something else in html land diff --git a/src/com/google/doclava/NavTree.java b/src/com/google/doclava/NavTree.java index b4861c8..3375df5 100644 --- a/src/com/google/doclava/NavTree.java +++ b/src/com/google/doclava/NavTree.java @@ -26,6 +26,7 @@ import java.util.TreeMap; public class NavTree { + /* @deprecated This method was used for an older version of DAC, circa 2012, retired May 2018 */ public static void writeNavTree(String dir, String refPrefix) { List<Node> children = new ArrayList<Node>(); for (PackageInfo pkg : Doclava.choosePackages()) { diff --git a/src/com/google/doclava/Stubs.java b/src/com/google/doclava/Stubs.java index 0ef3749..930d52c 100644 --- a/src/com/google/doclava/Stubs.java +++ b/src/com/google/doclava/Stubs.java @@ -49,7 +49,8 @@ public class Stubs { public static void writeStubsAndApi(String stubsDir, String apiFile, String dexApiFile, String keepListFile, String removedApiFile, String removedDexApiFile, String exactApiFile, String privateApiFile, String privateDexApiFile, String apiMappingFile, - HashSet<String> stubPackages, HashSet<String> stubImportPackages, boolean stubSourceOnly) { + HashSet<String> stubPackages, HashSet<String> stubImportPackages, boolean stubSourceOnly, + boolean keepStubComments) { // figure out which classes we need final HashSet<ClassInfo> notStrippable = new HashSet<ClassInfo>(); Collection<ClassInfo> all = Converter.allClasses(); @@ -259,7 +260,7 @@ public class Stubs { if (shouldWriteStub(cl.containingPackage().name(), stubPackages, stubPackageWildcards)) { // write out the stubs if (stubsDir != null) { - writeClassFile(stubsDir, notStrippable, cl); + writeClassFile(stubsDir, notStrippable, cl, keepStubComments); } // build class list for api file or keep list file if (apiWriter != null || dexApiWriter != null || keepListWriter != null) { @@ -588,7 +589,7 @@ public class Stubs { return dir + cl.name() + ".java"; } - static void writeClassFile(String stubsDir, HashSet<ClassInfo> notStrippable, ClassInfo cl) { + static void writeClassFile(String stubsDir, HashSet<ClassInfo> notStrippable, ClassInfo cl, boolean keepStubComments) { // inner classes are written by their containing class if (cl.containingClass() != null) { return; @@ -608,7 +609,7 @@ public class Stubs { PrintStream stream = null; try { stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file))); - writeClassFile(stream, notStrippable, cl); + writeClassFile(stream, notStrippable, cl, keepStubComments); } catch (FileNotFoundException e) { System.err.println("error writing file: " + filename); } finally { @@ -618,7 +619,7 @@ public class Stubs { } } - static void writeClassFile(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) { + static void writeClassFile(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl, boolean keepStubComments) { PackageInfo pkg = cl.containingPackage(); if (cl.containingClass() == null) { stream.print(parseLicenseHeader(cl.position())); @@ -626,7 +627,7 @@ public class Stubs { if (pkg != null) { stream.println("package " + pkg.name() + ";"); } - writeClass(stream, notStrippable, cl); + writeClass(stream, notStrippable, cl, keepStubComments); } private static String parseLicenseHeader(/* @Nonnull */ SourcePositionInfo positionInfo) { @@ -677,7 +678,11 @@ public class Stubs { return builder.toString(); } - static void writeClass(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) { + static void writeClass(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl, boolean keepStubComments) { + if (keepStubComments) { + writeComment(stream, cl); + } + writeAnnotations(stream, cl.annotations(), cl.isDeprecated()); stream.print(cl.scope() + " "); @@ -752,14 +757,14 @@ public class Stubs { for (ClassInfo inner : cl.getRealInnerClasses()) { if (notStrippable.contains(inner) && !inner.isDocOnly()) { - writeClass(stream, notStrippable, inner); + writeClass(stream, notStrippable, inner, keepStubComments); } } for (MethodInfo method : cl.constructors()) { if (!method.isDocOnly()) { - writeMethod(stream, method, true); + writeMethod(stream, method, true, keepStubComments); } } @@ -806,7 +811,7 @@ public class Stubs { } } if (!method.isDocOnly()) { - writeMethod(stream, method, false); + writeMethod(stream, method, false, keepStubComments); } } // Write all methods that are hidden or removed, but override abstract methods or interface methods. @@ -823,7 +828,7 @@ public class Stubs { (overriddenMethod.isAbstract() || overriddenMethod.containingClass().isInterface())) { method.setReason("1:" + classContainingMethod.qualifiedName()); cl.addMethod(method); - writeMethod(stream, method, false); + writeMethod(stream, method, false, keepStubComments); } } @@ -835,7 +840,7 @@ public class Stubs { for (FieldInfo field : cl.selfFields()) { if (!field.isDocOnly()) { - writeField(stream, field); + writeField(stream, field, keepStubComments); } } @@ -853,7 +858,10 @@ public class Stubs { stream.println("}"); } - static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) { + static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor, boolean keepStubComments) { + if (keepStubComments) { + writeComment(stream, method); + } String comma; writeAnnotations(stream, method.annotations(), method.isDeprecated()); @@ -924,7 +932,10 @@ public class Stubs { } } - static void writeField(PrintStream stream, FieldInfo field) { + static void writeField(PrintStream stream, FieldInfo field, boolean keepStubComments) { + if (keepStubComments) { + writeComment(stream, field); + } writeAnnotations(stream, field.annotations(), field.isDeprecated()); stream.print(field.scope() + " "); @@ -1090,6 +1101,16 @@ public class Stubs { stream.println(";"); } + static void writeComment(PrintStream stream, DocInfo doc) { + if (!doc.isHiddenOrRemoved() && !doc.comment().isDocOnly() && !"".equals(doc.getRawCommentText())) { + String newLineSeparator = System.getProperty("line.separator"); + stream.println("/**"); + stream.print(" * "); + stream.println(doc.getRawCommentText().replace(newLineSeparator, newLineSeparator + " *")); + stream.println(" */"); + } + } + public static void writeXml(PrintStream xmlWriter, Collection<PackageInfo> pkgs, boolean strip) { if (strip) { Stubs.writeXml(xmlWriter, pkgs); |