diff options
3 files changed, 217 insertions, 8 deletions
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 a6609d4666..6793119eaf 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 @@ -87,7 +87,7 @@ public final class SkylarkAttr implements SkylarkValue { private static final String ALLOW_RULES_ARG = "allow_rules"; private static final String ALLOW_RULES_DOC = "which rule targets (name of the classes) are allowed. This is deprecated (kept only for " - + "compatiblity), use providers instead."; + + "compatibility), use providers instead."; private static final String ASPECTS_ARG = "aspects"; private static final String ASPECTS_ARG_DOC = @@ -102,6 +102,10 @@ public final class SkylarkAttr implements SkylarkValue { private static final String DEFAULT_ARG = "default"; private static final String DEFAULT_DOC = "the default value of the attribute."; + private static final String DOC_ARG = "doc"; + private static final String DOC_DOC = + "a description of the attribute that can be extracted by documentation generating tools."; + private static final String EXECUTABLE_ARG = "executable"; private static final String EXECUTABLE_DOC = "True if the labels have to be executable. This means the label must refer to an " @@ -462,6 +466,14 @@ public final class SkylarkAttr implements SkylarkValue { positional = false ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -486,6 +498,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("int") { public Descriptor invoke( Integer defaultInt, + String doc, Boolean mandatory, SkylarkList<?> values, FuncallExpression ast, @@ -518,6 +531,14 @@ public final class SkylarkAttr implements SkylarkValue { positional = false ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -542,6 +563,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("string") { public Descriptor invoke( String defaultString, + String doc, Boolean mandatory, SkylarkList<?> values, FuncallExpression ast, @@ -587,6 +609,14 @@ public final class SkylarkAttr implements SkylarkValue { + "<code>attr.label(default = \"//a:b\")</code>" ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = EXECUTABLE_ARG, type = Boolean.class, defaultValue = "False", @@ -674,6 +704,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("label") { public Descriptor invoke( Object defaultO, + String doc, Boolean executable, Object allowFiles, Object allowSingleFile, @@ -739,6 +770,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -764,6 +803,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("string_list") { public Descriptor invoke( SkylarkList<?> defaultList, + String doc, Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, @@ -803,6 +843,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -828,6 +876,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("int_list") { public Descriptor invoke( SkylarkList<?> defaultList, + String doc, Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, @@ -877,6 +926,14 @@ public final class SkylarkAttr implements SkylarkValue { + "<code>attr.label_list(default = [\"//a:b\", \"//a:c\"])</code>" ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = ALLOW_FILES_ARG, // bool or FileType filter defaultValue = "None", named = true, @@ -958,6 +1015,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("label_list") { public Descriptor invoke( Object defaultList, + String doc, Object allowFiles, Object allowRules, SkylarkList<?> providers, @@ -1029,6 +1087,14 @@ public final class SkylarkAttr implements SkylarkValue { + "{\"//a:b\": \"value\", \"//a:c\": \"string\"})</code>" ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = ALLOW_FILES_ARG, // bool or FileType filter defaultValue = "None", named = true, @@ -1110,6 +1176,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("label_keyed_string_dict") { public Descriptor invoke( Object defaultList, + String doc, Object allowFiles, Object allowRules, SkylarkList<?> providers, @@ -1172,6 +1239,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -1186,7 +1261,7 @@ public final class SkylarkAttr implements SkylarkValue { private static BuiltinFunction bool = new BuiltinFunction("bool") { public Descriptor invoke( - Boolean defaultO, Boolean mandatory, FuncallExpression ast, Environment env) + Boolean defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env) throws EvalException { env.checkLoadingOrWorkspacePhase("attr.bool", ast.getLocation()); return createAttrDescriptor( @@ -1218,6 +1293,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -1232,7 +1315,7 @@ public final class SkylarkAttr implements SkylarkValue { private static BuiltinFunction output = new BuiltinFunction("output") { public Descriptor invoke( - Object defaultO, Boolean mandatory, FuncallExpression ast, Environment env) + Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env) throws EvalException { env.checkLoadingOrWorkspacePhase("attr.output", ast.getLocation()); return createNonconfigurableAttrDescriptor( @@ -1263,6 +1346,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -1292,6 +1383,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("output_list") { public Descriptor invoke( SkylarkList defaultList, + String doc, Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, @@ -1334,6 +1426,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, named = true, @@ -1363,6 +1463,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("string_dict") { public Descriptor invoke( SkylarkDict<?, ?> defaultO, + String doc, Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, @@ -1406,6 +1507,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -1435,6 +1544,7 @@ public final class SkylarkAttr implements SkylarkValue { new BuiltinFunction("string_list_dict") { public Descriptor invoke( SkylarkDict<?, ?> defaultO, + String doc, Boolean mandatory, Boolean nonEmpty, Boolean allowEmpty, @@ -1477,6 +1587,14 @@ public final class SkylarkAttr implements SkylarkValue { doc = DEFAULT_DOC ), @Param( + name = DOC_ARG, + type = String.class, + defaultValue = "''", + doc = DOC_DOC, + named = true, + positional = false + ), + @Param( name = MANDATORY_ARG, type = Boolean.class, defaultValue = "False", @@ -1491,7 +1609,7 @@ public final class SkylarkAttr implements SkylarkValue { private static BuiltinFunction license = new BuiltinFunction("license") { public Descriptor invoke( - Object defaultO, Boolean mandatory, FuncallExpression ast, Environment env) + Object defaultO, String doc, Boolean mandatory, FuncallExpression ast, Environment env) throws EvalException { env.checkLoadingOrWorkspacePhase("attr.license", ast.getLocation()); return createNonconfigurableAttrDescriptor( 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 ecc46a4268..a2cfcb29a7 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 @@ -258,11 +258,20 @@ public class SkylarkRuleClassFunctions { + "<pre class=\"language-python\">data = provider()\n" + "d = data(x = 2, y = 3)\n" + "print(d.x + d.y) # prints 5</pre>", + parameters = { + @Param( + name = "doc", + type = String.class, + defaultValue = "''", + doc = + "A description of the provider that can be extracted by documentation generating tools." + ) + }, useLocation = true ) private static final BuiltinFunction provider = new BuiltinFunction("provider") { - public ClassObjectConstructor invoke(Location location) { + public ClassObjectConstructor invoke(String doc, Location location) { return new SkylarkClassObjectConstructor( "<no name>", // name is set on export. location); @@ -391,6 +400,12 @@ public class SkylarkRuleClassFunctions { + "If set, the set of toolchains this rule requires. Toolchains will be " + "found by checking the current platform, and provided to the rule " + "implementation via <code>ctx.toolchain</code>." + ), + @Param( + name = "doc", + type = String.class, + defaultValue = "''", + doc = "A description of the rule that can be extracted by documentation generating tools." ) }, useAst = true, @@ -411,6 +426,7 @@ public class SkylarkRuleClassFunctions { SkylarkList hostFragments, Boolean skylarkTestable, SkylarkList<String> toolchains, + String doc, FuncallExpression ast, Environment funcallEnv) throws EvalException, ConversionException { @@ -605,6 +621,12 @@ public class SkylarkRuleClassFunctions { + "If set, the set of toolchains this rule requires. Toolchains will be " + "found by checking the current platform, and provided to the rule " + "implementation via <code>ctx.toolchain</code>." + ), + @Param( + name = "doc", + type = String.class, + defaultValue = "''", + doc = "A description of the aspect that can be extracted by documentation generating tools." ) }, useEnvironment = true, @@ -621,6 +643,7 @@ public class SkylarkRuleClassFunctions { SkylarkList fragments, SkylarkList hostFragments, SkylarkList<String> toolchains, + String doc, FuncallExpression ast, Environment funcallEnv) throws EvalException { diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java index a0f6316c9b..b3d614816d 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java @@ -493,7 +493,7 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { public void testAttrDefaultValueBadType() throws Exception { checkErrorContains( "argument 'default' has type 'int', but should be 'string'\n" - + "in call to builtin function attr.string(*, default, mandatory, values)", + + "in call to builtin function attr.string(*, default, doc, mandatory, values)", "attr.string(default = 1)"); } @@ -559,6 +559,34 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { } @Test + public void testAttrDoc() throws Exception { + // We don't actually store the doc in the attr definition; right now it's just meant to be + // extracted by documentation generating tools. So we don't have anything to assert and we just + // verify that no exceptions were thrown from building them. + buildAttribute("a1", "attr.bool(doc='foo')"); + buildAttribute("a2", "attr.int(doc='foo')"); + buildAttribute("a3", "attr.int_list(doc='foo')"); + buildAttribute("a4", "attr.label(doc='foo')"); + buildAttribute("a5", "attr.label_keyed_string_dict(doc='foo')"); + buildAttribute("a6", "attr.label_list(doc='foo')"); + buildAttribute("a7", "attr.license(doc='foo')"); + buildAttribute("a8", "attr.output(doc='foo')"); + buildAttribute("a9", "attr.output_list(doc='foo')"); + buildAttribute("a10", "attr.string(doc='foo')"); + buildAttribute("a11", "attr.string_dict(doc='foo')"); + buildAttribute("a12", "attr.string_list(doc='foo')"); + buildAttribute("a13", "attr.string_list_dict(doc='foo')"); + } + + @Test + public void testAttrDocValueBadType() throws Exception { + checkErrorContains( + "argument 'doc' has type 'int', but should be 'string'\n" + + "in call to builtin function attr.string(*, default, doc, mandatory, values)", + "attr.string(doc = 1)"); + } + + @Test public void testRuleImplementation() throws Exception { evalAndExport("def impl(ctx): return None", "rule1 = rule(impl)"); RuleClass c = ((RuleFunction) lookup("rule1")).getRuleClass(); @@ -566,10 +594,15 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { } @Test + public void testRuleDoc() throws Exception { + evalAndExport("def impl(ctx): return None", "rule1 = rule(impl, doc='foo')"); + } + + @Test public void testLateBoundAttrWorksWithOnlyLabel() throws Exception { checkEvalError( "argument 'default' has type 'function', but should be 'string'\n" - + "in call to builtin function attr.string(*, default, mandatory, values)", + + "in call to builtin function attr.string(*, default, doc, mandatory, values)", "def attr_value(cfg): return 'a'", "attr.string(default=attr_value)"); } @@ -689,6 +722,14 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { } @Test + public void testRuleBadTypeForDoc() throws Exception { + registerDummyUserDefinedFunction(); + checkErrorContains( + "argument 'doc' has type 'int', but should be 'string'", + "rule(impl, doc = 1)"); + } + + @Test public void testLabel() throws Exception { Object result = evalRuleClassCode("Label('//foo/foo:foo')"); assertThat(result).isInstanceOf(Label.class); @@ -1209,7 +1250,6 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { } @Test - public void structsAsDeclaredProvidersTest() throws Exception { evalAndExport( "data = struct(x = 1)" @@ -1222,6 +1262,18 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { } @Test + public void declaredProvidersDoc() throws Exception { + evalAndExport("data1 = provider(doc='foo')"); + } + + @Test + public void declaredProvidersBadTypeForDoc() throws Exception { + checkErrorContains( + "argument 'doc' has type 'int', but should be 'string'", + "provider(doc = 1)"); + } + + @Test public void aspectAllAttrs() throws Exception { evalAndExport( "def _impl(target, ctx):", @@ -1348,6 +1400,22 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { + " Should be list of providers, but got int. "); } + @Test + public void aspectDoc() throws Exception { + evalAndExport( + "def _impl(target, ctx):", + " pass", + "my_aspect = aspect(_impl, doc='foo')"); + } + + @Test + public void aspectBadTypeForDoc() throws Exception { + registerDummyUserDefinedFunction(); + checkErrorContains( + "argument 'doc' has type 'int', but should be 'string'", + "aspect(impl, doc = 1)"); + } + @Test |