summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2017-06-13 20:33:16 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-06-13 20:33:24 +0000
commit4bed278d51e069a52cd0aac560dcbf13593e0d45 (patch)
treeee84350471cf03ed84849a7f970a0fc03e30f9bb
parent4c4643b47bfe31bec46e0de9ac10448bbe3d3c1d (diff)
parentbb3c3f1d4ca6dfc90ac68019b71d732a8455912d (diff)
downloadplatform_external_doclava-4bed278d51e069a52cd0aac560dcbf13593e0d45.tar.gz
platform_external_doclava-4bed278d51e069a52cd0aac560dcbf13593e0d45.tar.bz2
platform_external_doclava-4bed278d51e069a52cd0aac560dcbf13593e0d45.zip
Merge "Add Doclava support for federated APIs not referenced from code"
-rw-r--r--src/com/google/doclava/Converter.java62
-rw-r--r--src/com/google/doclava/Doclava.java5
-rw-r--r--src/com/google/doclava/FederationTagger.java67
-rw-r--r--src/com/google/doclava/TypeInfo.java17
4 files changed, 128 insertions, 23 deletions
diff --git a/src/com/google/doclava/Converter.java b/src/com/google/doclava/Converter.java
index ee91960..0d4e455 100644
--- a/src/com/google/doclava/Converter.java
+++ b/src/com/google/doclava/Converter.java
@@ -16,7 +16,7 @@
package com.google.doclava;
-
+import com.google.doclava.apicheck.ApiInfo;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationTypeDoc;
import com.sun.javadoc.AnnotationTypeElementDoc;
@@ -42,12 +42,15 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
public class Converter {
private static RootDoc root;
+ private static List<ApiInfo> apis;
public static void makeInfo(RootDoc r) {
root = r;
+ apis = new ArrayList<>();
// create the objects
ClassDoc[] classes = getClasses(r);
@@ -78,6 +81,15 @@ public class Converter {
mRootClasses = Converter.convertClasses(classes);
}
+ /**
+ * Adds additional APIs to be available from calls to obtain() methods.
+ *
+ * @param api the APIs to add, must be non-{@code null}
+ */
+ public static void addApiInfo(ApiInfo api) {
+ apis.add(api);
+ }
+
private static ClassDoc[] getClasses(RootDoc r) {
ClassDoc[] classDocs = r.classes();
ArrayList<ClassDoc> filtered = new ArrayList<ClassDoc>(classDocs.length);
@@ -155,12 +167,54 @@ public class Converter {
Converter.convertClasses(c.innerClasses(false)))));
}
+ /**
+ * Obtains a {@link ClassInfo} describing the specified class. If the class
+ * was not specified on the source path, this method will attempt to locate
+ * the class within the list of federated APIs.
+ *
+ * @param className the fully-qualified class name to search for
+ * @return info for the specified class, or {@code null} if not available
+ * @see #addApiInfo(ApiInfo)
+ */
public static ClassInfo obtainClass(String className) {
- return Converter.obtainClass(root.classNamed(className));
+ ClassInfo result = Converter.obtainClass(root.classNamed(className));
+ if (result != null) {
+ return result;
+ }
+
+ for (ApiInfo api : apis) {
+ result = api.findClass(className);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
}
+ /**
+ * Obtains a {@link PackageInfo} describing the specified package. If the
+ * package was not specified on the source path, this method will attempt to
+ * locate the package within the list of federated APIs.
+ *
+ * @param packageName the fully-qualified package name to search for
+ * @return info for the specified package, or {@code null} if not available
+ * @see #addApiInfo(ApiInfo)
+ */
public static PackageInfo obtainPackage(String packageName) {
- return Converter.obtainPackage(root.packageNamed(packageName));
+ PackageInfo result = Converter.obtainPackage(root.packageNamed(packageName));
+ if (result != null) {
+ return result;
+ }
+
+ for (ApiInfo api : apis) {
+ result = api.getPackages().get(packageName);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
}
private static TagInfo convertTag(Tag tag) {
@@ -456,7 +510,7 @@ public class Converter {
}
// End of workaround.
MethodInfo result =
- new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))),
+ new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))),
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(),
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index 29ef509..9d3f1b6 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -415,6 +415,11 @@ public class Doclava {
// don't do ref doc tasks in devsite static-only builds
if (!DEVSITE_STATIC_ONLY) {
+ // Load additional data structures from federated sites.
+ for(FederatedSite site : federationTagger.getSites()) {
+ Converter.addApiInfo(site.apiInfo());
+ }
+
// Apply @since tags from the XML file
sinceTagger.tagAll(Converter.rootClasses());
diff --git a/src/com/google/doclava/FederationTagger.java b/src/com/google/doclava/FederationTagger.java
index f3603a5..a83bb20 100644
--- a/src/com/google/doclava/FederationTagger.java
+++ b/src/com/google/doclava/FederationTagger.java
@@ -29,22 +29,46 @@ import java.util.Map;
* against when overlapping content is discovered.
*/
public final class FederationTagger {
- private final Map<String, URL> federatedUrls = new HashMap<String, URL>();
- private final Map<String, String> federatedXmls = new HashMap<String, String>();
- private final List<FederatedSite> federatedSites = new ArrayList<FederatedSite>();
+ private final Map<String, URL> federatedUrls = new HashMap<>();
+ private final Map<String, String> federatedXmls = new HashMap<>();
+ private final List<FederatedSite> federatedSites = new ArrayList<>();
+
private boolean initialized = false;
+
/**
* Adds a Doclava documentation site for federation. Accepts the base URL of
* the remote API.
+ * <p>
+ * If {@link #addSiteApi(String, String)} is not called, this will default to
+ * reading the API from "/xml/current.xml" within the site's base URL.
+ * <p>
+ * <strong>Note:</strong> Must be called before calling tag() or get() methods.
+ *
+ * @param name internally-used name for federation site
*/
public void addSiteUrl(String name, URL site) {
+ if (initialized) {
+ throw new IllegalStateException("Cannot add sites after calling tag() or get() methods.");
+ }
federatedUrls.put(name, site);
}
-
+
+ /**
+ * Adds an explicit Doclava-generated API file for the specified site.
+ * <p>
+ * <strong>Note:</strong> Must be called before calling tag() or get() methods.
+ *
+ * @param name internally-used name for federation site (must match name used
+ * for {@link #addSiteUrl(String, URL)})
+ * @param file path to a Doclava-generated API file
+ */
public void addSiteApi(String name, String file) {
+ if (initialized) {
+ throw new IllegalStateException("Cannot add sites after calling tag() or get() methods.");
+ }
federatedXmls.put(name, file);
}
-
+
public void tag(ClassInfo classDoc) {
initialize();
for (FederatedSite site : federatedSites) {
@@ -58,19 +82,28 @@ public final class FederationTagger {
applyFederation(site, classDocs);
}
}
-
+
+ /**
+ * Returns a non-{@code null} list of {@link FederatedSite} objects, one for
+ * each unique {@code name} added using {@link #addSiteUrl(String, URL)}.
+ */
+ public List<FederatedSite> getSites() {
+ initialize();
+ return federatedSites;
+ }
+
private void initialize() {
if (initialized) {
return;
}
-
+
for (String name : federatedXmls.keySet()) {
if (!federatedUrls.containsKey(name)) {
Errors.error(Errors.NO_FEDERATION_DATA, (SourcePositionInfo) null,
"Unknown documentation site for " + name);
}
}
-
+
for (String name : federatedUrls.keySet()) {
try {
if (federatedXmls.containsKey(name)) {
@@ -87,10 +120,10 @@ public final class FederationTagger {
Errors.error(Errors.NO_FEDERATION_DATA, (SourcePositionInfo) null, error);
}
}
-
+
initialized = true;
}
-
+
private void applyFederation(FederatedSite federationSource, ClassInfo[] classDocs) {
for (ClassInfo classDoc : classDocs) {
PackageInfo packageSpec
@@ -101,11 +134,11 @@ public final class FederationTagger {
}
ClassInfo classSpec = packageSpec.allClasses().get(classDoc.name());
-
+
if (classSpec == null) {
continue;
}
-
+
federateMethods(federationSource, classSpec, classDoc);
federateConstructors(federationSource, classSpec, classDoc);
federateFields(federationSource, classSpec, classDoc);
@@ -124,7 +157,7 @@ public final class FederationTagger {
}
}
}
-
+
private void federateConstructors(FederatedSite site, ClassInfo federatedClass,
ClassInfo localClass) {
for (MethodInfo constructor : localClass.constructors()) {
@@ -133,7 +166,7 @@ public final class FederationTagger {
}
}
}
-
+
private void federateFields(FederatedSite site, ClassInfo federatedClass, ClassInfo localClass) {
for (FieldInfo field : localClass.fields()) {
if (federatedClass.allFields().containsKey(field.name())) {
@@ -141,12 +174,12 @@ public final class FederationTagger {
}
}
}
-
+
private void federateClass(FederatedSite source, ClassInfo doc) {
doc.addFederatedReference(source);
}
-
+
private void federatePackage(FederatedSite source, PackageInfo pkg) {
pkg.addFederatedReference(source);
}
-} \ No newline at end of file
+}
diff --git a/src/com/google/doclava/TypeInfo.java b/src/com/google/doclava/TypeInfo.java
index 7bba560..7e971c4 100644
--- a/src/com/google/doclava/TypeInfo.java
+++ b/src/com/google/doclava/TypeInfo.java
@@ -24,7 +24,7 @@ public class TypeInfo implements Resolvable {
public static final Set<String> PRIMITIVE_TYPES = Collections.unmodifiableSet(
new HashSet<String>(Arrays.asList("boolean", "byte", "char", "double", "float", "int",
"long", "short", "void")));
-
+
public TypeInfo(boolean isPrimitive, String dimension, String simpleTypeName,
String qualifiedTypeName, ClassInfo cl) {
mIsPrimitive = isPrimitive;
@@ -107,7 +107,7 @@ public class TypeInfo implements Resolvable {
typeString = typeString.substring(0, extendsPos);
}
- int pos = typeString.indexOf('[');
+ int pos = typeString.indexOf('[');
if (pos > -1) {
mDimension = typeString.substring(pos);
typeString = typeString.substring(0, pos);
@@ -153,7 +153,17 @@ public class TypeInfo implements Resolvable {
mFullName = other.fullName();
}
+ /**
+ * Returns this type as a {@link ClassInfo} if it represents a class or
+ * interface.
+ */
public ClassInfo asClassInfo() {
+ if (!mResolvedClass) {
+ mResolvedClass = true;
+ if (mClass == null && !mIsPrimitive && !mIsTypeVariable && !mIsWildcard) {
+ mClass = Converter.obtainClass(qualifiedTypeName());
+ }
+ }
return mClass;
}
@@ -544,6 +554,9 @@ public class TypeInfo implements Resolvable {
private ArrayList<Resolution> mResolutions;
+ /** Whether the value of {@code mClass} has been resolved. */
+ private boolean mResolvedClass;
+
private boolean mIsPrimitive;
private boolean mIsTypeVariable;
private boolean mIsWildcard;