|  | // Copyright 2023 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.auto.value.AutoValue; | 
|  | import com.google.common.base.Joiner; | 
|  | import com.google.common.collect.ImmutableList; | 
|  | import com.google.common.collect.ImmutableSet; | 
|  | import com.google.common.collect.ImmutableSortedSet; | 
|  | import com.google.devtools.build.lib.analysis.config.FeatureSet; | 
|  | import com.google.devtools.build.lib.cmdline.Label; | 
|  | import com.google.devtools.build.lib.collect.CollectionUtils; | 
|  | import com.google.devtools.build.lib.packages.License.DistributionType; | 
|  | import com.google.errorprone.annotations.CanIgnoreReturnValue; | 
|  | import java.util.List; | 
|  | import java.util.Set; | 
|  | import javax.annotation.Nullable; | 
|  | import net.starlark.java.eval.EvalException; | 
|  | import net.starlark.java.eval.Starlark; | 
|  |  | 
|  | /** | 
|  | * A group of {@link Package} argument values that may be provided by `package()` or `repo()` calls. | 
|  | */ | 
|  | @AutoValue | 
|  | public abstract class PackageArgs { | 
|  | public static final PackageArgs DEFAULT = | 
|  | PackageArgs.builder() | 
|  | .setDefaultVisibility(RuleVisibility.PRIVATE) | 
|  | .setDefaultTestOnly(false) | 
|  | .setFeatures(FeatureSet.EMPTY) | 
|  | .setLicense(License.NO_LICENSE) | 
|  | .setDistribs(License.DEFAULT_DISTRIB) | 
|  | .setDefaultCompatibleWith(ImmutableSet.of()) | 
|  | .setDefaultRestrictedTo(ImmutableSet.of()) | 
|  | .setDefaultPackageMetadata(ImmutableList.of()) | 
|  | .build(); | 
|  |  | 
|  | /** See {@link Package#getDefaultVisibility()}. */ | 
|  | @Nullable | 
|  | abstract RuleVisibility defaultVisibility(); | 
|  |  | 
|  | /** See {@link Package#getDefaultTestOnly()}. */ | 
|  | @Nullable | 
|  | abstract Boolean defaultTestOnly(); | 
|  |  | 
|  | /** See {@link Package#getDefaultDeprecation()}. */ | 
|  | @Nullable | 
|  | abstract String defaultDeprecation(); | 
|  |  | 
|  | /** See {@link Package#getFeatures()}. */ | 
|  | abstract FeatureSet features(); | 
|  |  | 
|  | /** See {@link Package#getDefaultLicense()}. */ | 
|  | @Nullable | 
|  | abstract License license(); | 
|  |  | 
|  | /** See {@link Package#getDefaultDistribs()}. */ | 
|  | @Nullable | 
|  | abstract ImmutableSet<DistributionType> distribs(); | 
|  |  | 
|  | /** See {@link Package#getDefaultCompatibleWith()}. */ | 
|  | @Nullable | 
|  | abstract ImmutableSet<Label> defaultCompatibleWith(); | 
|  |  | 
|  | /** See {@link Package#getDefaultRestrictedTo()}. */ | 
|  | @Nullable | 
|  | abstract ImmutableSet<Label> defaultRestrictedTo(); | 
|  |  | 
|  | /** See {@link Package#getDefaultPackageMetadata()}. */ | 
|  | @Nullable | 
|  | abstract ImmutableList<Label> defaultPackageMetadata(); | 
|  |  | 
|  | public static Builder builder() { | 
|  | return new AutoValue_PackageArgs.Builder().setFeatures(FeatureSet.EMPTY); | 
|  | } | 
|  |  | 
|  | abstract Builder toBuilder(); | 
|  |  | 
|  | /** Builder type for {@link PackageArgs}. */ | 
|  | @AutoValue.Builder | 
|  | public abstract static class Builder { | 
|  | public abstract Builder setDefaultVisibility(RuleVisibility x); | 
|  |  | 
|  | public abstract Builder setDefaultTestOnly(Boolean x); | 
|  |  | 
|  | public abstract Builder setDefaultDeprecation(String x); | 
|  |  | 
|  | abstract FeatureSet features(); | 
|  |  | 
|  | public abstract Builder setFeatures(FeatureSet x); | 
|  |  | 
|  | @CanIgnoreReturnValue | 
|  | public final Builder mergeFeatures(FeatureSet x) { | 
|  | return setFeatures(FeatureSet.merge(features(), x)); | 
|  | } | 
|  |  | 
|  | public abstract Builder setLicense(License x); | 
|  |  | 
|  | public abstract Builder setDistribs(Set<DistributionType> x); | 
|  |  | 
|  | /** Note that we don't check dupes in this method. Check beforehand! */ | 
|  | public abstract Builder setDefaultCompatibleWith(Iterable<Label> x); | 
|  |  | 
|  | /** Note that we don't check dupes in this method. Check beforehand! */ | 
|  | public abstract Builder setDefaultRestrictedTo(Iterable<Label> x); | 
|  |  | 
|  | @Nullable | 
|  | abstract ImmutableList<Label> defaultPackageMetadata(); | 
|  |  | 
|  | /** Note that we don't check dupes in this method. Check beforehand! */ | 
|  | public abstract Builder setDefaultPackageMetadata(List<Label> x); | 
|  |  | 
|  | public abstract PackageArgs build(); | 
|  | } | 
|  |  | 
|  | private static void throwIfHasDupes(List<Label> labels, String what) throws EvalException { | 
|  | var dupes = ImmutableSortedSet.copyOf(CollectionUtils.duplicatedElementsOf(labels)); | 
|  | if (!dupes.isEmpty()) { | 
|  | throw Starlark.errorf("duplicate label(s) in %s: %s", what, Joiner.on(", ").join(dupes)); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Processes the given Starlark parameter to the {@code package()/repo()} call into a field on a | 
|  | * {@link Builder} object. | 
|  | */ | 
|  | public static void processParam( | 
|  | String name, Object rawValue, String what, LabelConverter labelConverter, Builder builder) | 
|  | throws EvalException { | 
|  | if (name.equals("default_visibility")) { | 
|  | List<Label> value = BuildType.LABEL_LIST.convert(rawValue, what, labelConverter); | 
|  | builder.setDefaultVisibility(RuleVisibility.parse(value)); | 
|  |  | 
|  | } else if (name.equals("default_testonly")) { | 
|  | Boolean value = Type.BOOLEAN.convert(rawValue, what, labelConverter); | 
|  | builder.setDefaultTestOnly(value); | 
|  |  | 
|  | } else if (name.equals("default_deprecation")) { | 
|  | String value = Type.STRING.convert(rawValue, what, labelConverter); | 
|  | builder.setDefaultDeprecation(value); | 
|  |  | 
|  | } else if (name.equals("features")) { | 
|  | List<String> value = Type.STRING_LIST.convert(rawValue, what, labelConverter); | 
|  | builder.mergeFeatures(FeatureSet.parse(value)); | 
|  |  | 
|  | } else if (name.equals("licenses")) { | 
|  | License value = BuildType.LICENSE.convert(rawValue, what, labelConverter); | 
|  | builder.setLicense(value); | 
|  |  | 
|  | } else if (name.equals("distribs")) { | 
|  | Set<DistributionType> value = BuildType.DISTRIBUTIONS.convert(rawValue, what, labelConverter); | 
|  | builder.setDistribs(value); | 
|  |  | 
|  | } else if (name.equals("default_compatible_with")) { | 
|  | List<Label> value = BuildType.LABEL_LIST.convert(rawValue, what, labelConverter); | 
|  | throwIfHasDupes(value, name); | 
|  | builder.setDefaultCompatibleWith(value); | 
|  |  | 
|  | } else if (name.equals("default_restricted_to")) { | 
|  | List<Label> value = BuildType.LABEL_LIST.convert(rawValue, what, labelConverter); | 
|  | throwIfHasDupes(value, name); | 
|  | builder.setDefaultRestrictedTo(value); | 
|  |  | 
|  | } else if (name.equals("default_applicable_licenses") | 
|  | || name.equals("default_package_metadata")) { | 
|  | List<Label> value = BuildType.LABEL_LIST.convert(rawValue, what, labelConverter); | 
|  | if (builder.defaultPackageMetadata() != null) { | 
|  | throw Starlark.errorf( | 
|  | "Can not set both default_package_metadata and default_applicable_licenses." | 
|  | + " Move all declarations to default_package_metadata."); | 
|  | } | 
|  | throwIfHasDupes(value, name); | 
|  | builder.setDefaultPackageMetadata(value); | 
|  |  | 
|  | } else { | 
|  | throw Starlark.errorf("unexpected keyword argument: %s", name); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a new {@link PackageArgs} containing the result of merging {@code other} into {@code | 
|  | * this}. {@code other}'s fields take precedence if specified. | 
|  | */ | 
|  | public PackageArgs mergeWith(PackageArgs other) { | 
|  | Builder builder = toBuilder(); | 
|  | if (other.defaultVisibility() != null) { | 
|  | builder.setDefaultVisibility(other.defaultVisibility()); | 
|  | } | 
|  | if (other.defaultTestOnly() != null) { | 
|  | builder.setDefaultTestOnly(other.defaultTestOnly()); | 
|  | } | 
|  | if (other.defaultDeprecation() != null) { | 
|  | builder.setDefaultDeprecation(other.defaultDeprecation()); | 
|  | } | 
|  | if (!other.features().equals(FeatureSet.EMPTY)) { | 
|  | builder.mergeFeatures(other.features()); | 
|  | } | 
|  | if (other.license() != null) { | 
|  | builder.setLicense(other.license()); | 
|  | } | 
|  | if (other.distribs() != null) { | 
|  | builder.setDistribs(other.distribs()); | 
|  | } | 
|  | if (other.defaultCompatibleWith() != null) { | 
|  | builder.setDefaultCompatibleWith(other.defaultCompatibleWith()); | 
|  | } | 
|  | if (other.defaultRestrictedTo() != null) { | 
|  | builder.setDefaultRestrictedTo(other.defaultRestrictedTo()); | 
|  | } | 
|  | if (other.defaultPackageMetadata() != null) { | 
|  | builder.setDefaultPackageMetadata(other.defaultPackageMetadata()); | 
|  | } | 
|  | return builder.build(); | 
|  | } | 
|  | } |