diff options
Diffstat (limited to 'src/main')
3 files changed, 74 insertions, 40 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 334634e3b9..6b614b381b 100644 --- a/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java +++ b/src/main/java/com/google/devtools/build/docgen/SkylarkDocumentationCollector.java @@ -20,6 +20,7 @@ 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.skylarkinterface.SkylarkCallable; +import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor; import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; @@ -32,7 +33,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayDeque; import java.util.Deque; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -120,10 +120,8 @@ final class SkylarkDocumentationCollector { Map<String, SkylarkModuleDoc> modules) { Set<Class<?>> done = new HashSet<>(); Deque<Class<?>> toProcess = new ArrayDeque<>(); - Map<Class<?>, SkylarkModule> annotations = new HashMap<>(); toProcess.addLast(firstClass); - annotations.put(firstClass, firstModule); while (!toProcess.isEmpty()) { Class<?> c = toProcess.removeFirst(); @@ -143,7 +141,6 @@ final class SkylarkDocumentationCollector { if (returnClass.isAnnotationPresent(SkylarkModule.class) && !done.contains(returnClass)) { toProcess.addLast(returnClass); - annotations.put(returnClass, returnClass.getAnnotation(SkylarkModule.class)); } } } @@ -165,12 +162,21 @@ final class SkylarkDocumentationCollector { private static void collectBuiltinMethods( Map<String, SkylarkModuleDoc> modules, Class<?> moduleClass) { - SkylarkModuleDoc module = getTopLevelModuleDoc(modules); + SkylarkModuleDoc topLevelModuleDoc = getTopLevelModuleDoc(modules); ImmutableMap<Method, SkylarkCallable> methods = FuncallExpression.collectSkylarkMethodsWithAnnotation(moduleClass); for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) { - module.addMethod(new SkylarkJavaMethodDoc("", entry.getKey(), entry.getValue())); + 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())); + } else { + topLevelModuleDoc.addMethod(new SkylarkJavaMethodDoc("", entry.getKey(), entry.getValue())); + } } } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java index 985fbea325..a8ee1e007d 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java @@ -74,6 +74,7 @@ import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.ParamType; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; +import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor; import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature; @@ -1020,17 +1021,16 @@ public class SkylarkRuleClassFunctions { ImmutableList.of( SkylarkProvider.class, SkylarkDefinedAspect.class, SkylarkRuleFunction.class); - @SkylarkSignature( + @SkylarkCallable( name = "Label", doc = "Creates a Label referring to a BUILD target. Use " + "this function only when you want to give a default value for the label attributes. " + "The argument must refer to an absolute label. " + "Example: <br><pre class=language-python>Label(\"//tools:default\")</pre>", - returnType = Label.class, - objectType = Label.class, parameters = { - @Param(name = "label_string", type = String.class, doc = "the label string."), + @Param(name = "label_string", type = String.class, legacyNamed = true, + doc = "the label string."), @Param( name = "relative_to_caller_repository", type = Boolean.class, @@ -1050,36 +1050,26 @@ public class SkylarkRuleClassFunctions { useLocation = true, useEnvironment = true ) - private static final BuiltinFunction label = - new BuiltinFunction("Label") { - @SuppressWarnings({"unchecked", "unused"}) - public Label invoke( - String labelString, Boolean relativeToCallerRepository, Location loc, Environment env) - throws EvalException { - Label parentLabel = null; - if (relativeToCallerRepository) { - parentLabel = env.getCallerLabel(); - } else { - parentLabel = env.getGlobals().getTransitiveLabel(); - } - try { - if (parentLabel != null) { - LabelValidator.parseAbsoluteLabel(labelString); - labelString = parentLabel.getRelative(labelString).getUnambiguousCanonicalForm(); - } - return labelCache.get(labelString); - } catch (LabelValidator.BadLabelException | LabelSyntaxException | ExecutionException e) { - throw new EvalException(loc, "Illegal absolute label syntax: " + labelString); - } - } - }; - - // We want the Label ctor to show up under the Label documentation, but to be a "global - // function." Thus, we create a global Label object here, which just points to the Skylark - // function above. - @SkylarkSignature(name = "Label", - documented = false) - private static final BuiltinFunction globalLabel = label; + @SkylarkConstructor(objectType = Label.class) + public Label label( + String labelString, Boolean relativeToCallerRepository, Location loc, Environment env) + throws EvalException { + Label parentLabel = null; + if (relativeToCallerRepository) { + parentLabel = env.getCallerLabel(); + } else { + parentLabel = env.getGlobals().getTransitiveLabel(); + } + try { + if (parentLabel != null) { + LabelValidator.parseAbsoluteLabel(labelString); + labelString = parentLabel.getRelative(labelString).getUnambiguousCanonicalForm(); + } + return labelCache.get(labelString); + } catch (LabelValidator.BadLabelException | LabelSyntaxException | ExecutionException e) { + throw new EvalException(loc, "Illegal absolute label syntax: " + labelString); + } + } @SkylarkSignature( name = "FileType", diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkConstructor.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkConstructor.java new file mode 100644 index 0000000000..b785038da1 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkConstructor.java @@ -0,0 +1,38 @@ +// Copyright 2018 The Bazel Authors. 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.lib.skylarkinterface; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation to mark {@link SkylarkCallable}-annotated methods as representing top-level + * constructors for other Skylark objects. This is used only for documentation purposes. + * + * <p>For example, a "Foo" type skylark object might be constructable at the top level using + * a global callable "Foo()". One can annotate that callable with this annotation to ensure that + * the documentation for "Foo()" appears alongside the documentation for the Foo type, and not + * the available globals. + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SkylarkConstructor { + + /** + * The java class of the skylark type that this annotation's method is a constructor for. + */ + Class<?> objectType(); +} |