aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/docgen
diff options
context:
space:
mode:
authorGravatar cparsons <cparsons@google.com>2018-05-01 10:32:30 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-01 10:33:46 -0700
commit2415cb4ab69ec05d2e7ba15c75a20e2d2da2fc90 (patch)
tree33a8c5810973f58ff8c084b14078be87cc2bf5ad /src/main/java/com/google/devtools/build/docgen
parent2e4f703d361823fa12df9ddb57f21189743b2c74 (diff)
Use a new pattern for builtin Provider objects with @SkylarkCallable.
This deprecates the old NativeProvider pattern. The new pattern is demonstrated using AppleStaticLibraryInfo. RELNOTES: None. PiperOrigin-RevId: 194956883
Diffstat (limited to 'src/main/java/com/google/devtools/build/docgen')
-rw-r--r--src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java71
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java5
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java20
3 files changed, 78 insertions, 18 deletions
diff --git a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java
index 6b614b381b..67c46f0e95 100644
--- a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java
+++ b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java
@@ -37,6 +37,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import javax.annotation.Nullable;
/**
* A helper class that collects Skylark module documentation.
@@ -125,6 +126,10 @@ final class SkylarkDocumentationCollector {
while (!toProcess.isEmpty()) {
Class<?> c = toProcess.removeFirst();
+ if (done.contains(c)) {
+ continue;
+ }
+
SkylarkModuleDoc module = getSkylarkModuleDoc(c, modules);
done.add(c);
@@ -132,21 +137,57 @@ final class SkylarkDocumentationCollector {
ImmutableMap<Method, SkylarkCallable> methods =
FuncallExpression.collectSkylarkMethodsWithAnnotation(c);
for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
- module.addMethod(
- new SkylarkJavaMethodDoc(module.getName(), entry.getKey(), entry.getValue()));
- }
+ if (entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
+ collectConstructor(modules, module.getName(), entry.getKey(), entry.getValue());
+ } else {
+ module.addMethod(
+ new SkylarkJavaMethodDoc(module.getName(), entry.getKey(), entry.getValue()));
+ }
- for (Map.Entry<Method, SkylarkCallable> method : methods.entrySet()) {
- Class<?> returnClass = method.getKey().getReturnType();
- if (returnClass.isAnnotationPresent(SkylarkModule.class)
- && !done.contains(returnClass)) {
+ Class<?> returnClass = entry.getKey().getReturnType();
+ if (returnClass.isAnnotationPresent(SkylarkModule.class)) {
toProcess.addLast(returnClass);
+ } else {
+ Map.Entry<Method, SkylarkCallable> selfCallConstructor =
+ getSelfCallConstructorMethod(returnClass);
+ if (selfCallConstructor != null) {
+ // If the class to be processed is not annotated with @SkylarkModule, then its
+ // @SkylarkCallable methods are not processed, as it does not have its own
+ // documentation page. However, if it is a callable object (has a selfCall method)
+ // that is also a constructor for another type, we still want to ensure that method
+ // is documented.
+ // This is used for builtin providers, which typically are not marked @SkylarkModule,
+ // but which have selfCall constructors for their corresponding Info class.
+
+ // For example, the "mymodule" module may return a callable object at mymodule.foo
+ // which constructs instances of the Bar class. The type returned by mymodule.foo
+ // may have no documentation, but mymodule.foo should be documented as a
+ // constructor of Bar objects.
+ collectConstructor(modules, module.getName(),
+ selfCallConstructor.getKey(), selfCallConstructor.getValue());
+ }
}
}
}
}
}
+ @Nullable
+ private static Map.Entry<Method, SkylarkCallable> getSelfCallConstructorMethod(
+ Class<?> objectClass) {
+ ImmutableMap<Method, SkylarkCallable> methods =
+ FuncallExpression.collectSkylarkMethodsWithAnnotation(objectClass);
+ for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
+ if (entry.getValue().selfCall()
+ && entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
+ // It's illegal, and checked by the interpreter, for there to be more than one method
+ // annotated with selfCall. Thus, it's valid to return on the first find.
+ return entry;
+ }
+ }
+ return null;
+ }
+
private static void collectBuiltinDoc(Map<String, SkylarkModuleDoc> modules, Field[] fields) {
for (Field field : fields) {
if (field.isAnnotationPresent(SkylarkSignature.class)) {
@@ -168,15 +209,19 @@ final class SkylarkDocumentationCollector {
FuncallExpression.collectSkylarkMethodsWithAnnotation(moduleClass);
for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
if (entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
- SkylarkConstructor constructorAnnotation =
- entry.getKey().getAnnotation(SkylarkConstructor.class);
- Class<?> objectClass = constructorAnnotation.objectType();
- SkylarkModuleDoc module = getSkylarkModuleDoc(objectClass, modules);
- module.addMethod(
- new SkylarkJavaMethodDoc("", entry.getKey(), entry.getValue()));
+ collectConstructor(modules, "", entry.getKey(), entry.getValue());
} else {
topLevelModuleDoc.addMethod(new SkylarkJavaMethodDoc("", entry.getKey(), entry.getValue()));
}
}
}
+
+ private static void collectConstructor(Map<String, SkylarkModuleDoc> modules,
+ String originatingModuleName, Method method, SkylarkCallable callable) {
+ SkylarkConstructor constructorAnnotation =
+ Preconditions.checkNotNull(method.getAnnotation(SkylarkConstructor.class));
+ Class<?> objectClass = constructorAnnotation.objectType();
+ SkylarkModuleDoc module = getSkylarkModuleDoc(objectClass, modules);
+ module.setConstructor(new SkylarkJavaMethodDoc(originatingModuleName, method, callable));
+ }
}
diff --git a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java
index 60c19874fd..95f740e002 100644
--- a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java
@@ -17,6 +17,7 @@ import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.syntax.EvalUtils;
@@ -69,8 +70,8 @@ abstract class SkylarkDoc {
return "<a class=\"anchor\" href=\"" + TOP_LEVEL_ID + ".html#None\">None</a>";
} else if (type.equals(NestedSet.class)) {
return "<a class=\"anchor\" href=\"depset.html\">depset</a>";
- } else if (type.isAnnotationPresent(SkylarkModule.class)) {
- SkylarkModule module = type.getAnnotation(SkylarkModule.class);
+ } else if (SkylarkInterfaceUtils.getSkylarkModule(type) != null) {
+ SkylarkModule module = SkylarkInterfaceUtils.getSkylarkModule(type);
if (module.documented()) {
return String.format("<a class=\"anchor\" href=\"%1$s.html\">%1$s</a>",
module.name());
diff --git a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java
index 898c841085..24da2f3e96 100644
--- a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java
@@ -15,6 +15,7 @@ package com.google.devtools.build.docgen.skylark;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
@@ -25,10 +26,12 @@ import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
+import javax.annotation.Nullable;
/**
- * A class representing a Skylark built-in object with its {@link SkylarkSignature} annotation
- * and the {@link SkylarkCallable} methods it might have.
+ * A class representing documentation for a Skylark built-in object with its {@link SkylarkModule}
+ * annotation and with the {@link SkylarkCallable} methods and {@link SkylarkSignature} fields it
+ * documents.
*/
public final class SkylarkModuleDoc extends SkylarkDoc {
private final SkylarkModule module;
@@ -37,6 +40,7 @@ public final class SkylarkModuleDoc extends SkylarkDoc {
private final Multimap<String, SkylarkJavaMethodDoc> javaMethods;
private TreeMap<String, SkylarkMethodDoc> methodMap;
private final String title;
+ @Nullable private SkylarkJavaMethodDoc javaConstructor;
public SkylarkModuleDoc(SkylarkModule module, Class<?> classObject) {
this.module = Preconditions.checkNotNull(
@@ -74,6 +78,12 @@ public final class SkylarkModuleDoc extends SkylarkDoc {
return classObject;
}
+ public void setConstructor(SkylarkJavaMethodDoc method) {
+ Preconditions.checkState(javaConstructor == null);
+ javaConstructor = method;
+ methodMap.put(method.getName(), method);
+ }
+
public void addMethod(SkylarkBuiltinMethodDoc method) {
methodMap.put(method.getName(), method);
builtinMethodMap.put(method.getName(), method);
@@ -114,7 +124,11 @@ public final class SkylarkModuleDoc extends SkylarkDoc {
}
public Collection<SkylarkJavaMethodDoc> getJavaMethods() {
- return javaMethods.values();
+ ImmutableList.Builder<SkylarkJavaMethodDoc> returnedMethods = ImmutableList.builder();
+ if (javaConstructor != null) {
+ returnedMethods.add(javaConstructor);
+ }
+ return returnedMethods.addAll(javaMethods.values()).build();
}
public Collection<SkylarkMethodDoc> getMethods() {