diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java index 441b31b9175803..fa5441ec33909b 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java @@ -78,7 +78,6 @@ import com.google.devtools.build.lib.packages.MacroClass; import com.google.devtools.build.lib.packages.MacroInstance; import com.google.devtools.build.lib.packages.Package; -import com.google.devtools.build.lib.packages.Package.NameConflictException; import com.google.devtools.build.lib.packages.PredicateWithMessage; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; @@ -93,6 +92,7 @@ import com.google.devtools.build.lib.packages.StarlarkExportable; import com.google.devtools.build.lib.packages.StarlarkProvider; import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.TargetUtils; import com.google.devtools.build.lib.packages.Type; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodRepoRuleCreator.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodRepoRuleCreator.java index 356b933488f42a..a05150814b86c7 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodRepoRuleCreator.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodRepoRuleCreator.java @@ -22,12 +22,12 @@ import com.google.devtools.build.lib.events.ExtendedEventHandler; import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.Package; -import com.google.devtools.build.lib.packages.Package.NameConflictException; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleFactory; import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap; import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import com.google.devtools.build.lib.vfs.Root; import com.google.devtools.build.lib.vfs.RootedPath; diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java index 8ae318f024de68..f5a3c2415d4861 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java @@ -36,13 +36,13 @@ import com.google.devtools.build.lib.packages.BazelStarlarkContext; import com.google.devtools.build.lib.packages.BzlInitThreadContext; import com.google.devtools.build.lib.packages.Package; -import com.google.devtools.build.lib.packages.Package.NameConflictException; import com.google.devtools.build.lib.packages.PackageFactory; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException; import com.google.devtools.build.lib.packages.RuleFunction; import com.google.devtools.build.lib.packages.StarlarkExportable; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.WorkspaceFactoryHelper; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import com.google.devtools.build.lib.starlarkbuildapi.repository.RepositoryModuleApi; diff --git a/src/main/java/com/google/devtools/build/lib/packages/BuildGlobals.java b/src/main/java/com/google/devtools/build/lib/packages/BuildGlobals.java index 7a6b2489400b73..ab0604a2882253 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/BuildGlobals.java +++ b/src/main/java/com/google/devtools/build/lib/packages/BuildGlobals.java @@ -18,6 +18,7 @@ import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.packages.License.DistributionType; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.Type.ConversionException; import com.google.devtools.build.lib.server.FailureDetails.PackageLoading.Code; import java.util.List; @@ -94,7 +95,7 @@ public NoneType environmentGroup( return Starlark.NONE; } catch (LabelSyntaxException e) { throw Starlark.errorf("environment group has invalid name: %s: %s", name, e.getMessage()); - } catch (Package.NameConflictException e) { + } catch (NameConflictException e) { throw Starlark.errorf("%s", e.getMessage()); } } diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java index c8b30c105e832e..b2817c115f1d1b 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Package.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java @@ -118,20 +118,6 @@ public class Package { /** Sentinel value for package overhead being empty. */ private static final long PACKAGE_OVERHEAD_UNSET = -1; - /** - * An exception used when the name of a target or symbolic macro clashes with another entity - * defined in the package. - * - *

Common examples of conflicts include two targets or symbolic macros sharing the same name, - * and one output file being a prefix of another. See {@link #checkForExistingName} and {@link - * #checkRuleAndOutputs} for more details. - */ - public static final class NameConflictException extends Exception { - private NameConflictException(String message) { - super(message); - } - } - /** * The collection of all targets defined in this package, indexed by name. * @@ -864,7 +850,7 @@ private static DetailedExitCode createDetailedCode(String errorMessage, Code cod * A builder for {@link Package} objects. Only intended to be used by {@link PackageFactory} and * {@link com.google.devtools.build.lib.skyframe.PackageFunction}. */ - public static class Builder extends BazelStarlarkContext { + public static class Builder extends TargetDefinitionContext { /** * A bundle of options affecting package construction, that is not specific to any particular diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java index 0c065a1cbaf887..4be90fa78e0943 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java +++ b/src/main/java/com/google/devtools/build/lib/packages/RuleFactory.java @@ -20,8 +20,8 @@ import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.packages.Attribute.StarlarkComputedDefaultTemplate.CannotPrecomputeDefaultsException; -import com.google.devtools.build.lib.packages.Package.NameConflictException; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.Map; @@ -291,7 +291,7 @@ public NoneType call(StarlarkThread thread, Tuple args, Dict kwa .getSemantics() .getBool(BuildLanguageOptions.INCOMPATIBLE_FAIL_ON_UNKNOWN_ATTRIBUTES), thread.getCallStack()); - } catch (RuleFactory.InvalidRuleException | Package.NameConflictException e) { + } catch (RuleFactory.InvalidRuleException | NameConflictException e) { throw new EvalException(e); } return Starlark.NONE; diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java index 68cc6342338c79..e759f5c65a16ef 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java +++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java @@ -33,6 +33,7 @@ import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.io.FileSymlinkException; import com.google.devtools.build.lib.packages.Globber.BadGlobException; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import com.google.devtools.build.lib.server.FailureDetails.PackageLoading.Code; import com.google.devtools.build.lib.starlarkbuildapi.StarlarkNativeModuleApi; @@ -557,7 +558,7 @@ public NoneType packageGroup( return Starlark.NONE; } catch (LabelSyntaxException e) { throw Starlark.errorf("package group has invalid name: %s: %s", name, e.getMessage()); - } catch (Package.NameConflictException e) { + } catch (NameConflictException e) { throw new EvalException(e); } } @@ -598,7 +599,7 @@ public NoneType exportsFiles( } pkgBuilder.setVisibilityAndLicense(inputFile, visibility, license); - } catch (Package.NameConflictException e) { + } catch (NameConflictException e) { throw Starlark.errorf("%s", e.getMessage()); } } diff --git a/src/main/java/com/google/devtools/build/lib/packages/TargetDefinitionContext.java b/src/main/java/com/google/devtools/build/lib/packages/TargetDefinitionContext.java new file mode 100644 index 00000000000000..df871affbab215 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/packages/TargetDefinitionContext.java @@ -0,0 +1,68 @@ +// Copyright 2024 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.packages; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import javax.annotation.Nullable; +import net.starlark.java.eval.EvalException; +import net.starlark.java.eval.Starlark; +import net.starlark.java.eval.StarlarkThread; + +/** + * A context object, usually stored in a {@link StarlarkThread}, upon which rules and symbolic + * macros can be instantiated. + */ +// TODO(#19922): Elevate some Package.Builder methods to this class. +public abstract class TargetDefinitionContext extends BazelStarlarkContext { + + /** + * An exception used when the name of a target or symbolic macro clashes with another entity + * defined in the package. + * + *

Common examples of conflicts include two targets or symbolic macros sharing the same name, + * and one output file being a prefix of another. See {@link Package.Builder#checkForExistingName} + * and {@link Package.Builder#checkRuleAndOutputs} for more details. + */ + public static final class NameConflictException extends Exception { + public NameConflictException(String message) { + super(message); + } + } + + protected TargetDefinitionContext(Phase phase, SymbolGenerator symbolGenerator) { + super(phase, symbolGenerator); + } + + /** Retrieves this object from a Starlark thread. Returns null if not present. */ + @Nullable + public static TargetDefinitionContext fromOrNull(StarlarkThread thread) { + BazelStarlarkContext ctx = thread.getThreadLocal(BazelStarlarkContext.class); + return (ctx instanceof TargetDefinitionContext) ? (TargetDefinitionContext) ctx : null; + } + + /** + * Retrieves this object from a Starlark thread. If not present, throws {@code EvalException} with + * an error message indicating that {@code what} can't be used in this Starlark environment. + */ + @CanIgnoreReturnValue + public static TargetDefinitionContext fromOrFail(StarlarkThread thread, String what) + throws EvalException { + @Nullable BazelStarlarkContext ctx = thread.getThreadLocal(BazelStarlarkContext.class); + if (!(ctx instanceof TargetDefinitionContext)) { + throw Starlark.errorf("%s can only be used while evaluating a BUILD file or macro", what); + } + return (TargetDefinitionContext) ctx; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java index afe4f57d3b2269..7c9bb1ed6a7a60 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java +++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java @@ -19,7 +19,7 @@ import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.NullEventHandler; -import com.google.devtools.build.lib.packages.Package.NameConflictException; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.server.FailureDetails; import com.google.devtools.build.lib.server.FailureDetails.PackageLoading; import com.google.devtools.build.lib.vfs.Path; @@ -266,7 +266,7 @@ public Object call(StarlarkThread thread, Tuple args, Dict kwarg thread.getCallStack()); RepositoryName.validateUserProvidedRepoName(rule.getName()); } catch (RuleFactory.InvalidRuleException - | Package.NameConflictException + | NameConflictException | LabelSyntaxException e) { throw new EvalException(e); } diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java index 935206869a76a6..bd2b1b72ae24b7 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java +++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java @@ -25,6 +25,7 @@ import com.google.devtools.build.lib.cmdline.TargetParsingException; import com.google.devtools.build.lib.cmdline.TargetPattern; import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.Map; import java.util.stream.Collectors; @@ -50,7 +51,7 @@ public static Rule createAndAddRepositoryRule( Map kwargs, ImmutableList callstack) throws RuleFactory.InvalidRuleException, - Package.NameConflictException, + NameConflictException, LabelSyntaxException, InterruptedException { BuildLangTypedAttributeValuesMap attributeValues = new BuildLangTypedAttributeValuesMap(kwargs); @@ -155,7 +156,7 @@ static void addBindRule( Label virtual, Label actual, ImmutableList callstack) - throws RuleFactory.InvalidRuleException, Package.NameConflictException, InterruptedException { + throws RuleFactory.InvalidRuleException, NameConflictException, InterruptedException { Map attributes = Maps.newHashMap(); // Bound rules don't have a name field, but this works because we don't want more than one @@ -170,8 +171,7 @@ static void addBindRule( overwriteRule(pkg, rule); } - private static void overwriteRule(Package.Builder pkg, Rule rule) - throws Package.NameConflictException { + private static void overwriteRule(Package.Builder pkg, Rule rule) throws NameConflictException { Preconditions.checkArgument(rule.getOutputFiles().isEmpty()); Target old = pkg.getTarget(rule.getName()); if (old != null) { diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java index 3246811becabd6..be7cf5200442ca 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java +++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java @@ -29,6 +29,7 @@ import com.google.devtools.build.lib.cmdline.TargetParsingException; import com.google.devtools.build.lib.cmdline.TargetPattern; import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.starlarkbuildapi.WorkspaceGlobalsApi; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.List; @@ -142,7 +143,7 @@ public void bind(String name, Object actual, StarlarkThread thread) (String) actual, RepoContext.of(currentRepo, builder.getRepositoryMappingFor(currentRepo))), thread.getCallStack()); - } catch (InvalidRuleException | Package.NameConflictException | LabelSyntaxException e) { + } catch (InvalidRuleException | NameConflictException | LabelSyntaxException e) { throw Starlark.errorf("%s", e.getMessage()); } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java index afb76f4c9b710f..5700e6d4612b07 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java @@ -24,8 +24,8 @@ import com.google.devtools.build.lib.packages.AggregatingAttributeMapper; import com.google.devtools.build.lib.packages.ErrorDeterminingRepositoryException; import com.google.devtools.build.lib.packages.Package; -import com.google.devtools.build.lib.packages.Package.NameConflictException; import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.Type; import com.google.devtools.build.lib.packages.WorkspaceFileValue; import com.google.devtools.build.lib.repository.ExternalPackageHelper; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java index e9f6375ea5c06b..fd7c31b4af1b9f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java @@ -36,9 +36,9 @@ import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException; import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.Package; -import com.google.devtools.build.lib.packages.Package.NameConflictException; import com.google.devtools.build.lib.packages.PackageFactory; import com.google.devtools.build.lib.packages.RuleClassProvider; +import com.google.devtools.build.lib.packages.TargetDefinitionContext.NameConflictException; import com.google.devtools.build.lib.packages.WorkspaceFactory; import com.google.devtools.build.lib.packages.WorkspaceFileValue; import com.google.devtools.build.lib.packages.WorkspaceFileValue.WorkspaceFileKey;