|
100 | 100 | import com.google.errorprone.annotations.FormatMethod;
|
101 | 101 | import java.util.Collection;
|
102 | 102 | import java.util.Map;
|
103 |
| -import java.util.regex.Pattern; |
| 103 | +import java.util.Objects; |
104 | 104 | import javax.annotation.Nullable;
|
105 | 105 | import net.starlark.java.eval.Debug;
|
106 | 106 | import net.starlark.java.eval.Dict;
|
|
112 | 112 | import net.starlark.java.eval.StarlarkCallable;
|
113 | 113 | import net.starlark.java.eval.StarlarkFunction;
|
114 | 114 | import net.starlark.java.eval.StarlarkInt;
|
115 |
| -import net.starlark.java.eval.StarlarkList; |
116 | 115 | import net.starlark.java.eval.StarlarkThread;
|
117 | 116 | import net.starlark.java.eval.Tuple;
|
118 | 117 | import net.starlark.java.syntax.Identifier;
|
@@ -140,7 +139,6 @@ public Label load(String from) throws Exception {
|
140 | 139 | }
|
141 | 140 | }
|
142 | 141 | });
|
143 |
| - private static final Pattern RULE_NAME_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*"); |
144 | 142 |
|
145 | 143 | // TODO(bazel-team): Remove the code duplication (BaseRuleClasses and this class).
|
146 | 144 | /** Parent rule class for non-executable non-test Starlark rules. */
|
@@ -308,6 +306,51 @@ public StarlarkRuleFunction rule(
|
308 | 306 | Object name,
|
309 | 307 | StarlarkThread thread)
|
310 | 308 | throws EvalException {
|
| 309 | + return createRule( |
| 310 | + implementation, |
| 311 | + test, |
| 312 | + attrs, |
| 313 | + implicitOutputs, |
| 314 | + executable, |
| 315 | + outputToGenfiles, |
| 316 | + fragments, |
| 317 | + hostFragments, |
| 318 | + starlarkTestable, |
| 319 | + toolchains, |
| 320 | + useToolchainTransition, |
| 321 | + providesArg, |
| 322 | + execCompatibleWith, |
| 323 | + analysisTest, |
| 324 | + buildSetting, |
| 325 | + cfg, |
| 326 | + execGroups, |
| 327 | + compileOneFiletype, |
| 328 | + name, |
| 329 | + thread); |
| 330 | + } |
| 331 | + |
| 332 | + public static StarlarkRuleFunction createRule( |
| 333 | + StarlarkFunction implementation, |
| 334 | + boolean test, |
| 335 | + Object attrs, |
| 336 | + Object implicitOutputs, |
| 337 | + boolean executable, |
| 338 | + boolean outputToGenfiles, |
| 339 | + Sequence<?> fragments, |
| 340 | + Sequence<?> hostFragments, |
| 341 | + boolean starlarkTestable, |
| 342 | + Sequence<?> toolchains, |
| 343 | + boolean useToolchainTransition, |
| 344 | + Sequence<?> providesArg, |
| 345 | + Sequence<?> execCompatibleWith, |
| 346 | + Object analysisTest, |
| 347 | + Object buildSetting, |
| 348 | + Object cfg, |
| 349 | + Object execGroups, |
| 350 | + Object compileOneFiletype, |
| 351 | + Object name, |
| 352 | + StarlarkThread thread) |
| 353 | + throws EvalException { |
311 | 354 | BazelStarlarkContext bazelContext = BazelStarlarkContext.from(thread);
|
312 | 355 | bazelContext.checkLoadingOrWorkspacePhase("rule");
|
313 | 356 | // analysis_test=true implies test=true.
|
@@ -510,81 +553,6 @@ public StarlarkRuleFunction rule(
|
510 | 553 | return starlarkRuleFunction;
|
511 | 554 | }
|
512 | 555 |
|
513 |
| - @Override |
514 |
| - public void analysisTest( |
515 |
| - String name, |
516 |
| - StarlarkFunction implementation, |
517 |
| - Object attrs, |
518 |
| - Sequence<?> fragments, |
519 |
| - Sequence<?> toolchains, |
520 |
| - Object attrValuesApi, |
521 |
| - StarlarkThread thread) |
522 |
| - throws EvalException, InterruptedException { |
523 |
| - if (!RULE_NAME_PATTERN.matcher(name).matches()) { |
524 |
| - throw Starlark.errorf("'name' is limited to Starlark identifiers, got %s", name); |
525 |
| - } |
526 |
| - Dict<String, Object> attrValues = |
527 |
| - Dict.cast(attrValuesApi, String.class, Object.class, "attr_values"); |
528 |
| - if (attrValues.containsKey("name")) { |
529 |
| - throw Starlark.errorf("'name' cannot be set or overridden in 'attr_values'"); |
530 |
| - } |
531 |
| - |
532 |
| - StarlarkRuleFunction starlarkRuleFunction = |
533 |
| - rule( |
534 |
| - implementation, |
535 |
| - /*test=*/ true, |
536 |
| - attrs, |
537 |
| - /*implicitOutputs=*/ Starlark.NONE, |
538 |
| - /*executable=*/ false, |
539 |
| - /*outputToGenfiles=*/ false, |
540 |
| - /*fragments=*/ fragments, |
541 |
| - /*hostFragments=*/ StarlarkList.empty(), |
542 |
| - /*starlarkTestable=*/ false, |
543 |
| - /*toolchains=*/ toolchains, |
544 |
| - /*useToolchainTransition=*/ false, |
545 |
| - /*doc=*/ "", |
546 |
| - /*providesArg=*/ StarlarkList.empty(), |
547 |
| - /*execCompatibleWith=*/ StarlarkList.empty(), |
548 |
| - /*analysisTest=*/ Boolean.TRUE, |
549 |
| - /*buildSetting=*/ Starlark.NONE, |
550 |
| - /*cfg=*/ Starlark.NONE, |
551 |
| - /*execGroups=*/ Starlark.NONE, |
552 |
| - /*compileOneFiletype=*/ Starlark.NONE, |
553 |
| - /*name=*/ Starlark.NONE, |
554 |
| - thread); |
555 |
| - |
556 |
| - // Export the rule |
557 |
| - // Because exporting can raise multiple errors, we need to accumulate them here into a single |
558 |
| - // EvalException. This is a code smell because any non-ERROR events will be lost, and any |
559 |
| - // location information in the events will be overwritten by the location of this rule's |
560 |
| - // definition. |
561 |
| - // However, this is currently fine because StarlarkRuleFunction#export only creates events that |
562 |
| - // are ERRORs and that have the rule definition as their location. |
563 |
| - // TODO(brandjon): Instead of accumulating events here, consider registering the rule in the |
564 |
| - // BazelStarlarkContext, and exporting such rules after module evaluation in |
565 |
| - // BzlLoadFunction#execAndExport. |
566 |
| - PackageContext pkgContext = thread.getThreadLocal(PackageContext.class); |
567 |
| - StoredEventHandler handler = new StoredEventHandler(); |
568 |
| - starlarkRuleFunction.export( |
569 |
| - handler, pkgContext.getLabel(), name + "_test"); // export in BUILD thread |
570 |
| - if (handler.hasErrors()) { |
571 |
| - StringBuilder errors = |
572 |
| - handler.getEvents().stream() |
573 |
| - .filter(e -> e.getKind() == EventKind.ERROR) |
574 |
| - .reduce( |
575 |
| - new StringBuilder(), |
576 |
| - (sb, ev) -> sb.append("\n").append(ev.getMessage()), |
577 |
| - StringBuilder::append); |
578 |
| - throw Starlark.errorf("Errors in exporting %s: %s", name, errors.toString()); |
579 |
| - } |
580 |
| - |
581 |
| - // Instantiate the target |
582 |
| - Dict.Builder<String, Object> args = Dict.builder(); |
583 |
| - args.put("name", name); |
584 |
| - args.putAll(attrValues); |
585 |
| - starlarkRuleFunction.call(thread, Tuple.of(), args.buildImmutable()); |
586 |
| - } |
587 |
| - |
588 | 556 | /**
|
589 | 557 | * Returns the module (file) of the outermost enclosing Starlark function on the call stack or
|
590 | 558 | * null if none of the active calls are functions defined in Starlark.
|
@@ -1002,6 +970,7 @@ private void errorf(EventHandler handler, String format, Object... args) {
|
1002 | 970 | handler.handle(Event.error(definitionLocation, String.format(format, args)));
|
1003 | 971 | }
|
1004 | 972 |
|
| 973 | + @Override |
1005 | 974 | public RuleClass getRuleClass() {
|
1006 | 975 | Preconditions.checkState(ruleClass != null && builder == null);
|
1007 | 976 | return ruleClass;
|
|
0 commit comments