Create an experimental analysis_test parameter in rule
This will control whether a given rule should be treated as an "analysis test" rule. The parameter and its functionality will only be available via --experimental_analysis_testing_improvements until it is complete.
In this change, analysis_test = True enforces the restriction that the rule implementation function for that rule may not register actions.
See https://docs.google.com/document/d/17P2sgC6VPmcA7CcqC2p4cfU2Kaj6dwKiQfIXhtXTzl4/ for
details.
Progress toward #6237
RELNOTES: None.
PiperOrigin-RevId: 217562194
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
index 15ad36a..1679f60 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
@@ -151,6 +151,9 @@
GeneratingActions generatingActions =
Actions.filterSharedActionsAndThrowActionConflict(
analysisEnvironment.getActionKeyContext(), analysisEnvironment.getRegisteredActions());
+ if (ruleContext.getRule().isAnalysisTest()) {
+ Preconditions.checkState(generatingActions.getActions().isEmpty());
+ }
return new RuleConfiguredTarget(
ruleContext,
providers,
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
index b4b0eda..c3562c2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
@@ -22,7 +22,9 @@
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.ActionRegistry;
import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.CommandLine;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
@@ -100,6 +102,31 @@
: ruleContext.getBinOrGenfilesDirectory();
}
+ /**
+ * Returns a {@link ActionRegistry} object to register actions using this action factory.
+ *
+ * @throws EvalException if actions cannot be registered with this object
+ */
+ public ActionRegistry asActionRegistry(
+ final Location location, SkylarkActionFactory skylarkActionFactory) throws EvalException {
+ validateActionCreation(location);
+ return new ActionRegistry() {
+
+ @Override
+ public void registerAction(ActionAnalysisMetadata... actions) {
+ ruleContext.registerAction(actions);
+ }
+
+ @Override
+ public ArtifactOwner getOwner() {
+ return skylarkActionFactory
+ .getActionConstructionContext()
+ .getAnalysisEnvironment()
+ .getOwner();
+ }
+ };
+ }
+
@Override
public Artifact declareFile(String filename, Object sibling) throws EvalException {
context.checkMutable("actions.declare_file");
@@ -134,7 +161,7 @@
}
@Override
- public void doNothing(String mnemonic, Object inputs) throws EvalException {
+ public void doNothing(String mnemonic, Object inputs, Location location) throws EvalException {
context.checkMutable("actions.do_nothing");
NestedSet<Artifact> inputSet = inputs instanceof SkylarkNestedSet
? ((SkylarkNestedSet) inputs).getSet(Artifact.class)
@@ -152,7 +179,7 @@
mnemonic,
SPAWN_INFO,
SpawnInfo.newBuilder().build());
- ruleContext.registerAction(action);
+ registerAction(location, action);
}
@AutoCodec @AutoCodec.VisibleForSerialization
@@ -160,7 +187,8 @@
SpawnInfo.spawnInfo;
@Override
- public void write(FileApi output, Object content, Boolean isExecutable) throws EvalException {
+ public void write(FileApi output, Object content, Boolean isExecutable, Location location)
+ throws EvalException {
context.checkMutable("actions.write");
final Action action;
if (content instanceof String) {
@@ -181,7 +209,7 @@
} else {
throw new AssertionError("Unexpected type: " + content.getClass().getSimpleName());
}
- ruleContext.registerAction(action);
+ registerAction(location, action);
}
@Override
@@ -236,19 +264,31 @@
builder);
}
+ private void validateActionCreation(Location location) throws EvalException {
+ if (ruleContext.getRule().isAnalysisTest()) {
+ throw new EvalException(
+ location,
+ "implementation function of a rule with "
+ + "analysis_test=true may not register actions. Analysis test rules may only return "
+ + "success/failure information via AnalysisTestResultInfo.");
+ }
+ }
+
/**
* Registers actions in the context of this {@link SkylarkActionFactory}.
*
- * Use {@link #getActionConstructionContext()} to obtain the context required to
- * create those actions.
+ * <p>Use {@link #getActionConstructionContext()} to obtain the context required to create those
+ * actions.
*/
- public void registerAction(ActionAnalysisMetadata... actions) {
+ public void registerAction(Location location, ActionAnalysisMetadata... actions)
+ throws EvalException {
+ validateActionCreation(location);
ruleContext.registerAction(actions);
}
/**
- * Returns information needed to construct actions that can be
- * registered with {@link #registerAction(ActionAnalysisMetadata...)}.
+ * Returns information needed to construct actions that can be registered with {@link
+ * #registerAction(Location, ActionAnalysisMetadata...)}.
*/
public ActionConstructionContext getActionConstructionContext() {
return ruleContext;
@@ -487,7 +527,7 @@
}
}
// Always register the action
- ruleContext.registerAction(builder.build(ruleContext));
+ registerAction(location, builder.build(ruleContext));
}
private String getMnemonic(Object mnemonicUnchecked) {
@@ -508,7 +548,8 @@
FileApi template,
FileApi output,
SkylarkDict<?, ?> substitutionsUnchecked,
- Boolean executable)
+ Boolean executable,
+ Location location)
throws EvalException {
context.checkMutable("actions.expand_template");
ImmutableList.Builder<Substitution> substitutionsBuilder = ImmutableList.builder();
@@ -531,7 +572,7 @@
(Artifact) output,
substitutionsBuilder.build(),
executable);
- ruleContext.registerAction(action);
+ registerAction(location, action);
}
/**
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 eb1fe59..fa17854 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
@@ -271,10 +271,21 @@
SkylarkList<?> providesArg,
Boolean executionPlatformConstraintsAllowed,
SkylarkList<?> execCompatibleWith,
+ Object analysisTest,
FuncallExpression ast,
Environment funcallEnv)
throws EvalException, ConversionException {
SkylarkUtils.checkLoadingOrWorkspacePhase(funcallEnv, "rule", ast.getLocation());
+
+ if (analysisTest != Runtime.UNBOUND
+ && !funcallEnv.getSemantics().experimentalAnalysisTestingImprovements()) {
+ throw new EvalException(
+ ast.getLocation(),
+ "analysis_test parameter is experimental and not available for "
+ + "general use. It is subject to change at any time. It may be enabled by specifying "
+ + "--experimental_analysis_testing_improvements");
+ }
+
RuleClassType type = test ? RuleClassType.TEST : RuleClassType.NORMAL;
RuleClass parent =
test
@@ -289,6 +300,9 @@
if (skylarkTestable) {
builder.setSkylarkTestable();
}
+ if (Boolean.TRUE.equals(analysisTest)) {
+ builder.setIsAnalysisTest();
+ }
if (executable || test) {
addAttribute(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
index 2e24c3c..c647f87 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
@@ -884,7 +884,7 @@
throws EvalException {
checkDeprecated("ctx.actions.write", "ctx.file_action", loc, env.getSemantics());
checkMutable("file_action");
- actions().write(output, content, executable);
+ actions().write(output, content, executable, loc);
return Runtime.NONE;
}
@@ -893,7 +893,7 @@
throws EvalException {
checkDeprecated("ctx.actions.do_nothing", "ctx.empty_action", loc, env.getSemantics());
checkMutable("empty_action");
- actions().doNothing(mnemonic, inputs);
+ actions().doNothing(mnemonic, inputs, loc);
return Runtime.NONE;
}
@@ -908,7 +908,7 @@
throws EvalException {
checkDeprecated("ctx.actions.expand_template", "ctx.template_action", loc, env.getSemantics());
checkMutable("template_action");
- actions().expandTemplate(template, output, substitutionsUnchecked, executable);
+ actions().expandTemplate(template, output, substitutionsUnchecked, executable, loc);
return Runtime.NONE;
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
index 63eca18..00ee63e 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
@@ -176,6 +176,11 @@
: ruleClass.hasBinaryOutput();
}
+ /** Returns true if this rule is an analysis test (set by analysis_test = true). */
+ public boolean isAnalysisTest() {
+ return ruleClass.isAnalysisTest();
+ }
+
/**
* Returns true iff there were errors while constructing this rule, such as
* attributes with missing values or values of the wrong type.
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 72d5401..753b73e 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -630,6 +630,7 @@
private boolean binaryOutput = true;
private boolean workspaceOnly = false;
private boolean isExecutableSkylark = false;
+ private boolean isAnalysisTest = false;
private boolean isConfigMatcher = false;
private boolean hasFunctionTransitionWhitelist = false;
private ImplicitOutputsFunction implicitOutputsFunction = ImplicitOutputsFunction.NONE;
@@ -781,6 +782,7 @@
binaryOutput,
workspaceOnly,
isExecutableSkylark,
+ isAnalysisTest,
hasFunctionTransitionWhitelist,
implicitOutputsFunction,
isConfigMatcher,
@@ -1168,6 +1170,12 @@
return this;
}
+ /** This rule class is marked as an analysis test. */
+ public Builder setIsAnalysisTest() {
+ this.isAnalysisTest = true;
+ return this;
+ }
+
/**
* This rule class has the _whitelist_function_transition attribute. Intended only for Skylark
* rules.
@@ -1349,6 +1357,7 @@
private final boolean binaryOutput;
private final boolean workspaceOnly;
private final boolean isExecutableSkylark;
+ private final boolean isAnalysisTest;
private final boolean isConfigMatcher;
private final boolean hasFunctionTransitionWhitelist;
@@ -1470,6 +1479,7 @@
boolean binaryOutput,
boolean workspaceOnly,
boolean isExecutableSkylark,
+ boolean isAnalysisTest,
boolean hasFunctionTransitionWhitelist,
ImplicitOutputsFunction implicitOutputsFunction,
boolean isConfigMatcher,
@@ -1489,7 +1499,7 @@
boolean supportsPlatforms,
ExecutionPlatformConstraintsAllowed executionPlatformConstraintsAllowed,
Set<Label> executionPlatformConstraints,
- OutputFile.Kind outputFileKind,
+ OutputFile.Kind outputFileKind,
Collection<Attribute> attributes) {
this.name = name;
this.key = key;
@@ -1517,6 +1527,7 @@
this.attributes = ImmutableList.copyOf(attributes);
this.workspaceOnly = workspaceOnly;
this.isExecutableSkylark = isExecutableSkylark;
+ this.isAnalysisTest = isAnalysisTest;
this.hasFunctionTransitionWhitelist = hasFunctionTransitionWhitelist;
this.configurationFragmentPolicy = configurationFragmentPolicy;
this.supportsConstraintChecking = supportsConstraintChecking;
@@ -2343,6 +2354,11 @@
return isExecutableSkylark;
}
+ /** Returns true if this rule class is an analysis test (set by analysis_test = true). */
+ public boolean isAnalysisTest() {
+ return isAnalysisTest;
+ }
+
/**
* Returns true if this rule class has the _whitelist_function_transition attribute.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java
index 42b773d..a73db3f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java
@@ -22,10 +22,8 @@
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionRegistry;
import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.Runfiles;
@@ -120,7 +118,8 @@
sourceFiles,
sourceJars,
(ConfiguredTarget) javaToolchain,
- (ConfiguredTarget) hostJavabase);
+ (ConfiguredTarget) hostJavabase,
+ location);
}
final Artifact iJar;
if (useIjar) {
@@ -136,7 +135,11 @@
}
iJar =
buildIjar(
- (SkylarkActionFactory) actions, outputJar, null, (ConfiguredTarget) javaToolchain);
+ (SkylarkActionFactory) actions,
+ outputJar,
+ null,
+ (ConfiguredTarget) javaToolchain,
+ location);
} else {
iJar = outputJar;
}
@@ -241,7 +244,8 @@
SkylarkList<Artifact> sourceFiles,
SkylarkList<Artifact> sourceJars,
ConfiguredTarget javaToolchain,
- ConfiguredTarget hostJavabase)
+ ConfiguredTarget hostJavabase,
+ Location location)
throws EvalException {
// No sources to pack, return None
if (sourceFiles.isEmpty() && sourceJars.isEmpty()) {
@@ -251,7 +255,7 @@
if (sourceFiles.isEmpty() && sourceJars.size() == 1) {
return sourceJars.get(0);
}
- ActionRegistry actionRegistry = createActionRegistry(actions);
+ ActionRegistry actionRegistry = actions.asActionRegistry(location, actions);
Artifact outputSrcJar = getSourceJar(actions.getActionConstructionContext(), outputJar);
JavaRuntimeInfo javaRuntimeInfo = JavaRuntimeInfo.from(hostJavabase, null);
JavaToolchainProvider javaToolchainProvider = getJavaToolchainProvider(javaToolchain);
@@ -268,24 +272,6 @@
return outputSrcJar;
}
- private ActionRegistry createActionRegistry(SkylarkActionFactory skylarkActionFactory) {
- return new ActionRegistry() {
-
- @Override
- public void registerAction(ActionAnalysisMetadata... actions) {
- skylarkActionFactory.registerAction(actions);
- }
-
- @Override
- public ArtifactOwner getOwner() {
- return skylarkActionFactory
- .getActionConstructionContext()
- .getAnalysisEnvironment()
- .getOwner();
- }
- };
- }
-
/** Creates a {@link JavaSourceJarsProvider} from the given lists of source jars. */
private static JavaSourceJarsProvider createJavaSourceJarsProvider(
List<Artifact> sourceJars, NestedSet<Artifact> transitiveSourceJars) {
@@ -384,7 +370,8 @@
(SkylarkActionFactory) actions,
compileJar,
null,
- (ConfiguredTarget) javaToolchain));
+ (ConfiguredTarget) javaToolchain,
+ location));
}
javaCompilationArgsBuilder.addDirectCompileTimeJars(
/* interfaceJars = */ builder.build(), /* fullJars= */ compileTimeJars);
@@ -558,7 +545,8 @@
SkylarkActionFactory actions,
Artifact inputJar,
@Nullable Label targetLabel,
- ConfiguredTarget javaToolchainConfiguredTarget)
+ ConfiguredTarget javaToolchainConfiguredTarget,
+ Location location)
throws EvalException {
String ijarBasename = FileSystemUtils.removeExtension(inputJar.getFilename()) + "-ijar.jar";
Artifact interfaceJar = actions.declareFile(ijarBasename, inputJar);
@@ -578,7 +566,7 @@
.addCommandLine(commandLine.build())
.useDefaultShellEnvironment()
.setMnemonic("JavaIjar");
- actions.registerAction(actionBuilder.build(actions.getActionConstructionContext()));
+ actions.registerAction(location, actionBuilder.build(actions.getActionConstructionContext()));
return interfaceJar;
}
@@ -586,7 +574,8 @@
SkylarkActionFactory actions,
Artifact inputJar,
Label targetLabel,
- ConfiguredTarget javaToolchainConfiguredTarget)
+ ConfiguredTarget javaToolchainConfiguredTarget,
+ Location location)
throws EvalException {
String basename = FileSystemUtils.removeExtension(inputJar.getFilename()) + "-stamped.jar";
Artifact outputJar = actions.declareFile(basename, inputJar);
@@ -608,7 +597,7 @@
.addCommandLine(commandLine.build())
.useDefaultShellEnvironment()
.setMnemonic("JavaIjar");
- actions.registerAction(actionBuilder.build(actions.getActionConstructionContext()));
+ actions.registerAction(location, actionBuilder.build(actions.getActionConstructionContext()));
return outputJar;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
index 1a7d590..29a389e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
@@ -126,18 +126,28 @@
SkylarkActionFactory actions,
Artifact jar,
Object targetLabel,
- ConfiguredTarget javaToolchain)
+ ConfiguredTarget javaToolchain,
+ Location location)
throws EvalException {
return JavaInfoBuildHelper.getInstance()
.buildIjar(
- actions, jar, targetLabel != Runtime.NONE ? (Label) targetLabel : null, javaToolchain);
+ actions,
+ jar,
+ targetLabel != Runtime.NONE ? (Label) targetLabel : null,
+ javaToolchain,
+ location);
}
@Override
public Artifact stampJar(
- SkylarkActionFactory actions, Artifact jar, Label targetLabel, ConfiguredTarget javaToolchain)
+ SkylarkActionFactory actions,
+ Artifact jar,
+ Label targetLabel,
+ ConfiguredTarget javaToolchain,
+ Location location)
throws EvalException {
- return JavaInfoBuildHelper.getInstance().stampJar(actions, jar, targetLabel, javaToolchain);
+ return JavaInfoBuildHelper.getInstance()
+ .stampJar(actions, jar, targetLabel, javaToolchain, location);
}
@Override
@@ -147,10 +157,12 @@
SkylarkList<Artifact> sourceFiles,
SkylarkList<Artifact> sourceJars,
ConfiguredTarget javaToolchain,
- ConfiguredTarget hostJavabase)
+ ConfiguredTarget hostJavabase,
+ Location location)
throws EvalException {
return JavaInfoBuildHelper.getInstance()
- .packSourceFiles(actions, outputJar, sourceFiles, sourceJars, javaToolchain, hostJavabase);
+ .packSourceFiles(
+ actions, outputJar, sourceFiles, sourceJars, javaToolchain, hostJavabase, location);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java
index a48e067..aaef112 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java
@@ -122,41 +122,41 @@
positional = false,
defaultValue = "[]",
doc = "List of the input files of the action."),
- })
- public void doNothing(String mnemonic, Object inputs) throws EvalException;
+ },
+ useLocation = true)
+ public void doNothing(String mnemonic, Object inputs, Location location) throws EvalException;
@SkylarkCallable(
- name = "write",
- doc =
- "Creates a file write action. When the action is executed, it will write the given content "
- + "to a file. This is used to generate files using information available in the "
- + "analysis phase. If the file is large and with a lot of static content, consider "
- + "using <a href=\"#expand_template\"><code>expand_template</code></a>.",
- parameters = {
- @Param(name = "output", type = FileApi.class, doc = "The output file.", named = true),
- @Param(
- name = "content",
- type = Object.class,
- allowedTypes = {
- @ParamType(type = String.class),
- @ParamType(type = CommandLineArgsApi.class)
- },
- doc =
- "the contents of the file. "
- + "May be a either a string or an "
- + "<a href=\"actions.html#args\"><code>actions.args()</code></a> object.",
- named = true
- ),
- @Param(
- name = "is_executable",
- type = Boolean.class,
- defaultValue = "False",
- doc = "Whether the output file should be executable.",
- named = true
- )
- }
- )
- public void write(FileApi output, Object content, Boolean isExecutable) throws EvalException;
+ name = "write",
+ doc =
+ "Creates a file write action. When the action is executed, it will write the given "
+ + "content to a file. This is used to generate files using information available in "
+ + "the analysis phase. If the file is large and with a lot of static content, "
+ + "consider using <a href=\"#expand_template\"><code>expand_template</code></a>.",
+ parameters = {
+ @Param(name = "output", type = FileApi.class, doc = "The output file.", named = true),
+ @Param(
+ name = "content",
+ type = Object.class,
+ allowedTypes = {
+ @ParamType(type = String.class),
+ @ParamType(type = CommandLineArgsApi.class)
+ },
+ doc =
+ "the contents of the file. "
+ + "May be a either a string or an "
+ + "<a href=\"actions.html#args\"><code>actions.args()</code></a> object.",
+ named = true),
+ @Param(
+ name = "is_executable",
+ type = Boolean.class,
+ defaultValue = "False",
+ doc = "Whether the output file should be executable.",
+ named = true)
+ },
+ useLocation = true)
+ public void write(FileApi output, Object content, Boolean isExecutable, Location location)
+ throws EvalException;
@SkylarkCallable(
name = "run",
@@ -500,12 +500,14 @@
named = true,
positional = false,
doc = "Whether the output file should be executable.")
- })
+ },
+ useLocation = true)
public void expandTemplate(
FileApi template,
FileApi output,
SkylarkDict<?, ?> substitutionsUnchecked,
- Boolean executable)
+ Boolean executable,
+ Location location)
throws EvalException;
@SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
index 6454900..2f2c008 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
@@ -25,6 +25,7 @@
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.Runtime.UnboundMarker;
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
@@ -89,219 +90,226 @@
public ProviderApi provider(String doc, Object fields, Location location) throws EvalException;
@SkylarkCallable(
- name = "rule",
- doc =
- "Creates a new rule, which can be called from a BUILD file or a macro to create targets."
- + "<p>Rules must be assigned to global variables in a .bzl file; the name of the "
- + "global variable is the rule's name."
- + "<p>Test rules are required to have a name ending in <code>_test</code>, while all "
- + "other rules must not have this suffix. (This restriction applies only to rules, not "
- + "to their targets.)",
- parameters = {
- @Param(
- name = "implementation",
- type = BaseFunction.class,
- legacyNamed = true,
- doc =
- "the function implementing this rule, must have exactly one parameter: "
- + "<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."
- ),
- @Param(
- name = "test",
- type = Boolean.class,
- legacyNamed = true,
- defaultValue = "False",
- doc =
- "Whether this rule is a test rule, that is, whether it may be the subject of a "
- + "<code>blaze test</code> command. All test rules are automatically considered "
- + "<a href='#rule.executable'>executable</a>; it is unnecessary (and discouraged) "
- + "to explicitly set <code>executable = True</code> for a test rule. See the "
- + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> for "
- + "more information."
- ),
- @Param(
- name = "attrs",
- type = SkylarkDict.class,
- legacyNamed = true,
- 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=\"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>, <code>deprecation</code>, <code>tags</code>, "
- + "<code>testonly</code>, and <code>features</code> are implicitly added and "
- + "cannot be overridden."
- ),
- // TODO(bazel-team): need to give the types of these builtin attributes
- @Param(
- name = "outputs",
- type = SkylarkDict.class,
- legacyNamed = true,
- callbackEnabled = true,
- noneable = true,
- defaultValue = "None",
- doc =
- "<b>Experimental:</b> This API is in the process of being redesigned."
- + "<p>A schema for defining predeclared outputs. Unlike <a href='attr.html#output'>"
- + "<code>output</code></a> and <a href='attr.html#output_list'><code>output_list"
- + "</code></a> attributes, the user does not specify the labels for these files. "
- + "See the <a href='../rules.$DOC_EXT#files'>Rules page</a> for more on "
- + "predeclared outputs."
- + "<p>The value of this argument is either a dictionary or a callback function "
- + "that produces a dictionary. The callback works similar to computed dependency "
- + "attributes: The function's parameter names are matched against the rule's "
- + "attributes, so for example if you pass <code>outputs = _my_func</code> with the "
- + "definition <code>def _my_func(srcs, deps): ...</code>, the function has access "
- + "to the attributes <code>srcs</code> and <code>deps</code>. Whether the "
- + "dictionary is specified directly or via a function, it is interpreted as "
- + "follows."
- + "<p>Each entry in the dictionary creates a predeclared output where the key is "
- + "an identifier and the value is a string template that determines the output's "
- + "label. In the rule's implementation function, the identifier becomes the field "
- + "name used to access the output's <a href='File.html'><code>File</code></a> in "
- + "<a href='ctx.html#outputs'><code>ctx.outputs</code></a>. The output's label has "
- + "the same package as the rule, and the part after the package is produced by "
- + "substituting each placeholder of the form <code>\"%{ATTR}\"</code> with a "
- + "string formed from the value of the attribute <code>ATTR</code>:"
- + "<ul>"
- + "<li>String-typed attributes are substituted verbatim."
- + "<li>Label-typed attributes become the part of the label after the package, "
- + "minus the file extension. For example, the label <code>\"//pkg:a/b.c\"</code> "
- + "becomes <code>\"a/b\"</code>."
- + "<li>Output-typed attributes become the part of the label after the package, "
- + "including the file extension (for the above example, <code>\"a/b.c\"</code>)."
- + "<li>All list-typed attributes (for example, <code>attr.label_list</code>) used "
- + "in placeholders are required to have <i>exactly one element</i>. Their "
- + "conversion is the same as their non-list version (<code>attr.label</code>)."
- + "<li>Other attribute types may not appear in placeholders."
- + "<li>The special non-attribute placeholders <code>%{dirname}</code> and <code>"
- + "%{basename}</code> expand to those parts of the rule's label, excluding its "
- + "package. For example, in <code>\"//pkg:a/b.c\"</code>, the dirname is <code>"
- + "a</code> and the basename is <code>b.c</code>."
- + "</ul>"
- + "<p>In practice, the most common substitution placeholder is "
- + "<code>\"%{name}\"</code>. For example, for a target named \"foo\", the outputs "
- + "dict <code>{\"bin\": \"%{name}.exe\"}</code> predeclares an output named "
- + "<code>foo.exe</code> that is accessible in the implementation function as "
- + "<code>ctx.outputs.bin</code>."
- ),
- @Param(
- name = "executable",
- type = Boolean.class,
- legacyNamed = true,
- defaultValue = "False",
- doc =
- "Whether this rule is considered executable, that is, whether it may be the subject of "
- + "a <code>blaze run</code> command. See the "
- + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> for "
- + "more information."
- ),
- @Param(
- name = "output_to_genfiles",
- type = Boolean.class,
- legacyNamed = true,
- defaultValue = "False",
- doc =
- "If true, the files will be generated in the genfiles directory instead of the "
- + "bin directory. Unless you need it for compatibility with existing rules "
- + "(e.g. when generating header files for C++), do not set this flag."
- ),
- @Param(
- name = "fragments",
- type = SkylarkList.class,
- legacyNamed = true,
- generic1 = String.class,
- defaultValue = "[]",
- doc =
- "List of names of configuration fragments that the rule requires "
- + "in target configuration."
- ),
- @Param(
- name = "host_fragments",
- type = SkylarkList.class,
- legacyNamed = true,
- generic1 = String.class,
- defaultValue = "[]",
- doc =
- "List of names of configuration fragments that the rule requires "
- + "in host configuration."
- ),
- @Param(
- name = "_skylark_testable",
- type = Boolean.class,
- legacyNamed = true,
- defaultValue = "False",
- doc =
- "<i>(Experimental)</i><br/><br/>"
- + "If true, this rule will expose its actions for inspection by rules that "
- + "depend on it via an <a href=\"globals.html#Actions\">Actions</a> "
- + "provider. The provider is also available to the rule itself by calling "
- + "<a href=\"ctx.html#created_actions\">ctx.created_actions()</a>."
- + "<br/><br/>"
- + "This should only be used for testing the analysis-time behavior of "
- + "Skylark rules. This flag may be removed in the future."
- ),
- @Param(
- name = "toolchains",
- type = SkylarkList.class,
- legacyNamed = true,
- generic1 = String.class,
- defaultValue = "[]",
- doc =
- "<i>(Experimental)</i><br/><br/>"
- + "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,
- legacyNamed = true,
- defaultValue = "''",
- doc = "A description of the rule that can be extracted by documentation generating tools."
- ),
- @Param(
- name = "provides",
- type = SkylarkList.class,
- named = true,
- positional = false,
- defaultValue = "[]",
- doc = PROVIDES_DOC
- ),
- @Param(
- name = "execution_platform_constraints_allowed",
- type = Boolean.class,
- named = true,
- positional = false,
- defaultValue = "False",
- doc =
- "If true, a special attribute named <code>exec_compatible_with</code> of "
- + "label-list type is added, which must not already exist in "
- + "<code>attrs</code>. Targets may use this attribute to specify additional "
- + "constraints on the execution platform beyond those given in the "
- + "<code>exec_compatible_with</code> argument to <code>rule()</code>."
- ),
- @Param(
- name = "exec_compatible_with",
- type = SkylarkList.class,
- generic1 = String.class,
- named = true,
- positional = false,
- defaultValue = "[]",
- doc =
- "A list of constraints on the execution platform that apply to all targets of "
- + "this rule type."
- )
- },
- useAst = true,
- useEnvironment = true
- )
+ name = "rule",
+ doc =
+ "Creates a new rule, which can be called from a BUILD file or a macro to create targets."
+ + "<p>Rules must be assigned to global variables in a .bzl file; the name of the "
+ + "global variable is the rule's name."
+ + "<p>Test rules are required to have a name ending in <code>_test</code>, while all "
+ + "other rules must not have this suffix. (This restriction applies only to rules, "
+ + "not to their targets.)",
+ parameters = {
+ @Param(
+ name = "implementation",
+ type = BaseFunction.class,
+ legacyNamed = true,
+ doc =
+ "the function implementing this rule, must have exactly one parameter: "
+ + "<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."),
+ @Param(
+ name = "test",
+ type = Boolean.class,
+ legacyNamed = true,
+ defaultValue = "False",
+ doc =
+ "Whether this rule is a test rule, that is, whether it may be the subject of a "
+ + "<code>blaze test</code> command. All test rules are automatically "
+ + "considered <a href='#rule.executable'>executable</a>; it is unnecessary "
+ + "(and discouraged) to explicitly set <code>executable = True</code> for a "
+ + "test rule. See the "
+ + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> "
+ + "for more information."),
+ @Param(
+ name = "attrs",
+ type = SkylarkDict.class,
+ legacyNamed = true,
+ 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=\"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>, <code>deprecation</code>, <code>tags</code>, "
+ + "<code>testonly</code>, and <code>features</code> are implicitly added and "
+ + "cannot be overridden."),
+ // TODO(bazel-team): need to give the types of these builtin attributes
+ @Param(
+ name = "outputs",
+ type = SkylarkDict.class,
+ legacyNamed = true,
+ callbackEnabled = true,
+ noneable = true,
+ defaultValue = "None",
+ doc =
+ "<b>Experimental:</b> This API is in the process of being redesigned."
+ + "<p>A schema for defining predeclared outputs. Unlike "
+ + "<a href='attr.html#output'><code>output</code></a> and "
+ + "<a href='attr.html#output_list'><code>output_list</code></a> attributes, "
+ + "the user does not specify the labels for these files. "
+ + "See the <a href='../rules.$DOC_EXT#files'>Rules page</a> for more on "
+ + "predeclared outputs."
+ + "<p>The value of this argument is either a dictionary or a callback function "
+ + "that produces a dictionary. The callback works similar to computed "
+ + "dependency attributes: The function's parameter names are matched against "
+ + "the rule's attributes, so for example if you pass "
+ + "<code>outputs = _my_func</code> with the definition "
+ + "<code>def _my_func(srcs, deps): ...</code>, the function has access "
+ + "to the attributes <code>srcs</code> and <code>deps</code>. Whether the "
+ + "dictionary is specified directly or via a function, it is interpreted as "
+ + "follows."
+ + "<p>Each entry in the dictionary creates a predeclared output where the key "
+ + "is an identifier and the value is a string template that determines the "
+ + "output's label. In the rule's implementation function, the identifier "
+ + "becomes the field name used to access the output's "
+ + "<a href='File.html'><code>File</code></a> in "
+ + "<a href='ctx.html#outputs'><code>ctx.outputs</code></a>. The output's label "
+ + "has the same package as the rule, and the part after the package is "
+ + "produced by substituting each placeholder of the form "
+ + "<code>\"%{ATTR}\"</code> with a string formed from the value of the "
+ + "attribute <code>ATTR</code>:"
+ + "<ul>"
+ + "<li>String-typed attributes are substituted verbatim."
+ + "<li>Label-typed attributes become the part of the label after the package, "
+ + "minus the file extension. For example, the label "
+ + "<code>\"//pkg:a/b.c\"</code> becomes <code>\"a/b\"</code>."
+ + "<li>Output-typed attributes become the part of the label after the package, "
+ + "including the file extension (for the above example, "
+ + "<code>\"a/b.c\"</code>)."
+ + "<li>All list-typed attributes (for example, <code>attr.label_list</code>) "
+ + "used in placeholders are required to have <i>exactly one element</i>. Their "
+ + "conversion is the same as their non-list version (<code>attr.label</code>)."
+ + "<li>Other attribute types may not appear in placeholders."
+ + "<li>The special non-attribute placeholders <code>%{dirname}</code> and "
+ + "<code>%{basename}</code> expand to those parts of the rule's label, "
+ + "excluding its package. For example, in <code>\"//pkg:a/b.c\"</code>, the "
+ + "dirname is <code>a</code> and the basename is <code>b.c</code>."
+ + "</ul>"
+ + "<p>In practice, the most common substitution placeholder is "
+ + "<code>\"%{name}\"</code>. For example, for a target named \"foo\", the "
+ + "outputs dict <code>{\"bin\": \"%{name}.exe\"}</code> predeclares an output "
+ + "named <code>foo.exe</code> that is accessible in the implementation "
+ + "function as <code>ctx.outputs.bin</code>."),
+ @Param(
+ name = "executable",
+ type = Boolean.class,
+ legacyNamed = true,
+ defaultValue = "False",
+ doc =
+ "Whether this rule is considered executable, that is, whether it may be the "
+ + "subject of a <code>blaze run</code> command. See the "
+ + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> "
+ + "for more information."),
+ @Param(
+ name = "output_to_genfiles",
+ type = Boolean.class,
+ legacyNamed = true,
+ defaultValue = "False",
+ doc =
+ "If true, the files will be generated in the genfiles directory instead of the "
+ + "bin directory. Unless you need it for compatibility with existing rules "
+ + "(e.g. when generating header files for C++), do not set this flag."),
+ @Param(
+ name = "fragments",
+ type = SkylarkList.class,
+ legacyNamed = true,
+ generic1 = String.class,
+ defaultValue = "[]",
+ doc =
+ "List of names of configuration fragments that the rule requires "
+ + "in target configuration."),
+ @Param(
+ name = "host_fragments",
+ type = SkylarkList.class,
+ legacyNamed = true,
+ generic1 = String.class,
+ defaultValue = "[]",
+ doc =
+ "List of names of configuration fragments that the rule requires "
+ + "in host configuration."),
+ @Param(
+ name = "_skylark_testable",
+ type = Boolean.class,
+ legacyNamed = true,
+ defaultValue = "False",
+ doc =
+ "<i>(Experimental)</i><br/><br/>"
+ + "If true, this rule will expose its actions for inspection by rules that "
+ + "depend on it via an <a href=\"globals.html#Actions\">Actions</a> "
+ + "provider. The provider is also available to the rule itself by calling "
+ + "<a href=\"ctx.html#created_actions\">ctx.created_actions()</a>."
+ + "<br/><br/>"
+ + "This should only be used for testing the analysis-time behavior of "
+ + "Skylark rules. This flag may be removed in the future."),
+ @Param(
+ name = "toolchains",
+ type = SkylarkList.class,
+ legacyNamed = true,
+ generic1 = String.class,
+ defaultValue = "[]",
+ doc =
+ "<i>(Experimental)</i><br/><br/>"
+ + "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,
+ legacyNamed = true,
+ defaultValue = "''",
+ doc =
+ "A description of the rule that can be extracted by documentation generating "
+ + "tools."),
+ @Param(
+ name = "provides",
+ type = SkylarkList.class,
+ named = true,
+ positional = false,
+ defaultValue = "[]",
+ doc = PROVIDES_DOC),
+ @Param(
+ name = "execution_platform_constraints_allowed",
+ type = Boolean.class,
+ named = true,
+ positional = false,
+ defaultValue = "False",
+ doc =
+ "If true, a special attribute named <code>exec_compatible_with</code> of "
+ + "label-list type is added, which must not already exist in "
+ + "<code>attrs</code>. Targets may use this attribute to specify additional "
+ + "constraints on the execution platform beyond those given in the "
+ + "<code>exec_compatible_with</code> argument to <code>rule()</code>."),
+ @Param(
+ name = "exec_compatible_with",
+ type = SkylarkList.class,
+ generic1 = String.class,
+ named = true,
+ positional = false,
+ defaultValue = "[]",
+ doc =
+ "A list of constraints on the execution platform that apply to all targets of "
+ + "this rule type."),
+ @Param(
+ name = "analysis_test",
+ allowedTypes = {
+ @ParamType(type = Boolean.class),
+ @ParamType(type = UnboundMarker.class)
+ },
+ named = true,
+ positional = false,
+ // TODO(cparsons): Make the default false when this is no longer experimental.
+ defaultValue = "unbound",
+ // TODO(cparsons): Link to in-build testing documentation when it is available.
+ doc =
+ "<b>Experimental: This parameter is experimental and subject to change at any "
+ + "time.</b><p> If true, then this rule is treated as an analysis test."),
+ },
+ useAst = true,
+ useEnvironment = true)
public BaseFunction rule(
BaseFunction implementation,
Boolean test,
@@ -317,6 +325,7 @@
SkylarkList<?> providesArg,
Boolean executionPlatformConstraintsAllowed,
SkylarkList<?> execCompatibleWith,
+ Object analysisTest,
FuncallExpression ast,
Environment funcallEnv)
throws EvalException;
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java
index aa99ba5..802db05 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/java/JavaCommonApi.java
@@ -367,12 +367,14 @@
named = true,
type = TransitiveInfoCollectionApi.class,
doc = "A label pointing to a java_toolchain rule to used to find the ijar tool."),
- })
+ },
+ useLocation = true)
public FileApi runIjar(
SkylarkActionFactoryT actions,
FileT jar,
Object targetLabel,
- TransitiveInfoCollectionT javaToolchain)
+ TransitiveInfoCollectionT javaToolchain,
+ Location location)
throws EvalException;
@SkylarkCallable(
@@ -412,10 +414,14 @@
named = true,
type = TransitiveInfoCollectionApi.class,
doc = "A label pointing to a java_toolchain rule to used to find the stamp_jar tool."),
- })
+ },
+ useLocation = true)
public FileApi stampJar(
- SkylarkActionFactoryT actions, FileT jar, Label targetLabel,
- TransitiveInfoCollectionT javaToolchain)
+ SkylarkActionFactoryT actions,
+ FileT jar,
+ Label targetLabel,
+ TransitiveInfoCollectionT javaToolchain,
+ Location location)
throws EvalException;
@SkylarkCallable(
@@ -466,14 +472,16 @@
type = TransitiveInfoCollectionApi.class,
doc = "A label pointing to a JDK to be used for packing sources."),
},
- allowReturnNones = true)
+ allowReturnNones = true,
+ useLocation = true)
public FileApi packSources(
SkylarkActionFactoryT actions,
FileT outputJar,
SkylarkList<FileT> sourceFiles,
SkylarkList<FileT> sourceJars,
TransitiveInfoCollectionT javaToolchain,
- TransitiveInfoCollectionT hostJavabase)
+ TransitiveInfoCollectionT hostJavabase,
+ Location location)
throws EvalException;
@SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
index 1c3d82b..29a7cb2 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
@@ -101,12 +101,25 @@
}
@Override
- public BaseFunction rule(BaseFunction implementation, Boolean test, Object attrs,
- Object implicitOutputs, Boolean executable, Boolean outputToGenfiles,
- SkylarkList<?> fragments, SkylarkList<?> hostFragments, Boolean skylarkTestable,
- SkylarkList<?> toolchains, String doc, SkylarkList<?> providesArg,
- Boolean executionPlatformConstraintsAllowed, SkylarkList<?> execCompatibleWith,
- FuncallExpression ast, Environment funcallEnv) throws EvalException {
+ public BaseFunction rule(
+ BaseFunction implementation,
+ Boolean test,
+ Object attrs,
+ Object implicitOutputs,
+ Boolean executable,
+ Boolean outputToGenfiles,
+ SkylarkList<?> fragments,
+ SkylarkList<?> hostFragments,
+ Boolean skylarkTestable,
+ SkylarkList<?> toolchains,
+ String doc,
+ SkylarkList<?> providesArg,
+ Boolean executionPlatformConstraintsAllowed,
+ SkylarkList<?> execCompatibleWith,
+ Object analysisTest,
+ FuncallExpression ast,
+ Environment funcallEnv)
+ throws EvalException {
List<AttributeInfo> attrInfos;
ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
if (attrs != null && attrs != Runtime.NONE) {
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java
index 8ca3718..c673f2b 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/java/FakeJavaCommon.java
@@ -61,21 +61,36 @@
}
@Override
- public FileApi runIjar(SkylarkActionFactoryApi actions, FileApi jar, Object targetLabel,
- TransitiveInfoCollectionApi javaToolchain) throws EvalException {
+ public FileApi runIjar(
+ SkylarkActionFactoryApi actions,
+ FileApi jar,
+ Object targetLabel,
+ TransitiveInfoCollectionApi javaToolchain,
+ Location location)
+ throws EvalException {
return null;
}
@Override
- public FileApi stampJar(SkylarkActionFactoryApi actions, FileApi jar, Label targetLabel,
- TransitiveInfoCollectionApi javaToolchain) throws EvalException {
+ public FileApi stampJar(
+ SkylarkActionFactoryApi actions,
+ FileApi jar,
+ Label targetLabel,
+ TransitiveInfoCollectionApi javaToolchain,
+ Location location)
+ throws EvalException {
return null;
}
@Override
- public FileApi packSources(SkylarkActionFactoryApi actions, FileApi outputJar,
- SkylarkList<FileApi> sourceFiles, SkylarkList<FileApi> sourceJars,
- TransitiveInfoCollectionApi javaToolchain, TransitiveInfoCollectionApi hostJavabase)
+ public FileApi packSources(
+ SkylarkActionFactoryApi actions,
+ FileApi outputJar,
+ SkylarkList<FileApi> sourceFiles,
+ SkylarkList<FileApi> sourceJars,
+ TransitiveInfoCollectionApi javaToolchain,
+ TransitiveInfoCollectionApi hostJavabase,
+ Location location)
throws EvalException {
return null;
}