aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
authorGravatar David Chen <dzc@google.com>2015-08-17 17:25:46 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-08-18 10:39:58 +0000
commit24f2d99880317c928b36bc972eefe43e3134e27a (patch)
tree8eee0f94c6638ebd521c4019a623430f2486c2a9 /src/main/java/com/google/devtools/build
parente4ead964ce3250a82bcc8803abc837301238acca (diff)
Split Skylark Library into multiple pages, one per module. Add collapsible
submenus to sidebar, and expand and highlight the link for the current page. Collapse sidebar on mobile and expose button for toggling sidebar. -- MOS_MIGRATED_REVID=100836792
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/docgen/DocgenConsts.java6
-rw-r--r--src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java196
-rw-r--r--src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationGenerator.java3
-rw-r--r--src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationProcessor.java456
-rw-r--r--src/main/java/com/google/devtools/build/docgen/SkylarkJavaInterfaceExplorer.java160
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkBuiltinMethodDoc.java97
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java85
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkJavaMethodDoc.java71
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkMethodDoc.java116
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java98
-rw-r--r--src/main/java/com/google/devtools/build/docgen/skylark/SkylarkParamDoc.java61
-rw-r--r--src/main/java/com/google/devtools/build/docgen/templates/be-header.vm8
-rw-r--r--src/main/java/com/google/devtools/build/docgen/templates/skylark-body.html58
-rw-r--r--src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm58
-rw-r--r--src/main/java/com/google/devtools/build/docgen/templates/skylark-nav.vm4
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/Artifact.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Attribute.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkFileType.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java2
25 files changed, 869 insertions, 653 deletions
diff --git a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
index 31f3359247..e50058854d 100644
--- a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
+++ b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
@@ -32,7 +32,11 @@ public class DocgenConsts {
public static final String HEADER_TEMPLATE = "templates/be-header.html";
public static final String FOOTER_TEMPLATE = "templates/be-footer.html";
public static final String BODY_TEMPLATE = "templates/be-body.html";
- public static final String SKYLARK_BODY_TEMPLATE = "templates/skylark-body.html";
+
+ public static final String SKYLARK_LIBRARY_TEMPLATE =
+ "com/google/devtools/build/docgen/templates/skylark-library.vm";
+ public static final String SKYLARK_NAV_TEMPLATE =
+ "com/google/devtools/build/docgen/templates/skylark-nav.vm";
public static final String VAR_LEFT_PANEL = "LEFT_PANEL";
diff --git a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java
new file mode 100644
index 0000000000..f7ae83b0e4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java
@@ -0,0 +1,196 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.docgen.skylark.SkylarkBuiltinMethodDoc;
+import com.google.devtools.build.docgen.skylark.SkylarkJavaMethodDoc;
+import com.google.devtools.build.docgen.skylark.SkylarkModuleDoc;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.rules.SkylarkModules;
+import com.google.devtools.build.lib.rules.SkylarkRuleContext;
+import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.MethodLibrary;
+import com.google.devtools.build.lib.syntax.SkylarkCallable;
+import com.google.devtools.build.lib.syntax.SkylarkModule;
+import com.google.devtools.build.lib.syntax.SkylarkSignature;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * A helper class that collects Skylark module documentation.
+ */
+final class SkylarkDocumentationCollector {
+ @SkylarkModule(name = "globals",
+ doc = "Objects, functions and modules registered in the global environment.")
+ private static final class TopLevelModule {}
+
+ private SkylarkDocumentationCollector() {}
+
+ /**
+ * Returns the SkylarkModule annotation for the top-level Skylark module.
+ */
+ public static SkylarkModule getTopLevelModule() {
+ return TopLevelModule.class.getAnnotation(SkylarkModule.class);
+ }
+
+ /**
+ * Collects the documentation for all Skylark modules and returns a map that maps Skylark
+ * module name to the module documentation.
+ */
+ public static Map<String, SkylarkModuleDoc> collectModules() {
+ Map<String, SkylarkModuleDoc> modules = new TreeMap<>();
+ Map<String, SkylarkModuleDoc> builtinModules = collectBuiltinModules();
+ Map<SkylarkModule, Class<?>> builtinJavaObjects = collectBuiltinJavaObjects();
+
+ modules.putAll(builtinModules);
+ for (SkylarkModuleDoc builtinObject : builtinModules.values()) {
+ // Check the return type for built-in functions, it can be a module previously not added.
+ for (SkylarkBuiltinMethodDoc builtinMethod : builtinObject.getBuiltinMethods().values()) {
+ Class<?> type = builtinMethod.getAnnotation().returnType();
+ if (type.isAnnotationPresent(SkylarkModule.class)) {
+ collectJavaObjects(type.getAnnotation(SkylarkModule.class), type, modules);
+ }
+ }
+ collectJavaObjects(builtinObject.getAnnotation(), builtinObject.getClassObject(), modules);
+ }
+ for (Entry<SkylarkModule, Class<?>> builtinModule : builtinJavaObjects.entrySet()) {
+ collectJavaObjects(builtinModule.getKey(), builtinModule.getValue(), modules);
+ }
+ return modules;
+ }
+
+ /**
+ * Collects and returns all the Java objects reachable in Skylark from (and including)
+ * firstClass with the corresponding SkylarkModule annotation.
+ *
+ * <p>Note that the {@link SkylarkModule} annotation for firstClass - firstModule -
+ * is also an input parameter, because some top level Skylark built-in objects and methods
+ * are not annotated on the class, but on a field referencing them.
+ */
+ @VisibleForTesting
+ static void collectJavaObjects(SkylarkModule firstModule, Class<?> firstClass,
+ Map<String, SkylarkModuleDoc> modules) {
+ Set<Class<?>> done = new HashSet<>();
+ Deque<Class<?>> toProcess = new LinkedList<>();
+ Map<Class<?>, SkylarkModule> annotations = new HashMap<>();
+
+ toProcess.addLast(firstClass);
+ annotations.put(firstClass, firstModule);
+
+ while (!toProcess.isEmpty()) {
+ Class<?> c = toProcess.removeFirst();
+ SkylarkModule annotation = annotations.get(c);
+ done.add(c);
+ if (!modules.containsKey(annotation.name())) {
+ modules.put(annotation.name(), new SkylarkModuleDoc(annotation, c));
+ }
+ SkylarkModuleDoc module = modules.get(annotation.name());
+
+ if (module.javaMethodsNotCollected()) {
+ ImmutableMap<Method, SkylarkCallable> methods =
+ FuncallExpression.collectSkylarkMethodsWithAnnotation(c);
+ for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
+ module.addMethod(new SkylarkJavaMethodDoc(module, 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)) {
+ toProcess.addLast(returnClass);
+ annotations.put(returnClass, returnClass.getAnnotation(SkylarkModule.class));
+ }
+ }
+ }
+ }
+ }
+
+ private static Map<String, SkylarkModuleDoc> collectBuiltinModules() {
+ Map<String, SkylarkModuleDoc> modules = new HashMap<>();
+ collectBuiltinDoc(modules, Environment.class.getDeclaredFields());
+ collectBuiltinDoc(modules, MethodLibrary.class.getDeclaredFields());
+ for (Class<?> moduleClass : SkylarkModules.MODULES) {
+ collectBuiltinDoc(modules, moduleClass.getDeclaredFields());
+ }
+ return modules;
+ }
+
+ private static void collectBuiltinDoc(Map<String, SkylarkModuleDoc> modules, Field[] fields) {
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(SkylarkSignature.class)) {
+ SkylarkSignature skylarkSignature = field.getAnnotation(SkylarkSignature.class);
+ Class<?> moduleClass = skylarkSignature.objectType();
+ SkylarkModule skylarkModule = moduleClass.equals(Object.class)
+ ? getTopLevelModule()
+ : moduleClass.getAnnotation(SkylarkModule.class);
+ if (!modules.containsKey(skylarkModule.name())) {
+ modules.put(skylarkModule.name(), new SkylarkModuleDoc(skylarkModule, moduleClass));
+ }
+
+ SkylarkModuleDoc module = modules.get(skylarkModule.name());
+ module.addMethod(new SkylarkBuiltinMethodDoc(module, skylarkSignature, field.getType()));
+ }
+ }
+ }
+
+ private static Map<SkylarkModule, Class<?>> collectBuiltinJavaObjects() {
+ Map<SkylarkModule, Class<?>> modules = new HashMap<>();
+ collectBuiltinModule(modules, SkylarkRuleContext.class);
+ collectBuiltinModule(modules, TransitiveInfoCollection.class);
+ return modules;
+ }
+
+ private static void collectBuiltinModule(
+ Map<SkylarkModule, Class<?>> modules, Class<?> moduleClass) {
+ if (moduleClass.isAnnotationPresent(SkylarkModule.class)) {
+ SkylarkModule skylarkModule = moduleClass.getAnnotation(SkylarkModule.class);
+ modules.put(skylarkModule, moduleClass);
+ }
+ }
+
+ /**
+ * Returns the top level modules and functions with their documentation in a command-line
+ * printable format.
+ */
+ public static Map<String, String> collectTopLevelModules() {
+ Map<String, String> modules = new TreeMap<>();
+ for (SkylarkModuleDoc doc : collectBuiltinModules().values()) {
+ if (doc.getAnnotation() == getTopLevelModule()) {
+ for (Map.Entry<String, SkylarkBuiltinMethodDoc> entry :
+ doc.getBuiltinMethods().entrySet()) {
+ if (entry.getValue().documented()) {
+ modules.put(entry.getKey(),
+ DocgenConsts.toCommandLineFormat(entry.getValue().getDocumentation()));
+ }
+ }
+ } else {
+ modules.put(doc.getAnnotation().name(),
+ DocgenConsts.toCommandLineFormat(doc.getAnnotation().doc()));
+ }
+ }
+ return modules;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationGenerator.java b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationGenerator.java
index c4f8cf3de7..6e0d572a48 100644
--- a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationGenerator.java
+++ b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationGenerator.java
@@ -39,9 +39,8 @@ public class SkylarkDocumentationGenerator {
public static void main(String[] args) {
if (checkArgs(args)) {
System.out.println("Generating Skylark documentation...");
- SkylarkDocumentationProcessor processor = new SkylarkDocumentationProcessor();
try {
- processor.generateDocumentation(args[0]);
+ SkylarkDocumentationProcessor.generateDocumentation(args[0]);
} catch (Throwable e) {
fail(e, true);
}
diff --git a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationProcessor.java b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationProcessor.java
index fa5933415c..816a46524b 100644
--- a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationProcessor.java
+++ b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationProcessor.java
@@ -13,389 +13,59 @@
// limitations under the License.
package com.google.devtools.build.docgen;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.io.Files;
-import com.google.devtools.build.docgen.SkylarkJavaInterfaceExplorer.SkylarkBuiltinMethod;
-import com.google.devtools.build.docgen.SkylarkJavaInterfaceExplorer.SkylarkJavaMethod;
-import com.google.devtools.build.docgen.SkylarkJavaInterfaceExplorer.SkylarkModuleDoc;
-import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
-import com.google.devtools.build.lib.rules.SkylarkModules;
-import com.google.devtools.build.lib.rules.SkylarkRuleContext;
-import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.Environment.NoneType;
-import com.google.devtools.build.lib.syntax.EvalUtils;
-import com.google.devtools.build.lib.syntax.FuncallExpression;
-import com.google.devtools.build.lib.syntax.MethodLibrary;
-import com.google.devtools.build.lib.syntax.SkylarkCallable;
-import com.google.devtools.build.lib.syntax.SkylarkList;
-import com.google.devtools.build.lib.syntax.SkylarkModule;
-import com.google.devtools.build.lib.syntax.SkylarkSignature;
-import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
-import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor.HackHackEitherList;
+import com.google.devtools.build.docgen.skylark.SkylarkBuiltinMethodDoc;
+import com.google.devtools.build.docgen.skylark.SkylarkJavaMethodDoc;
+import com.google.devtools.build.docgen.skylark.SkylarkModuleDoc;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
/**
* A class to assemble documentation for Skylark.
*/
-public class SkylarkDocumentationProcessor {
-
- private static final String TOP_LEVEL_ID = "_top_level";
-
- private static final boolean USE_TEMPLATE = false;
-
- @SkylarkModule(name = "Global objects, functions and modules",
- doc = "Objects, functions and modules registered in the global environment.")
- private static final class TopLevelModule {}
-
- static SkylarkModule getTopLevelModule() {
- return TopLevelModule.class.getAnnotation(SkylarkModule.class);
- }
+public final class SkylarkDocumentationProcessor {
+ private SkylarkDocumentationProcessor() {}
/**
* Generates the Skylark documentation to the given output directory.
*/
- public void generateDocumentation(String outputPath) throws IOException,
+ public static void generateDocumentation(String outputDir) throws IOException,
BuildEncyclopediaDocException {
- File skylarkDocPath = new File(outputPath);
- try (BufferedWriter bw = new BufferedWriter(
- Files.newWriter(skylarkDocPath, StandardCharsets.UTF_8))) {
- if (USE_TEMPLATE) {
- bw.write(SourceFileReader.readTemplateContents(DocgenConsts.SKYLARK_BODY_TEMPLATE,
- ImmutableMap.<String, String>of(
- DocgenConsts.VAR_SECTION_SKYLARK_BUILTIN, generateAllBuiltinDoc())));
- } else {
- bw.write(generateAllBuiltinDoc());
- }
- System.out.println("Skylark documentation generated: " + skylarkDocPath.getAbsolutePath());
- }
- }
-
- @VisibleForTesting
- Map<String, SkylarkModuleDoc> collectModules() {
- Map<String, SkylarkModuleDoc> modules = new TreeMap<>();
- Map<String, SkylarkModuleDoc> builtinModules = collectBuiltinModules();
- Map<SkylarkModule, Class<?>> builtinJavaObjects = collectBuiltinJavaObjects();
-
- modules.putAll(builtinModules);
- SkylarkJavaInterfaceExplorer explorer = new SkylarkJavaInterfaceExplorer();
- for (SkylarkModuleDoc builtinObject : builtinModules.values()) {
- // Check the return type for built-in functions, it can be a module previously not added.
- for (SkylarkBuiltinMethod builtinMethod : builtinObject.getBuiltinMethods().values()) {
- Class<?> type = builtinMethod.annotation.returnType();
- if (type.isAnnotationPresent(SkylarkModule.class)) {
- explorer.collect(type.getAnnotation(SkylarkModule.class), type, modules);
- }
- }
- explorer.collect(builtinObject.getAnnotation(), builtinObject.getClassObject(), modules);
- }
- for (Entry<SkylarkModule, Class<?>> builtinModule : builtinJavaObjects.entrySet()) {
- explorer.collect(builtinModule.getKey(), builtinModule.getValue(), modules);
- }
- return modules;
- }
-
- private String generateAllBuiltinDoc() {
- Map<String, SkylarkModuleDoc> modules = collectModules();
+ Map<String, SkylarkModuleDoc> modules = SkylarkDocumentationCollector.collectModules();
+ List<SkylarkModuleDoc> navModules = new ArrayList<>();
- StringBuilder sb = new StringBuilder();
// Generate the top level module first in the doc
- SkylarkModuleDoc topLevelModule = modules.remove(getTopLevelModule().name());
- generateModuleDoc(topLevelModule, sb);
+ SkylarkModuleDoc topLevelModule = modules.remove(
+ SkylarkDocumentationCollector.getTopLevelModule().name());
+ topLevelModule.setTitle("Globals");
+ writePage(outputDir, topLevelModule);
+ navModules.add(topLevelModule);
+
for (SkylarkModuleDoc module : modules.values()) {
if (module.getAnnotation().documented()) {
- sb.append("<hr>");
- generateModuleDoc(module, sb);
+ writePage(outputDir, module);
+ navModules.add(module);
}
}
- return sb.toString();
+ writeNavPage(outputDir, navModules);
}
- private void generateModuleDoc(SkylarkModuleDoc module, StringBuilder sb) {
- SkylarkModule annotation = module.getAnnotation();
- sb.append(String.format("<h2 id=\"modules.%s\">%s</h2>\n",
- getModuleId(annotation),
- annotation.name()))
- .append(annotation.doc())
- .append("\n");
- sb.append("<ul>");
- // Sort Java and Skylark builtin methods together. The map key is only used for sorting.
- TreeMap<String, Object> methodMap = new TreeMap<>();
- for (SkylarkJavaMethod method : module.getJavaMethods()) {
- methodMap.put(method.name + method.method.getParameterTypes().length, method);
- }
- for (SkylarkBuiltinMethod builtin : module.getBuiltinMethods().values()) {
- methodMap.put(builtin.annotation.name(), builtin);
- }
- for (Object object : methodMap.values()) {
- if (object instanceof SkylarkJavaMethod) {
- SkylarkJavaMethod method = (SkylarkJavaMethod) object;
- generateDirectJavaMethodDoc(annotation.name(), method.name, method.method,
- method.callable, sb);
- }
- if (object instanceof SkylarkBuiltinMethod) {
- generateBuiltinItemDoc(getModuleId(annotation), (SkylarkBuiltinMethod) object, sb);
- }
- }
- sb.append("</ul>");
+ private static void writePage(String outputDir, SkylarkModuleDoc module) throws IOException {
+ File skylarkDocPath = new File(outputDir + "/" + module.getName() + ".html");
+ Page page = TemplateEngine.newPage(DocgenConsts.SKYLARK_LIBRARY_TEMPLATE);
+ page.add("module", module);
+ page.write(skylarkDocPath);
}
- private String getModuleId(SkylarkModule annotation) {
- if (annotation == getTopLevelModule()) {
- return TOP_LEVEL_ID;
- } else {
- return annotation.name();
- }
- }
-
- private void generateBuiltinItemDoc(
- String moduleId, SkylarkBuiltinMethod method, StringBuilder sb) {
- SkylarkSignature annotation = method.annotation;
- if (!annotation.documented()) {
- return;
- }
- sb.append(String.format("<li><h3 id=\"modules.%s.%s\">%s</h3>\n",
- moduleId,
- annotation.name(),
- annotation.name()));
-
- if (BaseFunction.class.isAssignableFrom(method.fieldClass)) {
- sb.append(getSignature(moduleId, annotation));
- } else {
- if (!annotation.returnType().equals(Object.class)) {
- sb.append("<code>" + getTypeAnchor(annotation.returnType()) + "</code><br>");
- }
- }
-
- sb.append(annotation.doc() + "\n");
- printParams(moduleId, annotation, sb);
- }
-
- // Elide self parameter from mandatoryPositionals in class methods.
- private static Param[] adjustedMandatoryPositionals(SkylarkSignature annotation) {
- Param[] mandatoryPos = annotation.mandatoryPositionals();
- if (mandatoryPos.length > 0
- && annotation.objectType() != Object.class
- && !FuncallExpression.isNamespace(annotation.objectType())) {
- // Skip the self parameter, which is the first mandatory positional parameter.
- return Arrays.copyOfRange(mandatoryPos, 1, mandatoryPos.length);
- } else {
- return mandatoryPos;
- }
- }
-
- private void printParams(String moduleId, SkylarkSignature annotation, StringBuilder sb) {
- Param[] mandatoryPos = adjustedMandatoryPositionals(annotation);
- Param[] optionalPos = annotation.optionalPositionals();
- Param[] optionalKey = annotation.optionalNamedOnly();
- Param[] mandatoryKey = annotation.mandatoryNamedOnly();
- Param[] star = annotation.extraPositionals();
- Param[] starStar = annotation.extraKeywords();
-
- if (mandatoryPos.length + optionalPos.length + optionalKey.length + mandatoryKey.length
- + star.length + starStar.length > 0) {
- sb.append("<h4>Parameters</h4>\n");
- printParams(moduleId, annotation.name(), mandatoryPos, sb);
- printParams(moduleId, annotation.name(), optionalPos, sb);
- printParams(moduleId, annotation.name(), star, sb);
- printParams(moduleId, annotation.name(), mandatoryKey, sb);
- printParams(moduleId, annotation.name(), optionalKey, sb);
- printParams(moduleId, annotation.name(), starStar, sb);
- } else {
- sb.append("<br/>\n");
- }
- }
-
- private void generateDirectJavaMethodDoc(String objectName, String methodName,
- Method method, SkylarkCallable annotation, StringBuilder sb) {
- if (!annotation.documented()) {
- return;
- }
- if (annotation.doc().isEmpty()) {
- throw new RuntimeException(String.format(
- "empty SkylarkCallable.doc() for object %s, method %s", objectName, methodName));
- }
-
- sb.append(String.format("<li><h3 id=\"modules.%s.%s\">%s</h3>\n%s\n",
- objectName,
- methodName,
- methodName,
- getSignature(objectName, methodName, method)))
- .append(annotation.doc())
- .append(getReturnTypeExtraMessage(annotation))
- .append("\n");
- }
-
- private String getReturnTypeExtraMessage(SkylarkCallable annotation) {
- if (annotation.allowReturnNones()) {
- return " May return <code>None</code>.\n";
- }
- return "";
- }
-
- private String getSignature(String objectName, String methodName, Method method) {
- String args = method.getAnnotation(SkylarkCallable.class).structField()
- ? "" : "(" + getParameterString(method) + ")";
-
- return String.format("<code>%s %s.%s%s</code><br>",
- getTypeAnchor(method.getReturnType()), objectName, methodName, args);
- }
-
- private String getSignature(String objectName, SkylarkSignature method) {
- List<String> argList = new ArrayList<>();
- for (Param param : adjustedMandatoryPositionals(method)) {
- argList.add(param.name());
- }
- for (Param param : method.optionalPositionals()) {
- argList.add(formatOptionalParameter(param));
- }
- for (Param param : method.extraPositionals()) {
- argList.add("*" + param.name());
- }
- if (argList.size() > 0 && method.extraPositionals().length == 0
- && (method.optionalNamedOnly().length > 0 || method.mandatoryNamedOnly().length > 0)) {
- argList.add("*");
- }
- for (Param param : method.mandatoryNamedOnly()) {
- argList.add(param.name());
- }
- for (Param param : method.optionalNamedOnly()) {
- argList.add(formatOptionalParameter(param));
- }
- for (Param param : method.extraKeywords()) {
- argList.add("**" + param.name());
- }
- String args = "(" + Joiner.on(", ").join(argList) + ")";
- if (!objectName.equals(TOP_LEVEL_ID)) {
- return String.format("<code>%s %s.%s%s</code><br>\n",
- getTypeAnchor(method.returnType()), objectName, method.name(), args);
- } else {
- return String.format("<code>%s %s%s</code><br>\n",
- getTypeAnchor(method.returnType()), method.name(), args);
- }
- }
-
- private String formatOptionalParameter(Param param) {
- String defaultValue = param.defaultValue();
-
- return String.format("%s=%s", param.name(),
- (defaultValue == null || defaultValue.isEmpty()) ? "&hellip;" : defaultValue);
- }
-
- private String getTypeAnchor(Class<?> returnType, Class<?> generic1) {
- return getTypeAnchor(returnType) + " of " + getTypeAnchor(generic1) + "s";
- }
-
- private String getTypeAnchor(Class<?> type) {
- if (type.equals(Boolean.class) || type.equals(boolean.class)) {
- return "<a class=\"anchor\" href=\"#modules._top_level.bool\">bool</a>";
- } else if (type.equals(String.class)) {
- return "<a class=\"anchor\" href=\"#modules.string\">string</a>";
- } else if (Map.class.isAssignableFrom(type)) {
- return "<a class=\"anchor\" href=\"#modules.dict\">dict</a>";
- } else if (List.class.isAssignableFrom(type) || SkylarkList.class.isAssignableFrom(type)
- || type == HackHackEitherList.class) {
- // Annotated Java methods can return simple java.util.Lists (which get auto-converted).
- return "<a class=\"anchor\" href=\"#modules.list\">list</a>";
- } else if (type.equals(Void.TYPE) || type.equals(NoneType.class)) {
- return "<a class=\"anchor\" href=\"#modules." + TOP_LEVEL_ID + ".None\">None</a>";
- } else if (type.isAnnotationPresent(SkylarkModule.class)) {
- // TODO(bazel-team): this can produce dead links for types don't show up in the doc.
- // The correct fix is to generate those types (e.g. SkylarkFileType) too.
- String module = type.getAnnotation(SkylarkModule.class).name();
- return "<a class=\"anchor\" href=\"#modules." + module + "\">" + module + "</a>";
- } else {
- return EvalUtils.getDataTypeNameFromClass(type);
- }
- }
-
- private String getParameterString(Method method) {
- return Joiner.on(", ").join(Iterables.transform(
- ImmutableList.copyOf(method.getParameterTypes()), new Function<Class<?>, String>() {
- @Override
- public String apply(Class<?> input) {
- return getTypeAnchor(input);
- }
- }));
- }
-
- private void printParams(String moduleId, String methodName,
- Param[] params, StringBuilder sb) {
- if (params.length > 0) {
- sb.append("<ul>\n");
- for (Param param : params) {
- String paramType = param.type().equals(Object.class) ? ""
- : (param.generic1().equals(Object.class)
- ? " (" + getTypeAnchor(param.type()) + ")"
- : " (" + getTypeAnchor(param.type(), param.generic1()) + ")");
- sb.append(String.format("\t<li id=\"modules.%s.%s.%s\"><code>%s%s</code>: ",
- moduleId,
- methodName,
- param.name(),
- param.name(),
- paramType))
- .append(param.doc())
- .append("\n\t</li>\n");
- }
- sb.append("</ul>\n");
- }
- }
-
- private Map<String, SkylarkModuleDoc> collectBuiltinModules() {
- Map<String, SkylarkModuleDoc> modules = new HashMap<>();
- collectBuiltinDoc(modules, Environment.class.getDeclaredFields());
- collectBuiltinDoc(modules, MethodLibrary.class.getDeclaredFields());
- for (Class<?> moduleClass : SkylarkModules.MODULES) {
- collectBuiltinDoc(modules, moduleClass.getDeclaredFields());
- }
- return modules;
- }
-
- private Map<SkylarkModule, Class<?>> collectBuiltinJavaObjects() {
- Map<SkylarkModule, Class<?>> modules = new HashMap<>();
- collectBuiltinModule(modules, SkylarkRuleContext.class);
- collectBuiltinModule(modules, TransitiveInfoCollection.class);
- return modules;
- }
-
- /**
- * Returns the top level modules and functions with their documentation in a command-line
- * printable format.
- */
- public Map<String, String> collectTopLevelModules() {
- Map<String, String> modules = new TreeMap<>();
- for (SkylarkModuleDoc doc : collectBuiltinModules().values()) {
- if (doc.getAnnotation() == getTopLevelModule()) {
- for (Map.Entry<String, SkylarkBuiltinMethod> entry : doc.getBuiltinMethods().entrySet()) {
- if (entry.getValue().annotation.documented()) {
- modules.put(entry.getKey(),
- DocgenConsts.toCommandLineFormat(entry.getValue().annotation.doc()));
- }
- }
- } else {
- modules.put(doc.getAnnotation().name(),
- DocgenConsts.toCommandLineFormat(doc.getAnnotation().doc()));
- }
- }
- return modules;
+ private static void writeNavPage(String outputDir, List<SkylarkModuleDoc> navModules)
+ throws IOException {
+ File navFile = new File(outputDir + "/" + "skylark-nav.html");
+ Page page = TemplateEngine.newPage(DocgenConsts.SKYLARK_NAV_TEMPLATE);
+ page.add("modules", navModules);
+ page.write(navFile);
}
/**
@@ -404,9 +74,10 @@ public class SkylarkDocumentationProcessor {
* method in the module.<br>
* Returns null if no Skylark object is found.
*/
- public String getCommandLineAPIDoc(String[] params) {
- Map<String, SkylarkModuleDoc> modules = collectModules();
- SkylarkModuleDoc toplevelModuleDoc = modules.get(getTopLevelModule().name());
+ public static String getCommandLineAPIDoc(String[] params) {
+ Map<String, SkylarkModuleDoc> modules = SkylarkDocumentationCollector.collectModules();
+ SkylarkModuleDoc toplevelModuleDoc = modules.get(
+ SkylarkDocumentationCollector.getTopLevelModule().name());
if (modules.containsKey(params[0])) {
// Top level module
SkylarkModuleDoc module = modules.get(params[0]);
@@ -415,12 +86,12 @@ public class SkylarkDocumentationProcessor {
StringBuilder sb = new StringBuilder();
sb.append(moduleName).append("\n\t").append(module.getAnnotation().doc()).append("\n");
// Print the signature of all built-in methods
- for (SkylarkBuiltinMethod method : module.getBuiltinMethods().values()) {
- printBuiltinFunctionDoc(moduleName, method.annotation, sb);
+ for (SkylarkBuiltinMethodDoc method : module.getBuiltinMethods().values()) {
+ printBuiltinFunctionDoc(moduleName, method, sb);
}
// Print all Java methods
- for (SkylarkJavaMethod method : module.getJavaMethods()) {
- printJavaFunctionDoc(moduleName, method, sb);
+ for (SkylarkJavaMethodDoc method : module.getJavaMethods()) {
+ printJavaFunctionDoc(method, sb);
}
return DocgenConsts.toCommandLineFormat(sb.toString());
} else {
@@ -433,67 +104,42 @@ public class SkylarkDocumentationProcessor {
return null;
}
- private String getFunctionDoc(String moduleName, String methodName, SkylarkModuleDoc module) {
+ private static String getFunctionDoc(String moduleName, String methodName,
+ SkylarkModuleDoc module) {
if (module.getBuiltinMethods().containsKey(methodName)) {
// Create the doc for the built-in function
- SkylarkBuiltinMethod method = module.getBuiltinMethods().get(methodName);
+ SkylarkBuiltinMethodDoc method = module.getBuiltinMethods().get(methodName);
StringBuilder sb = new StringBuilder();
- printBuiltinFunctionDoc(moduleName, method.annotation, sb);
- printParams(moduleName, method.annotation, sb);
+ printBuiltinFunctionDoc(moduleName, method, sb);
+ sb.append(method.getParams());
return DocgenConsts.removeDuplicatedNewLines(DocgenConsts.toCommandLineFormat(sb.toString()));
} else {
// Search if there are matching Java functions
StringBuilder sb = new StringBuilder();
boolean foundMatchingMethod = false;
- for (SkylarkJavaMethod method : module.getJavaMethods()) {
- if (method.name.equals(methodName)) {
- printJavaFunctionDoc(moduleName, method, sb);
+ for (SkylarkJavaMethodDoc method : module.getJavaMethods()) {
+ if (method.getName().equals(methodName)) {
+ printJavaFunctionDoc(method, sb);
foundMatchingMethod = true;
}
}
if (foundMatchingMethod) {
- return DocgenConsts.toCommandLineFormat(sb.toString());
+ return DocgenConsts.toCommandLineFormat(sb.toString());
}
}
return null;
}
- private void printBuiltinFunctionDoc(
- String moduleName, SkylarkSignature annotation, StringBuilder sb) {
+ private static void printBuiltinFunctionDoc(String moduleName, SkylarkBuiltinMethodDoc method,
+ StringBuilder sb) {
if (moduleName != null) {
sb.append(moduleName).append(".");
}
- sb.append(annotation.name()).append("\n\t").append(annotation.doc()).append("\n");
- }
-
- private void printJavaFunctionDoc(String moduleName, SkylarkJavaMethod method, StringBuilder sb) {
- sb.append(getSignature(moduleName, method.name, method.method))
- .append("\t").append(method.callable.doc()).append("\n");
- }
-
- private void collectBuiltinModule(
- Map<SkylarkModule, Class<?>> modules, Class<?> moduleClass) {
- if (moduleClass.isAnnotationPresent(SkylarkModule.class)) {
- SkylarkModule skylarkModule = moduleClass.getAnnotation(SkylarkModule.class);
- modules.put(skylarkModule, moduleClass);
- }
+ sb.append(method.getName()).append("\n\t").append(method.getDocumentation()).append("\n");
}
- private void collectBuiltinDoc(Map<String, SkylarkModuleDoc> modules, Field[] fields) {
- for (Field field : fields) {
- if (field.isAnnotationPresent(SkylarkSignature.class)) {
- SkylarkSignature skylarkSignature = field.getAnnotation(SkylarkSignature.class);
- Class<?> moduleClass = skylarkSignature.objectType();
- SkylarkModule skylarkModule = moduleClass.equals(Object.class)
- ? getTopLevelModule()
- : moduleClass.getAnnotation(SkylarkModule.class);
- if (!modules.containsKey(skylarkModule.name())) {
- modules.put(skylarkModule.name(), new SkylarkModuleDoc(skylarkModule, moduleClass));
- }
- modules.get(skylarkModule.name()).getBuiltinMethods()
- .put(skylarkSignature.name(),
- new SkylarkBuiltinMethod(skylarkSignature, field.getType()));
- }
- }
+ private static void printJavaFunctionDoc(SkylarkJavaMethodDoc method, StringBuilder sb) {
+ sb.append(method.getSignature())
+ .append("\t").append(method.getDocumentation()).append("\n");
}
}
diff --git a/src/main/java/com/google/devtools/build/docgen/SkylarkJavaInterfaceExplorer.java b/src/main/java/com/google/devtools/build/docgen/SkylarkJavaInterfaceExplorer.java
deleted file mode 100644
index 1118991d66..0000000000
--- a/src/main/java/com/google/devtools/build/docgen/SkylarkJavaInterfaceExplorer.java
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2014 Google Inc. All rights reserved.
-//
-// 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.devtools.build.docgen;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.syntax.FuncallExpression;
-import com.google.devtools.build.lib.syntax.SkylarkCallable;
-import com.google.devtools.build.lib.syntax.SkylarkModule;
-import com.google.devtools.build.lib.syntax.SkylarkSignature;
-import com.google.devtools.build.lib.util.StringUtilities;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * A helper class to collect all the Java objects / methods reachable from Skylark.
- */
-public class SkylarkJavaInterfaceExplorer {
- /**
- * A class representing a Java method callable from Skylark with annotation.
- */
- static final class SkylarkJavaMethod {
- public final String name;
- public final Method method;
- public final SkylarkCallable callable;
-
- private String getName(Method method, SkylarkCallable callable) {
- return callable.name().isEmpty()
- ? StringUtilities.toPythonStyleFunctionName(method.getName())
- : callable.name();
- }
-
- SkylarkJavaMethod(Method method, SkylarkCallable callable) {
- this.name = getName(method, callable);
- this.method = method;
- this.callable = callable;
- }
- }
-
- /**
- * A class representing a Skylark built-in object or method.
- */
- static final class SkylarkBuiltinMethod {
- public final SkylarkSignature annotation;
- public final Class<?> fieldClass;
-
- public SkylarkBuiltinMethod(SkylarkSignature annotation, Class<?> fieldClass) {
- this.annotation = annotation;
- this.fieldClass = fieldClass;
- }
- }
-
- /**
- * A class representing a Skylark built-in object with its {@link SkylarkSignature} annotation
- * and the {@link SkylarkCallable} methods it might have.
- */
- static final class SkylarkModuleDoc {
-
- private final SkylarkModule module;
- private final Class<?> classObject;
- private final Map<String, SkylarkBuiltinMethod> builtin;
- private ArrayList<SkylarkJavaMethod> methods = null;
-
- SkylarkModuleDoc(SkylarkModule module, Class<?> classObject) {
- this.module = Preconditions.checkNotNull(
- module, "Class has to be annotated with SkylarkModule: %s", classObject);
- this.classObject = classObject;
- this.builtin = new TreeMap<>();
- }
-
- SkylarkModule getAnnotation() {
- return module;
- }
-
- Class<?> getClassObject() {
- return classObject;
- }
-
- private boolean javaMethodsNotCollected() {
- return methods == null;
- }
-
- private void setJavaMethods(ArrayList<SkylarkJavaMethod> methods) {
- this.methods = methods;
- }
-
- Map<String, SkylarkBuiltinMethod> getBuiltinMethods() {
- return builtin;
- }
-
- ArrayList<SkylarkJavaMethod> getJavaMethods() {
- return methods;
- }
- }
-
- /**
- * Collects and returns all the Java objects reachable in Skylark from (and including)
- * firstClassObject with the corresponding SkylarkSignature annotations.
- *
- * <p>Note that the {@link SkylarkSignature} annotation for firstClassObject - firstAnnotation -
- * is also an input parameter, because some top level Skylark built-in objects and methods
- * are not annotated on the class, but on a field referencing them.
- */
- void collect(SkylarkModule firstModule, Class<?> firstClass,
- Map<String, SkylarkModuleDoc> modules) {
- Set<Class<?>> processedClasses = new HashSet<>();
- LinkedList<Class<?>> classesToProcess = new LinkedList<>();
- Map<Class<?>, SkylarkModule> annotations = new HashMap<>();
-
- classesToProcess.addLast(firstClass);
- annotations.put(firstClass, firstModule);
-
- while (!classesToProcess.isEmpty()) {
- Class<?> classObject = classesToProcess.removeFirst();
- SkylarkModule annotation = annotations.get(classObject);
- processedClasses.add(classObject);
- if (!modules.containsKey(annotation.name())) {
- modules.put(annotation.name(), new SkylarkModuleDoc(annotation, classObject));
- }
- SkylarkModuleDoc module = modules.get(annotation.name());
-
- if (module.javaMethodsNotCollected()) {
- ImmutableMap<Method, SkylarkCallable> methods =
- FuncallExpression.collectSkylarkMethodsWithAnnotation(classObject);
- ArrayList<SkylarkJavaMethod> methodList = new ArrayList<>();
- for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
- methodList.add(new SkylarkJavaMethod(entry.getKey(), entry.getValue()));
- }
- module.setJavaMethods(methodList);
-
- for (Map.Entry<Method, SkylarkCallable> method : methods.entrySet()) {
- Class<?> returnClass = method.getKey().getReturnType();
- if (returnClass.isAnnotationPresent(SkylarkModule.class)
- && !processedClasses.contains(returnClass)) {
- classesToProcess.addLast(returnClass);
- annotations.put(returnClass, returnClass.getAnnotation(SkylarkModule.class));
- }
- }
- }
- }
- }
-}
diff --git a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkBuiltinMethodDoc.java b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkBuiltinMethodDoc.java
new file mode 100644
index 0000000000..553cd1141f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkBuiltinMethodDoc.java
@@ -0,0 +1,97 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen.skylark;
+
+import com.google.devtools.build.lib.syntax.BaseFunction;
+import com.google.devtools.build.lib.syntax.SkylarkSignature;
+import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class representing a Skylark built-in object or method.
+ */
+public final class SkylarkBuiltinMethodDoc extends SkylarkMethodDoc {
+ private final SkylarkModuleDoc module;
+ private final SkylarkSignature annotation;
+ private final Class<?> fieldClass;
+ private List<SkylarkParamDoc> params;
+
+ public SkylarkBuiltinMethodDoc(SkylarkModuleDoc module, SkylarkSignature annotation,
+ Class<?> fieldClass) {
+ this.module = module;
+ this.annotation = annotation;
+ this.fieldClass = fieldClass;
+ this.params = new ArrayList<>();
+ processParams();
+ }
+
+ public SkylarkSignature getAnnotation() {
+ return annotation;
+ }
+
+ @Override
+ public boolean documented() {
+ return annotation.documented();
+ }
+
+ @Override
+ public String getName() {
+ return annotation.name();
+ }
+
+ @Override
+ public String getDocumentation() {
+ return annotation.doc();
+ }
+
+ /**
+ * Returns a string representing the method signature with links to the types if
+ * available.
+ *
+ * <p>If the built-in method is a function, the construct the method signature. Otherwise,
+ * return a string containing the return type of the method.
+ */
+ @Override
+ public String getSignature() {
+ if (BaseFunction.class.isAssignableFrom(fieldClass)) {
+ return getSignature(module.getName(), annotation);
+ }
+ if (!annotation.returnType().equals(Object.class)) {
+ return getTypeAnchor(annotation.returnType());
+ }
+ return "";
+ }
+
+ @Override
+ public List<SkylarkParamDoc> getParams() {
+ return params;
+ }
+
+ private void processParams() {
+ processParams(adjustedMandatoryPositionals(annotation));
+ processParams(annotation.optionalPositionals());
+ processParams(annotation.optionalNamedOnly());
+ processParams(annotation.mandatoryNamedOnly());
+ processParams(annotation.extraPositionals());
+ processParams(annotation.extraKeywords());
+ }
+
+ private void processParams(Param[] params) {
+ for (Param param : params) {
+ this.params.add(new SkylarkParamDoc(this, param));
+ }
+ }
+}
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
new file mode 100644
index 0000000000..065ab68c0c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkDoc.java
@@ -0,0 +1,85 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen.skylark;
+
+import com.google.devtools.build.lib.syntax.Environment.NoneType;
+import com.google.devtools.build.lib.syntax.EvalUtils;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.SkylarkModule;
+import com.google.devtools.build.lib.syntax.SkylarkSignature;
+import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
+import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor.HackHackEitherList;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstract class for containing documentation for a Skylark syntactic entity.
+ */
+abstract class SkylarkDoc {
+ protected static final String TOP_LEVEL_ID = "globals";
+
+ /**
+ * Returns a string containing the name of the entity being documented.
+ */
+ public abstract String getName();
+
+ /**
+ * Returns a string containing the HTML documentation of the entity being
+ * documented.
+ */
+ public abstract String getDocumentation();
+
+ protected String getTypeAnchor(Class<?> returnType, Class<?> generic1) {
+ return getTypeAnchor(returnType) + " of " + getTypeAnchor(generic1) + "s";
+ }
+
+ protected String getTypeAnchor(Class<?> type) {
+ if (type.equals(Boolean.class) || type.equals(boolean.class)) {
+ return "<a class=\"anchor\" href=\"" + TOP_LEVEL_ID + ".html#bool\">bool</a>";
+ } else if (type.equals(String.class)) {
+ return "<a class=\"anchor\" href=\"string.html\">string</a>";
+ } else if (Map.class.isAssignableFrom(type)) {
+ return "<a class=\"anchor\" href=\"dict.html\">dict</a>";
+ } else if (List.class.isAssignableFrom(type) || SkylarkList.class.isAssignableFrom(type)
+ || type == HackHackEitherList.class) {
+ // Annotated Java methods can return simple java.util.Lists (which get auto-converted).
+ return "<a class=\"anchor\" href=\"list.html\">list</a>";
+ } else if (type.equals(Void.TYPE) || type.equals(NoneType.class)) {
+ return "<a class=\"anchor\" href=\"" + TOP_LEVEL_ID + ".html#None\">None</a>";
+ } else if (type.isAnnotationPresent(SkylarkModule.class)) {
+ // TODO(bazel-team): this can produce dead links for types don't show up in the doc.
+ // The correct fix is to generate those types (e.g. SkylarkFileType) too.
+ String module = type.getAnnotation(SkylarkModule.class).name();
+ return "<a class=\"anchor\" href=\"" + module + ".html\">" + module + "</a>";
+ } else {
+ return EvalUtils.getDataTypeNameFromClass(type);
+ }
+ }
+
+ // Elide self parameter from mandatoryPositionals in class methods.
+ protected static Param[] adjustedMandatoryPositionals(SkylarkSignature annotation) {
+ Param[] mandatoryPos = annotation.mandatoryPositionals();
+ if (mandatoryPos.length > 0
+ && annotation.objectType() != Object.class
+ && !FuncallExpression.isNamespace(annotation.objectType())) {
+ // Skip the self parameter, which is the first mandatory positional parameter.
+ return Arrays.copyOfRange(mandatoryPos, 1, mandatoryPos.length);
+ } else {
+ return mandatoryPos;
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkJavaMethodDoc.java b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkJavaMethodDoc.java
new file mode 100644
index 0000000000..d4212f7dc7
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkJavaMethodDoc.java
@@ -0,0 +1,71 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen.skylark;
+
+import com.google.devtools.build.lib.syntax.SkylarkCallable;
+import com.google.devtools.build.lib.util.StringUtilities;
+
+import java.lang.reflect.Method;
+
+/**
+ * A class representing a Java method callable from Skylark with annotation.
+ */
+public final class SkylarkJavaMethodDoc extends SkylarkMethodDoc {
+ private final SkylarkModuleDoc module;
+ private final String name;
+ private final Method method;
+ private final SkylarkCallable callable;
+
+ public SkylarkJavaMethodDoc(SkylarkModuleDoc module, Method method,
+ SkylarkCallable callable) {
+ this.module = module;
+ this.name = callable.name().isEmpty()
+ ? StringUtilities.toPythonStyleFunctionName(method.getName())
+ : callable.name();
+ this.method = method;
+ this.callable = callable;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ @Override
+ public boolean documented() {
+ return callable.documented();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDocumentation() {
+ return callable.doc();
+ }
+
+ @Override
+ public String getSignature() {
+ return getSignature(module.getName(), name, method);
+ }
+
+ @Override
+ public String getReturnTypeExtraMessage() {
+ if (callable.allowReturnNones()) {
+ return " May return <code>None</code>.\n";
+ }
+ return "";
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkMethodDoc.java b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkMethodDoc.java
new file mode 100644
index 0000000000..294634f90d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkMethodDoc.java
@@ -0,0 +1,116 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen.skylark;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.syntax.SkylarkCallable;
+import com.google.devtools.build.lib.syntax.SkylarkSignature;
+import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An abstract class containing documentation for a Skylark method.
+ */
+abstract class SkylarkMethodDoc extends SkylarkDoc {
+ /**
+ * Returns whether the Skylark method is documented.
+ */
+ public abstract boolean documented();
+
+ /**
+ * Returns a string representing the method signature of the Skylark method, which contains
+ * HTML links to the documentation of parameter types if available.
+ */
+ public abstract String getSignature();
+
+ /**
+ * Returns a string containing additional documentation about the method's return value.
+ *
+ * <p>Returns an empty string by default.
+ */
+ public String getReturnTypeExtraMessage() {
+ return "";
+ }
+
+ /**
+ * Returns a list containing the documentation for each of the method's parameters.
+ */
+ public List<SkylarkParamDoc> getParams() {
+ return ImmutableList.<SkylarkParamDoc>of();
+ }
+
+ private String getParameterString(Method method) {
+ return Joiner.on(", ").join(Iterables.transform(
+ ImmutableList.copyOf(method.getParameterTypes()), new Function<Class<?>, String>() {
+ @Override
+ public String apply(Class<?> input) {
+ return getTypeAnchor(input);
+ }
+ }));
+ }
+
+ protected String getSignature(String objectName, String methodName, Method method) {
+ String args = method.getAnnotation(SkylarkCallable.class).structField()
+ ? "" : "(" + getParameterString(method) + ")";
+
+ return String.format("%s %s.%s%s",
+ getTypeAnchor(method.getReturnType()), objectName, methodName, args);
+ }
+
+ protected String getSignature(String objectName, SkylarkSignature method) {
+ List<String> argList = new ArrayList<>();
+ for (Param param : adjustedMandatoryPositionals(method)) {
+ argList.add(param.name());
+ }
+ for (Param param : method.optionalPositionals()) {
+ argList.add(formatOptionalParameter(param));
+ }
+ for (Param param : method.extraPositionals()) {
+ argList.add("*" + param.name());
+ }
+ if (argList.size() > 0 && method.extraPositionals().length == 0
+ && (method.optionalNamedOnly().length > 0 || method.mandatoryNamedOnly().length > 0)) {
+ argList.add("*");
+ }
+ for (Param param : method.mandatoryNamedOnly()) {
+ argList.add(param.name());
+ }
+ for (Param param : method.optionalNamedOnly()) {
+ argList.add(formatOptionalParameter(param));
+ }
+ for (Param param : method.extraKeywords()) {
+ argList.add("**" + param.name());
+ }
+ String args = "(" + Joiner.on(", ").join(argList) + ")";
+ if (!objectName.equals(TOP_LEVEL_ID)) {
+ return String.format("%s %s.%s%s\n",
+ getTypeAnchor(method.returnType()), objectName, method.name(), args);
+ } else {
+ return String.format("%s %s%s\n",
+ getTypeAnchor(method.returnType()), method.name(), args);
+ }
+ }
+
+ private String formatOptionalParameter(Param param) {
+ String defaultValue = param.defaultValue();
+ return String.format("%s=%s", param.name(),
+ (defaultValue == null || defaultValue.isEmpty()) ? "&hellip;" : defaultValue);
+ }
+}
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
new file mode 100644
index 0000000000..881f932e14
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkModuleDoc.java
@@ -0,0 +1,98 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen.skylark;
+
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.syntax.SkylarkModule;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A class representing a Skylark built-in object with its {@link SkylarkSignature} annotation
+ * and the {@link SkylarkCallable} methods it might have.
+ */
+public final class SkylarkModuleDoc extends SkylarkDoc {
+ private final SkylarkModule module;
+ private final Class<?> classObject;
+ private final Map<String, SkylarkBuiltinMethodDoc> builtinMethodMap;
+ private ArrayList<SkylarkJavaMethodDoc> javaMethods;
+ private TreeMap<String, SkylarkMethodDoc> methodMap;
+ private String title;
+
+ public SkylarkModuleDoc(SkylarkModule module, Class<?> classObject) {
+ this.module = Preconditions.checkNotNull(
+ module, "Class has to be annotated with SkylarkModule: %s", classObject);
+ this.classObject = classObject;
+ this.builtinMethodMap = new TreeMap<>();
+ this.methodMap = new TreeMap<>();
+ this.javaMethods = new ArrayList<>();
+ this.title = module.name();
+ }
+
+ @Override
+ public String getName() {
+ return module.name();
+ }
+
+ @Override
+ public String getDocumentation() {
+ return module.doc();
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public SkylarkModule getAnnotation() {
+ return module;
+ }
+
+ public Class<?> getClassObject() {
+ return classObject;
+ }
+
+ public void addMethod(SkylarkBuiltinMethodDoc method) {
+ methodMap.put(method.getName(), method);
+ builtinMethodMap.put(method.getName(), method);
+ }
+
+ public void addMethod(SkylarkJavaMethodDoc method) {
+ methodMap.put(method.getName() + "$" + method.getMethod().getParameterTypes().length, method);
+ javaMethods.add(method);
+ }
+
+ public boolean javaMethodsNotCollected() {
+ return javaMethods.isEmpty();
+ }
+
+ public Map<String, SkylarkBuiltinMethodDoc> getBuiltinMethods() {
+ return builtinMethodMap;
+ }
+
+ public List<SkylarkJavaMethodDoc> getJavaMethods() {
+ return javaMethods;
+ }
+
+ public Collection<SkylarkMethodDoc> getMethods() {
+ return methodMap.values();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkParamDoc.java b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkParamDoc.java
new file mode 100644
index 0000000000..d733e7de65
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/skylark/SkylarkParamDoc.java
@@ -0,0 +1,61 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// 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.devtools.build.docgen.skylark;
+
+import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
+
+/**
+ * A class containing the documentation for a Skylark method parameter.
+ */
+public final class SkylarkParamDoc extends SkylarkDoc {
+ private SkylarkMethodDoc method;
+ private Param param;
+
+ public SkylarkParamDoc(SkylarkMethodDoc method, Param param) {
+ this.method = method;
+ this.param = param;
+ }
+
+ /**
+ * Returns the string representing the type of this parameter with the link to the
+ * documentation for the type if available.
+ *
+ * <p>If the parameter type is Object, then returns the empty string. If the parameter
+ * type is not a generic, then this method returns a string representing the type name
+ * with a link to the documentation for the type if available. If the parameter type
+ * is a generic, then this method returns a string "CONTAINER of TYPE".
+ */
+ public String getType() {
+ if (param.type().equals(Object.class)) {
+ return "";
+ }
+ if (param.generic1().equals(Object.class)) {
+ return getTypeAnchor(param.type());
+ } else {
+ return getTypeAnchor(param.type(), param.generic1());
+ }
+ }
+
+ public SkylarkMethodDoc getMethod() {
+ return method;
+ }
+
+ public String getName() {
+ return param.name();
+ }
+
+ public String getDocumentation() {
+ return param.doc();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm b/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
index 8e841a626d..3eba02b93e 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
@@ -20,7 +20,7 @@ ${LEFT_PANEL}
<h3>Concepts and terminology</h3>
<table class="layout"><tr><td>
- <ul class="toc">
+ <ul class="be-toc">
<li><a href="#common-definitions">Common definitions</a>:
<ul>
<li><a href="#sh-tokenization">Bourne shell tokenization</a></li>
@@ -34,9 +34,9 @@ ${LEFT_PANEL}
</li>
</ul>
</td><td>
- <ul class="toc">
+ <ul class="be-toc">
<li><a href="#make_variables">"Make" variables</a>
- <ul class="toc">
+ <ul class="be-toc">
<li><a href="#make-var-substitution">"Make" variable substitution</a></li>
<li><a href="#predefined_variables">Predefined variables</a></li>
@@ -44,7 +44,7 @@ ${LEFT_PANEL}
<li><a href="#predefined-python-variables">Predefined Python Variables</a></li>
</ul>
</td><td>
- <ul class="toc">
+ <ul class="be-toc">
<li><a href="#load">load</a></li>
<li><a href="#package">package</a></li>
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/skylark-body.html b/src/main/java/com/google/devtools/build/docgen/templates/skylark-body.html
deleted file mode 100644
index 5becb1a7cd..0000000000
--- a/src/main/java/com/google/devtools/build/docgen/templates/skylark-body.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<html>
-<head>
- <title>Skylark documentation</title>
-
- <style type="text/css" id="internalStyle">
- h1 { margin-bottom: 5px; }
- .toc { margin: 0px; }
- ul li { margin-bottom: 1em; }
- ul.toc li { margin-bottom: 0px; }
- em.harmful { color: red; }
-
- .deprecated { text-decoration: line-through; }
- .discouraged { text-decoration: line-through; }
-
- #rules { width: 980px; border-collapse: collapse; }
- #rules td { border-top: 1px solid gray; padding: 4px; vertical-align: top; }
- #rules th { text-align: left; padding: 4px; }
-
- table.layout { width: 980px; }
- table.layout td { vertical-align: top; }
-
- #maintainer { text-align: right; }
-
- dt {
- font-weight: bold;
- margin-top: 0.5em;
- margin-bottom: 0.5em;
- }
- dd dt {
- font-weight: normal;
- text-decoration: underline;
- color: gray;
- }
- a.anchor {
- color:inherit;
- text-decoration: none;
- }
- </style>
-
- <style type="text/css">
- .rule-signature {
- color: #006000;
- font-family: monospace;
- }
- </style>
-</head>
-
-<body>
-<h1>Skylark documentation</h1>
-
-<h2>Built-in objects and functions in the Skylark Environment</h2>
-
-
-${SECTION_BUILTIN}
-
-</body>
-</html>
-
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm b/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm
new file mode 100644
index 0000000000..0cd39e4969
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm
@@ -0,0 +1,58 @@
+<h1 id="modules.${module.name}">${module.title}</h1>
+
+${module.documentation}
+
+#if (!$module.methods.isEmpty())
+<div class="toc">
+ <h1>Methods</h1>
+ <ul>
+ #foreach ($method in $module.methods)
+ #if ($method.documented())
+ <li><a href="#${method.name}">${method.name}</a></li>
+ #end
+ #end
+ </ul>
+</div>
+#end
+#foreach ($method in $module.methods)
+ #if ($method.documented())
+ <h2 id="${method.name}">${method.name}</h2>
+ #if (!$method.signature.isEmpty())
+ <p><pre>${method.signature}</pre></p>
+ #end
+
+ ${method.documentation}
+
+ #if (!$method.params.isEmpty())
+ <h3>Parameters</h3>
+ <table class="table table-bordered table-condensed table-params">
+ <colgroup>
+ <col class="col-param">
+ <col class="param-description">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>Parameter</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ #foreach ($param in $method.params)
+ <tr>
+ <td id="${param.method.name}.${param.name}">
+ <code>${param.name}</code>
+ </td>
+ <td>
+ #if (!$param.type.isEmpty())
+ <p><code>${param.type}</code></p>
+ #end
+ <p>${param.documentation}</p>
+ </td>
+ </tr>
+ #end
+ </tbody>
+ </table>
+ #end
+ ${method.returnTypeExtraMessage}
+ #end
+#end
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/skylark-nav.vm b/src/main/java/com/google/devtools/build/docgen/templates/skylark-nav.vm
new file mode 100644
index 0000000000..54194c0c24
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/skylark-nav.vm
@@ -0,0 +1,4 @@
+#foreach ($module in $modules)
+
+<li><a href="/docs/skylark/lib/${module.name}.html">${module.title}</a></li>
+#end
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
index 1166cffd8e..e620ef63c6 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
@@ -367,7 +367,7 @@ public class Artifact implements FileType.HasFilename, ActionInput {
@SkylarkCallable(name = "path", structField = true,
doc = "The execution path of this file, relative to the execution directory. It consists of "
+ "two parts, an optional first part called the <i>root</i> (see also the <a "
- + "href=\"#modules.root\">root</a> module), and the second part which is the "
+ + "href=\"root.html\">root</a> module), and the second part which is the "
+ "<code>short_path</code>. The root may be empty, which it usually is for non-generated "
+ "files. For generated files it usually contains a configuration-specific path fragment that"
+ " encodes things like the target CPU architecture that was used while building said file.")
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
index 2ba49d79d9..fcc9c641a2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
@@ -86,10 +86,10 @@ import javax.annotation.Nullable;
"A BUILD target. It is essentially a <code>struct</code> with the following fields:"
+ "<ul>"
+ "<li><h3 id=\"modules.Target.label\">label</h3><code><a class=\"anchor\" "
- + "href=\"#modules.Label\">Label</a> Target.label</code><br>The identifier of the target.</li>"
+ + "href=\"Label.html\">Label</a> Target.label</code><br>The identifier of the target.</li>"
+ "<li><h3 id=\"modules.Target.files\">files</h3><code><a class=\"anchor\" "
- + "href=\"#modules.set\">set</a> Target.files </code><br>The (transitive) set of <a "
- + "class=\"anchor\" href=\"#modules.File\">File</a>s produced by this target.</li>"
+ + "href=\"set.html\">set</a> Target.files </code><br>The (transitive) set of <a "
+ + "class=\"anchor\" href=\"File.html\">File</a>s produced by this target.</li>"
+ "<li><h3 id=\"modules.Target.extraproviders\">Extra providers</h3>For rule targets all "
+ "additional providers provided by this target are accessible as <code>struct</code> fields. "
+ "These extra providers are defined in the <code>struct</code> returned by the rule "
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 38bab82545..4d31424e46 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -90,8 +90,8 @@ public final class Attribute implements Comparable<Attribute> {
*/
@SkylarkModule(name = "ConfigurationTransition", doc =
"Declares how the configuration should change when following a dependency. "
- + "It can be either <a href=\"#modules._top_level.DATA_CFG\">DATA_CFG</a> or "
- + "<a href=\"#modules._top_level.HOST_CFG\">HOST_CFG</a>.")
+ + "It can be either <a href=\"globals.html#DATA_CFG\">DATA_CFG</a> or "
+ + "<a href=\"globals.html#HOST_CFG\">HOST_CFG</a>.")
public enum ConfigurationTransition implements Transition {
/** No transition, i.e., the same configuration as the current. */
NONE,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
index fc85bb1874..9c3fedf7e1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
@@ -44,10 +44,9 @@ import java.util.Map;
/**
* A helper class to provide Attr module in Skylark.
*
- * It exposes functions (e.g. 'attr.string', 'attr.label_list', etc.) to Skylark
+ * <p>It exposes functions (e.g. 'attr.string', 'attr.label_list', etc.) to Skylark
* users. The functions are executed through reflection. As everywhere in Skylark,
* arguments are type-checked with the signature and cannot be null.
- *
*/
@SkylarkModule(
name = "attr",
@@ -55,7 +54,7 @@ import java.util.Map;
onlyLoadingPhase = true,
doc =
"Module for creating new attributes. "
- + "They are only for use with the <a href=\"#modules._top_level.rule\">rule</a> function."
+ + "They are only for use with the <a href=\"globals.html#rule\">rule</a> function."
)
public final class SkylarkAttr {
@@ -463,7 +462,7 @@ public final class SkylarkAttr {
name = "label_list",
doc =
"Creates an attribute of type list of labels. "
- + "See <a href=\"#modules.attr.label\">label</a> for more information.",
+ + "See <a href=\"attr.html#label\">label</a> for more information.",
objectType = SkylarkAttr.class,
returnType = Attribute.Builder.class,
optionalNamedOnly = {
@@ -623,7 +622,7 @@ public final class SkylarkAttr {
name = "output_list",
doc =
"Creates an attribute of type list of outputs. Its default value is <code>[]</code>. "
- + "See <a href=\"#modules.attr.output\">output</a> above for more information.",
+ + "See <a href=\"attr.html#output\">output</a> above for more information.",
objectType = SkylarkAttr.class,
returnType = Attribute.Builder.class,
optionalNamedOnly = {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkFileType.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkFileType.java
index 0571cb410d..e47b47e76c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkFileType.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkFileType.java
@@ -47,9 +47,9 @@ public class SkylarkFileType {
@SkylarkCallable(doc =
"Returns a list created from the elements of the parameter containing all the "
- + "<a href=\"#modules.File\"><code>File</code></a>s that match the FileType. The parameter "
- + "must be a <a href=\"#modules.set\"><code>set</code></a> or a "
- + "<a href=\"#modules.list\"><code>list</code></a>.")
+ + "<a href=\"File.html\"><code>File</code></a>s that match the FileType. The parameter "
+ + "must be a <a href=\"set.html\"><code>set</code></a> or a "
+ + "<a href=\"list.html\"><code>list</code></a>.")
public List<Artifact> filter(Iterable<Artifact> files) {
return ImmutableList.copyOf(FileType.filter(files, fileType));
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
index e128d7eec7..2f129501cb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
@@ -191,7 +191,7 @@ public class SkylarkRuleClassFunctions {
mandatoryPositionals = {
@Param(name = "implementation", type = BaseFunction.class,
doc = "the function implementing this rule, must have exactly one parameter: "
- + "<a href=\"#modules.ctx\">ctx</a>. The function is called during the analysis phase "
+ + "<a href=\"ctx.html\">ctx</a>. The function is called during the analysis phase "
+ "for each instance of the rule. It can access the attributes provided by the user. "
+ "It must create actions to generate all the declared outputs.")
},
@@ -202,7 +202,7 @@ public class SkylarkRuleClassFunctions {
+ "and there must be an action that generates <code>ctx.outputs.executable</code>."),
@Param(name = "attrs", type = Map.class, noneable = true, defaultValue = "None", doc =
"dictionary to declare all the attributes of the rule. It maps from an attribute name "
- + "to an attribute object (see <a href=\"#modules.attr\">attr</a> module). "
+ + "to an attribute object (see <a href=\"attr.html\">attr</a> module). "
+ "Attributes starting with <code>_</code> are private, and can be used to add "
+ "an implicit dependency on a label. The attribute <code>name</code> is implicitly "
+ "added and must not be specified. Attributes <code>visibility</code>, "
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
index 385b04d8ca..8221066a3a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java
@@ -329,14 +329,14 @@ public final class SkylarkRuleContext {
}
@SkylarkCallable(name = "configuration", structField = true,
- doc = "Returns the default configuration. See the <a href=\"#modules.configuration\">"
+ doc = "Returns the default configuration. See the <a href=\"configuration.html\">"
+ "configuration</a> type for more details.")
public BuildConfiguration getConfiguration() {
return ruleContext.getConfiguration();
}
@SkylarkCallable(name = "host_configuration", structField = true,
- doc = "Returns the host configuration. See the <a href=\"#modules.configuration\">"
+ doc = "Returns the host configuration. See the <a href=\"configuration.html\">"
+ "configuration</a> type for more details.")
public BuildConfiguration getHostConfiguration() {
return ruleContext.getHostConfiguration();
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java b/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java
index 9ed20cc68a..c38ea774fd 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java
@@ -57,7 +57,7 @@ public interface ClassObject {
@Immutable
@SkylarkModule(name = "struct",
doc = "A special language element to support structs (i.e. simple value objects). "
- + "See the global <a href=\"#modules._top_level.struct\">struct</a> function "
+ + "See the global <a href=\"globals.html#struct\">struct</a> function "
+ "for more details.")
public class SkylarkClassObject implements ClassObject {
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index d8b625e328..2e0d38c4f5 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -952,7 +952,7 @@ public class MethodLibrary {
};
@SkylarkSignature(name = "set", returnType = SkylarkNestedSet.class,
- doc = "Creates a <a href=\"#modules.set\">set</a> from the <code>items</code>."
+ doc = "Creates a <a href=\"set.html\">set</a> from the <code>items</code>."
+ " The set supports nesting other sets of the same element"
+ " type in it. A desired iteration order can also be specified.<br>"
+ " Examples:<br><pre class=\"language-python\">set([\"a\", \"b\"])\n"
@@ -965,7 +965,7 @@ public class MethodLibrary {
doc = "The ordering strategy for the set if it's nested, "
+ "possible values are: <code>stable</code> (default), <code>compile</code>, "
+ "<code>link</code> or <code>naive_link</code>. An explanation of the "
- + "values can be found <a href=\"#modules.set\">here</a>.")},
+ + "values can be found <a href=\"set.html\">here</a>.")},
useLocation = true)
private static final BuiltinFunction set = new BuiltinFunction("set") {
public SkylarkNestedSet invoke(Object items, String order,
@@ -1022,7 +1022,7 @@ public class MethodLibrary {
@SkylarkSignature(name = "union", objectType = SkylarkNestedSet.class,
returnType = SkylarkNestedSet.class,
- doc = "Creates a new <a href=\"#modules.set\">set</a> that contains both "
+ doc = "Creates a new <a href=\"set.html\">set</a> that contains both "
+ "the input set as well as all additional elements.",
mandatoryPositionals = {
@Param(name = "input", type = SkylarkNestedSet.class, doc = "The input set"),
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
index e4eeba3333..004d4c4143 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
@@ -35,7 +35,7 @@ import javax.annotation.Nullable;
*/
@SkylarkModule(name = "set",
doc = "A language built-in type that supports (nested) sets. "
- + "Sets can be created using the <a href=\"#modules._top_level.set\">set</a> function, and "
+ + "Sets can be created using the <a href=\"globals.html#set\">set</a> function, and "
+ "they support the <code>+</code> operator to extend the set with more elements or "
+ "to nest other sets inside of it. Examples:<br>"
+ "<pre class=language-python>s = set([1, 2])\n"