Merge "Snap for 6982797 from 513926fc07f451c58e0c346a9c214018eca858fd to androidx-transition-release" into androidx-transition-release
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+ license_type: NOTICE
+}
diff --git a/build.gradle b/build.gradle
index 3096e0e..0a0ce4d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,76 +16,42 @@
import javax.tools.ToolProvider
-apply plugin: 'java'
-apply plugin: 'maven'
+plugins {
+ id("java")
+ id("maven-publish")
+}
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.
- * 2. The DIST_DIR is where you want to save things from the build.
- *
- * The build server will copy the contents of DIST_DIR to somewhere and make it available.
- */
-if (System.env.DIST_DIR != null && System.env.OUT_DIR != null) {
- buildDir = file("${System.env.OUT_DIR}/gradle/external/jdiff/build").getCanonicalFile()
- ext.distDir = file(System.env.DIST_DIR).getCanonicalFile()
-
- // The distDir is conveniently named after the build ID.
- version = "${version}.${ext.distDir.name}"
+if (System.env.OUT_DIR != null) {
+ buildDir = file("${System.env.OUT_DIR}/gradle/external/doclava/build").getCanonicalFile()
} else {
- buildDir = file('../../out/host/gradle/external/jdiff/build')
- ext.distDir = file('../../out/dist')
-
- // Local builds are not public release candidates.
- version = "${version}-SNAPSHOT"
+ buildDir = file('../../out/host/gradle/external/doclava/build')
}
-/*
- * If prebuilts are available, use them. Else, if this is unbundled build use jcenter().
- * Finally, if none of that is true, attempt to compile against the full source trees.
- */
-File m2repo = file('../../prebuilts/androidx/external')
-boolean unbundleBuild = (new File("unbundled-build")).exists()
-
-if (m2repo.exists() || unbundleBuild) {
- repositories {
- maven { url m2repo.absolutePath }
- if (unbundleBuild) {
- jcenter()
- }
- }
-
- dependencies {
- compile 'org.antlr:antlr:3.5.2'
- compile 'com.google.jsilver:jsilver:1.0.0'
- compile 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
- // Transitive dependency required by jsilver.
- compile 'com.google.guava:guava:15.0'
- }
-} else {
- dependencies {
- compile project(path: ':antlr', configuration: 'antlrRuntime')
- compile project(':jsilver')
- compile project(':tagsoup')
- }
+repositories {
+ maven { url file('../../prebuilts/androidx/external').absolutePath }
}
-
dependencies {
- testCompile 'junit:junit:4.12'
+ implementation("org.antlr:antlr:3.5.2")
+ implementation("com.google.jsilver:jsilver:1.0.0")
+ implementation("org.ccil.cowan.tagsoup:tagsoup:1.2.1")
// tools.jar required for com.sun.javadoc
- compile files(((URLClassLoader) ToolProvider.getSystemToolClassLoader()).getURLs())
+ def toolsJar
+ if (JavaVersion.current().getMajorVersion() == "8") {
+ toolsJar = ((URLClassLoader) ToolProvider.getSystemToolClassLoader()).getURLs()
+ } else if (System.env.JAVA_TOOLS_JAR != null) {
+ toolsJar = System.env.JAVA_TOOLS_JAR
+ } else {
+ throw new Exception("If you are not using Java 8, JAVA_TOOLS_JAR env variable " +
+ "needs to be set to build Doclava")
+ }
+ implementation(files(toolsJar))
+
+ testImplementation("junit:junit:4.12")
}
sourceSets {
@@ -99,22 +65,12 @@
}
}
-uploadArchives {
- repositories {
- mavenDeployer {
- repository(url: uri("${buildDir}/repo"))
- }
- }
+tasks.withType(JavaCompile) {
+ // Suppress build warnings that we're not interested in: b/154755010
+ options.warnings = false
}
-task dist(type: Zip, dependsOn: uploadArchives) {
- group = BasePlugin.BUILD_GROUP
- description 'Builds distribution artifacts.'
-
- from uploadArchives.artifacts
- destinationDir distDir
-
- doLast {
- logger.lifecycle "Compressed maven artifacts to ${archivePath}"
- }
+tasks.withType(Jar) { task ->
+ task.reproducibleFileOrder = true
+ task.preserveFileTimestamps = false
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 84939b4..92352a0 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=../../../../tools/external/gradle/gradle-3.3-bin.zip
+distributionUrl=../../../../tools/external/gradle/gradle-6.5.1-bin.zip
diff --git a/res/assets/templates-sdk/compatchanges.cs b/res/assets/templates-sdk/compatchanges.cs
new file mode 100644
index 0000000..001b937
--- /dev/null
+++ b/res/assets/templates-sdk/compatchanges.cs
@@ -0,0 +1,47 @@
+<?cs # THIS CREATES THE COMPAT CONFIG DOCS FROM compatconfig.xml ?>
+<?cs include:"macros.cs" ?>
+<?cs include:"macros_override.cs" ?>
+
+<?cs include:"doctype.cs" ?>
+<html<?cs if:devsite ?> devsite<?cs /if ?>>
+<?cs include:"head_tag.cs" ?>
+<?cs include:"body_tag.cs" ?>
+<div itemscope itemtype="http://developers.google.com/ReferenceObject">
+<?cs include:"header.cs" ?>
+<?cs # Includes api-info-block DIV at top of page. Standard Devsite uses right nav. ?>
+<?cs if:dac ?><?cs include:"page_info.cs" ?><?cs /if ?>
+<?cs # This DIV spans the entire document to provide scope for some scripts ?>
+<div id="jd-content" >
+
+<?cs each:change=change ?>
+ <h3 class="api-name" id="<?cs var:change.name ?>"><?cs var:change.name ?></h3>
+ <div>Value: <?cs var:change.id ?></div>
+ <div>
+ <?cs if:change.loggingOnly ?>
+ Used for logging only.
+ <?cs else ?>
+ <?cs if:change.disabled ?>
+ Disabled for all apps.
+ <?cs else ?>
+ Enabled for
+ <?cs if:change.enableAfterTargetSdk ?>
+ apps with a <code>targetSdkVersion</code> of greater than
+ <?cs var:change.enableAfterTargetSdk ?>.
+ <?cs else ?>
+ all apps.
+ <?cs /if ?>
+ <?cs /if ?>
+ <?cs /if ?>
+ </div>
+
+ <?cs call:description(change) ?>
+<?cs /each ?>
+
+</div>
+<?cs if:!devsite ?>
+<?cs include:"footer.cs" ?>
+<?cs include:"trailer.cs" ?>
+<?cs /if ?>
+</div><!-- end devsite ReferenceObject -->
+</body>
+</html>
diff --git a/src/com/google/doclava/CompatInfo.java b/src/com/google/doclava/CompatInfo.java
new file mode 100644
index 0000000..167f6ab
--- /dev/null
+++ b/src/com/google/doclava/CompatInfo.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.doclava;
+
+import com.google.clearsilver.jsilver.data.Data;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+public class CompatInfo {
+
+ public static class CompatChange {
+ public final String name;
+ public final long id;
+ public final String description;
+ public final String definedInClass;
+ public final String sourceFile;
+ public final int sourceLine;
+ public final boolean disabled;
+ public final boolean loggingOnly;
+ public final int enableAfterTargetSdk;
+
+
+ CompatChange(String name, long id, String description, String definedInClass,
+ String sourceFile, int sourceLine, boolean disabled, boolean loggingOnly,
+ int enableAfterTargetSdk) {
+ this.name = name;
+ this.id = id;
+ this.description = description;
+ this.definedInClass = definedInClass;
+ this.sourceFile = sourceFile;
+ this.sourceLine = sourceLine;
+ this.disabled = disabled;
+ this.loggingOnly = loggingOnly;
+ this.enableAfterTargetSdk = enableAfterTargetSdk;
+ }
+
+ static class Builder {
+ private String mName;
+ private long mId;
+ private String mDescription;
+ private String mDefinedInClass;
+ private String mSourceFile;
+ private int mSourceLine;
+ private boolean mDisabled;
+ private boolean mLoggingOnly;
+ private int mEnableAfterTargetSdk;
+
+ CompatChange build() {
+ return new CompatChange(
+ mName, mId, mDescription, mDefinedInClass, mSourceFile, mSourceLine,
+ mDisabled, mLoggingOnly, mEnableAfterTargetSdk);
+ }
+
+ Builder name(String name) {
+ mName = name;
+ return this;
+ }
+
+ Builder id(long id) {
+ mId = id;
+ return this;
+ }
+
+ Builder description(String description) {
+ mDescription = description;
+ return this;
+ }
+
+ Builder definedInClass(String definedInClass) {
+ mDefinedInClass = definedInClass;
+ return this;
+ }
+
+ Builder sourcePosition(String sourcePosition) throws SAXException {
+ if (sourcePosition != null) {
+ int colonPos = sourcePosition.indexOf(":");
+ if (colonPos == -1) {
+ throw new SAXException("Invalid source position: " + sourcePosition);
+ }
+ mSourceFile = sourcePosition.substring(0, colonPos);
+ try {
+ mSourceLine = Integer.parseInt(sourcePosition.substring(colonPos + 1));
+ } catch (NumberFormatException nfe) {
+ throw new SAXException("Invalid source position: " + sourcePosition, nfe);
+ }
+ }
+ return this;
+ }
+
+ boolean parseBool(String value) {
+ if (value == null) {
+ return false;
+ }
+ boolean result = Boolean.parseBoolean(value);
+ return result;
+ }
+
+ Builder disabled(String disabled) {
+ mDisabled = parseBool(disabled);
+ return this;
+ }
+
+ Builder loggingOnly(String loggingOnly) {
+ mLoggingOnly = parseBool(loggingOnly);
+ return this;
+ }
+
+ Builder enableAfterTargetSdk(String enableAfter) throws SAXException {
+ if (enableAfter == null) {
+ mEnableAfterTargetSdk = 0;
+ } else {
+ try {
+ mEnableAfterTargetSdk = Integer.parseInt(enableAfter);
+ } catch (NumberFormatException nfe) {
+ throw new SAXException("Invalid SDK version int: " + enableAfter, nfe);
+ }
+ }
+ return this;
+ }
+ }
+
+ }
+
+ private class CompatConfigXmlParser extends DefaultHandler {
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ if (qName.equals("compat-change")) {
+ mCurrentChange = new CompatChange.Builder();
+ String idStr = attributes.getValue("id");
+ if (idStr == null) {
+ throw new SAXException("<compat-change> element has no id");
+ }
+ try {
+ mCurrentChange.id(Long.parseLong(idStr));
+ } catch (NumberFormatException nfe) {
+ throw new SAXException("<compat-change> id is not a valid long", nfe);
+ }
+ mCurrentChange.name(attributes.getValue("name"))
+ .description(attributes.getValue("description"))
+ .enableAfterTargetSdk(attributes.getValue("enableAfterTargetSdk"))
+ .disabled(attributes.getValue("disabled"))
+ .loggingOnly(attributes.getValue("loggingOnly"));
+
+ } else if (qName.equals("meta-data")) {
+ if (mCurrentChange == null) {
+ throw new SAXException("<meta-data> tag with no enclosing <compat-change>");
+ }
+ mCurrentChange.definedInClass(attributes.getValue("definedIn"))
+ .sourcePosition(attributes.getValue("sourcePosition"));
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) {
+ if (qName.equals("compat-change")) {
+ mChanges.add(mCurrentChange.build());
+ mCurrentChange = null;
+ }
+ }
+ }
+
+ public static CompatInfo readCompatConfig(String source) {
+ CompatInfo config = new CompatInfo();
+ try {
+ InputStream in = new FileInputStream(new File(source));
+
+ XMLReader xmlreader = XMLReaderFactory.createXMLReader();
+ xmlreader.setContentHandler(config.mXmlParser);
+ xmlreader.setErrorHandler(config.mXmlParser);
+ xmlreader.parse(new InputSource(in));
+ in.close();
+ return config;
+ } catch (SAXException e) {
+ throw new RuntimeException("Failed to parse " + source, e);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to read " + source, e);
+ }
+ }
+
+ private final CompatConfigXmlParser mXmlParser = new CompatConfigXmlParser();
+ private CompatChange.Builder mCurrentChange;
+ private List<CompatChange> mChanges = new ArrayList<>();
+
+ public List<CompatChange> getChanges() {
+ return mChanges;
+ }
+
+ public void makeHDF(Data hdf) {
+ // We construct a Comment for each compat change to re-use the default docs generation support
+ // for comments.
+ mChanges.sort(Comparator.comparing(a -> a.name));
+ for (int i = 0; i < mChanges.size(); ++i) {
+ CompatInfo.CompatChange change = mChanges.get(i);
+ // we will get null ClassInfo here if the defining class is not in the SDK.
+ ContainerInfo definedInContainer = Converter.obtainClass(change.definedInClass);
+ if (definedInContainer == null) {
+ // This happens when the class defining the @ChangeId constant is not included in
+ // the sources that the SDK docs are generated from. Using package "android" as the
+ // container works, but means we lose the context of the original javadoc comment.
+ // This means that if the javadoc comment refers to classes imported by it's
+ // containing source file, we cannot resolve those imports here.
+ // TODO see if we could somehow plumb the import list from the original source file,
+ // via compat_config.xml, so we can resolve links properly here?
+ definedInContainer = Converter.obtainPackage("android");
+ }
+ if (change.description == null) {
+ throw new RuntimeException("No desriprion found for @ChangeId " + change.name);
+ }
+ Comment comment = new Comment(change.description, definedInContainer, new SourcePositionInfo(
+ change.sourceFile, change.sourceLine, 1));
+ String path = "change." + i;
+ hdf.setValue(path + ".id", Long.toString(change.id));
+ hdf.setValue(path + ".name", change.name);
+ if (change.enableAfterTargetSdk != 0) {
+ hdf.setValue(path + ".enableAfterTargetSdk",
+ Integer.toString(change.enableAfterTargetSdk));
+ }
+ if (change.loggingOnly) {
+ hdf.setValue(path + ".loggingOnly", Boolean.toString(true));
+ }
+ if (change.disabled) {
+ hdf.setValue(path + ".disabled", Boolean.toString(true));
+ }
+ TagInfo.makeHDF(hdf, path + ".descr", comment.tags());
+ }
+ }
+}
diff --git a/src/com/google/doclava/Converter.java b/src/com/google/doclava/Converter.java
index a6f803b..cf14237 100644
--- a/src/com/google/doclava/Converter.java
+++ b/src/com/google/doclava/Converter.java
@@ -501,23 +501,9 @@
return result;
} else {
ConstructorDoc m = (ConstructorDoc) o;
- // Workaround for a JavaDoc behavior change introduced in OpenJDK 8 that breaks
- // links in documentation and the content of API files like current.txt.
- // http://b/18051133.
- String name = m.name();
- ClassDoc containingClass = m.containingClass();
- if (containingClass.containingClass() != null) {
- // This should detect the new behavior and be bypassed otherwise.
- if (!name.contains(".")) {
- // Constructors of inner classes do not contain the name of the enclosing class
- // with OpenJDK 8. This simulates the old behavior:
- name = containingClass.name();
- }
- }
- // End of workaround.
MethodInfo result =
new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))),
- name, m.signature(), Converter.obtainClass(m.containingClass()), Converter
+ m.name(), m.signature(), Converter.obtainClass(m.containingClass()), Converter
.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
.isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
false, m.isSynchronized(), m.isNative(), false/*isDefault*/, false, "constructor", m.flatSignature(),
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index f24718a..049e93e 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -127,6 +127,7 @@
public static Linter linter = new EmptyLinter();
public static boolean android = false;
public static String manifestFile = null;
+ public static String compatConfig = null;
public static Map<String, String> manifestPermissions = new HashMap<>();
public static JSilver jSilver = null;
@@ -403,6 +404,8 @@
android = true;
} else if (a[0].equals("-manifest")) {
manifestFile = a[1];
+ } else if (a[0].equals("-compatconfig")) {
+ compatConfig = a[1];
}
}
@@ -538,6 +541,7 @@
writeClassLists();
writeClasses();
writeHierarchy();
+ writeCompatConfig();
// writeKeywords();
// Write yaml tree.
@@ -962,6 +966,9 @@
if (option.equals("-manifest")) {
return 2;
}
+ if (option.equals("-compatconfig")) {
+ return 2;
+ }
return 0;
}
public static boolean validOptions(String[][] options, DocErrorReporter r) {
@@ -2171,8 +2178,8 @@
public static String getDocumentationStringForAnnotation(String annotationName) {
if (!documentAnnotations) return null;
if (annotationDocumentationMap == null) {
- // parse the file for map
annotationDocumentationMap = new HashMap<String, String>();
+ // parse the file for map
try {
BufferedReader in = new BufferedReader(
new FileReader(documentAnnotationsPath));
@@ -2195,4 +2202,17 @@
return annotationDocumentationMap.get(annotationName);
}
+ public static void writeCompatConfig() {
+ if (compatConfig == null) {
+ return;
+ }
+ CompatInfo config = CompatInfo.readCompatConfig(compatConfig);
+ Data data = makeHDF();
+ config.makeHDF(data);
+ setPageTitle(data, "Compatibility changes");
+ // TODO - should we write the output to some other path?
+ String outfile = "compatchanges.html";
+ ClearPage.write(data, "compatchanges.cs", outfile);
+ }
+
}
diff --git a/src/com/google/doclava/SeeTagInfo.java b/src/com/google/doclava/SeeTagInfo.java
index eddc595..fee8ce2 100644
--- a/src/com/google/doclava/SeeTagInfo.java
+++ b/src/com/google/doclava/SeeTagInfo.java
@@ -35,16 +35,8 @@
protected LinkReference linkReference() {
if (mLink == null) {
- // If this is a @see reference in frameworks/base, suppress errors about broken references.
- // Outside of frameworks/base, and the generated android/R file, all such
- // errors have been fixed, see b/80570421.
- boolean suppressableSeeReference =
- "@see".equals(name()) &&
- (position().file.contains("frameworks/base/")
- || position().file.endsWith("android/R.java"));
- mLink =
- LinkReference.parse(text(), mBase, position(), !suppressableSeeReference
- && (mBase != null ? mBase.checkLevel() : true));
+ mLink = LinkReference.parse(text(), mBase, position(),
+ mBase != null ? mBase.checkLevel() : true);
}
return mLink;
}