blob: ef6496c2117acc830923c8912673d8439eb919a7 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.packages;
16
Greg Estren4ccabd32017-03-14 17:12:45 +000017import static com.google.common.collect.Sets.newEnumSet;
18
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019import com.google.common.annotations.VisibleForTesting;
Marian Lobur702cad72015-09-02 09:53:58 +000020import com.google.common.base.Function;
tomlua155b532017-11-08 20:12:47 +010021import com.google.common.base.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010022import com.google.common.base.Predicate;
23import com.google.common.base.Predicates;
Greg Estren9d837842016-12-01 21:36:59 +000024import com.google.common.base.Verify;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.common.collect.ImmutableList;
Googler74558fc2016-05-06 21:47:42 +000026import com.google.common.collect.ImmutableMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027import com.google.common.collect.ImmutableSet;
28import com.google.common.collect.Iterables;
Florian Weikertea6c82d2016-09-05 12:15:31 +000029import com.google.common.collect.Ordering;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.common.collect.Sets;
Liam Miller-Cushonbbae4d92016-05-03 18:23:03 +000031import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
gregcebe55e112018-01-30 11:04:53 -080032import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
gregce7fa23ea2018-01-18 12:46:04 -080033import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
gregce74a895d2018-05-29 11:26:03 -070034import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
gregce6bc35ed2017-12-22 11:51:39 -080035import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
janakra56a6ad2018-02-02 15:52:22 -080036import com.google.devtools.build.lib.cmdline.Label;
Florian Weikertea6c82d2016-09-05 12:15:31 +000037import com.google.devtools.build.lib.events.EventHandler;
Dmitry Lomovf188dc22016-07-19 09:00:55 +000038import com.google.devtools.build.lib.events.Location;
gregceda4c9592017-07-27 22:09:34 +020039import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassNamePredicate;
mjhalupka7b398f92018-03-08 12:08:25 -080040import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
mjhalupkacfa0bb72018-03-12 12:43:15 -070041import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
cparsonse29c1832018-05-25 14:55:00 -070042import com.google.devtools.build.lib.skylarkbuildapi.SplitTransitionProviderApi;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043import com.google.devtools.build.lib.syntax.ClassObject;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044import com.google.devtools.build.lib.syntax.EvalException;
Florian Weikertea6c82d2016-09-05 12:15:31 +000045import com.google.devtools.build.lib.syntax.EvalUtils;
46import com.google.devtools.build.lib.syntax.Runtime;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000048import com.google.devtools.build.lib.syntax.Type;
49import com.google.devtools.build.lib.syntax.Type.ConversionException;
Michael Staiba751f922017-02-14 15:50:04 +000050import com.google.devtools.build.lib.syntax.Type.LabelClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010051import com.google.devtools.build.lib.util.FileType;
52import com.google.devtools.build.lib.util.FileTypeSet;
53import com.google.devtools.build.lib.util.StringUtil;
Florian Weikertea6c82d2016-09-05 12:15:31 +000054import java.util.ArrayList;
Carmi Grushkoe80cccd2015-11-11 19:12:31 +000055import java.util.Arrays;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010056import java.util.Collection;
57import java.util.EnumSet;
58import java.util.HashMap;
Dmitry Lomovf188dc22016-07-19 09:00:55 +000059import java.util.LinkedHashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060import java.util.List;
61import java.util.Map;
janakr9ba46f82018-03-13 13:07:52 -070062import java.util.Objects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010063import java.util.Set;
Florian Weikertea6c82d2016-09-05 12:15:31 +000064import java.util.concurrent.atomic.AtomicReference;
vladmos9c787fa2017-07-04 11:45:22 -040065import javax.annotation.Nullable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010066import javax.annotation.concurrent.Immutable;
67
68/**
mjhalupkacfa0bb72018-03-12 12:43:15 -070069 * Metadata of a rule attribute. Contains the attribute name and type, and an default value to be
70 * used if none is provided in a rule declaration in a BUILD file. Attributes are immutable, and may
71 * be shared by more than one rule (for example, <code>foo_binary</code> and <code>foo_library
72 * </code> may share many attributes in common).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073 */
74@Immutable
mjhalupkacfa0bb72018-03-12 12:43:15 -070075@AutoCodec
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010076public final class Attribute implements Comparable<Attribute> {
77
Googler72f3a102017-12-01 16:28:28 -080078 public static final RuleClassNamePredicate ANY_RULE = RuleClassNamePredicate.unspecified();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079
Googler72f3a102017-12-01 16:28:28 -080080 public static final RuleClassNamePredicate NO_RULE = RuleClassNamePredicate.only();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010081
mjhalupkacfa0bb72018-03-12 12:43:15 -070082 /** Wraps the information necessary to construct an Aspect. */
83 @VisibleForSerialization
84 abstract static class RuleAspect<C extends AspectClass> {
Dmitry Lomove8040172016-04-06 14:53:43 +000085 protected final C aspectClass;
86 protected final Function<Rule, AspectParameters> parametersExtractor;
Marian Lobur702cad72015-09-02 09:53:58 +000087
Dmitry Lomove8040172016-04-06 14:53:43 +000088 protected RuleAspect(C aspectClass, Function<Rule, AspectParameters> parametersExtractor) {
89 this.aspectClass = aspectClass;
Marian Lobur702cad72015-09-02 09:53:58 +000090 this.parametersExtractor = parametersExtractor;
91 }
92
Googler74558fc2016-05-06 21:47:42 +000093 public String getName() {
94 return this.aspectClass.getName();
95 }
96
97 public ImmutableSet<String> getRequiredParameters() {
98 return ImmutableSet.<String>of();
99 }
100
Dmitry Lomove8040172016-04-06 14:53:43 +0000101 public abstract Aspect getAspect(Rule rule);
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000102
103 public C getAspectClass() {
104 return aspectClass;
105 }
Dmitry Lomove8040172016-04-06 14:53:43 +0000106 }
107
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000108 private static class NativeRuleAspect extends RuleAspect<NativeAspectClass> {
109 public NativeRuleAspect(NativeAspectClass aspectClass,
Dmitry Lomove8040172016-04-06 14:53:43 +0000110 Function<Rule, AspectParameters> parametersExtractor) {
111 super(aspectClass, parametersExtractor);
Marian Lobur702cad72015-09-02 09:53:58 +0000112 }
Dmitry Lomove8040172016-04-06 14:53:43 +0000113
114 @Override
115 public Aspect getAspect(Rule rule) {
Googler459f1302017-04-05 19:40:35 +0000116 AspectParameters params = parametersExtractor.apply(rule);
117 return params == null ? null : Aspect.forNative(aspectClass, params);
Dmitry Lomove8040172016-04-06 14:53:43 +0000118 }
119 }
120
mjhalupkacfa0bb72018-03-12 12:43:15 -0700121 @AutoCodec
122 static class SkylarkRuleAspect extends RuleAspect<SkylarkAspectClass> {
cparsons0d55f4c2017-12-20 14:49:13 -0800123 private final SkylarkDefinedAspect aspect;
Dmitry Lomov777845c2016-04-06 15:24:36 +0000124
cparsons0d55f4c2017-12-20 14:49:13 -0800125 public SkylarkRuleAspect(SkylarkDefinedAspect aspect) {
Googler74558fc2016-05-06 21:47:42 +0000126 super(aspect.getAspectClass(), aspect.getDefaultParametersExtractor());
127 this.aspect = aspect;
128 }
129
130 @Override
131 public ImmutableSet<String> getRequiredParameters() {
132 return aspect.getParamAttributes();
Dmitry Lomove8040172016-04-06 14:53:43 +0000133 }
134
135 @Override
136 public Aspect getAspect(Rule rule) {
Googler74558fc2016-05-06 21:47:42 +0000137 AspectParameters parameters = parametersExtractor.apply(rule);
138 return Aspect.forSkylark(aspectClass, aspect.getDefinition(parameters), parameters);
139 }
140 }
141
Michajlo Matijkiwccd5fb12016-07-26 20:58:42 +0000142 /** A RuleAspect that just wraps a pre-existing Aspect that doesn't vary with the Rule. */
Googler74558fc2016-05-06 21:47:42 +0000143 private static class PredefinedRuleAspect extends RuleAspect<AspectClass> {
Kevin Bierhoff6f1d6082017-03-24 21:17:13 +0000144 private final Aspect aspect;
Googler74558fc2016-05-06 21:47:42 +0000145
146 public PredefinedRuleAspect(Aspect aspect) {
147 super(aspect.getAspectClass(), null);
148 this.aspect = aspect;
149 }
150
151 @Override
152 public Aspect getAspect(Rule rule) {
153 return aspect;
Marian Lobur702cad72015-09-02 09:53:58 +0000154 }
155 }
156
mjhalupkacfa0bb72018-03-12 12:43:15 -0700157 @VisibleForSerialization
158 enum PropertyFlag {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100159 MANDATORY,
160 EXECUTABLE,
161 UNDOCUMENTED,
162 TAGGABLE,
163
164 /**
165 * Whether the list attribute is order-independent and can be sorted.
166 */
167 ORDER_INDEPENDENT,
168
169 /**
170 * Whether the allowedRuleClassesForLabels or allowedFileTypesForLabels are
171 * set to custom values. If so, and the attribute is called "deps", the
172 * legacy deps checking is skipped, and the new stricter checks are used
173 * instead. For non-"deps" attributes, this allows skipping the check if it
174 * would pass anyway, as the default setting allows any rule classes and
175 * file types.
176 */
177 STRICT_LABEL_CHECKING,
178
179 /**
180 * Set for things that would cause the a compile or lint-like action to
181 * be executed when the input changes. Used by compile_one_dependency.
182 * Set for attributes like hdrs and srcs on cc_ rules or srcs on java_
183 * or py_rules. Generally not set on data/resource attributes.
184 */
185 DIRECT_COMPILE_TIME_INPUT,
186
187 /**
188 * Whether the value of the list type attribute must not be an empty list.
189 */
190 NON_EMPTY,
191
192 /**
193 * Verifies that the referenced rule produces a single artifact. Note that this check happens
194 * on a per label basis, i.e. the check happens separately for every label in a label list.
195 */
196 SINGLE_ARTIFACT,
197
198 /**
199 * Whether we perform silent ruleclass filtering of the dependencies of the label type
200 * attribute according to their rule classes. I.e. elements of the list which don't match the
201 * allowedRuleClasses predicate or not rules will be filtered out without throwing any errors.
202 * This flag is introduced to handle plugins, do not use it in other cases.
203 */
204 SILENT_RULECLASS_FILTER,
205
206 // TODO(bazel-team): This is a hack introduced because of the bad design of the original rules.
207 // Depot cleanup would be too expensive, but don't migrate this to Skylark.
208 /**
209 * Whether to perform analysis time filetype check on this label-type attribute or not.
210 * If the flag is set, we skip the check that applies the allowedFileTypes filter
211 * to generated files. Do not use this if avoidable.
212 */
213 SKIP_ANALYSIS_TIME_FILETYPE_CHECK,
214
215 /**
216 * Whether the value of the attribute should come from a given set of values.
217 */
218 CHECK_ALLOWED_VALUES,
219
220 /**
221 * Whether this attribute is opted out of "configurability", i.e. the ability to determine
222 * its value based on properties of the build configuration.
223 */
224 NONCONFIGURABLE,
Ulf Adams0b638972015-09-08 13:25:35 +0000225
226 /**
Greg Estren875c7a72015-09-24 19:57:54 +0000227 * Whether we should skip dependency validation checks done by
228 * {@link com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.PrerequisiteValidator}
229 * (for visibility, etc.).
Ulf Adams0b638972015-09-08 13:25:35 +0000230 */
Greg Estren875c7a72015-09-24 19:57:54 +0000231 SKIP_PREREQ_VALIDATOR_CHECKS,
Greg Estren4a102512015-10-28 20:49:22 +0000232
233 /**
Greg Estren9d837842016-12-01 21:36:59 +0000234 * Whether we should check constraints on this attribute even if default enforcement policy
235 * would skip it. See
236 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for more on
237 * constraints.
Greg Estren4a102512015-10-28 20:49:22 +0000238 */
Greg Estren9d837842016-12-01 21:36:59 +0000239 CHECK_CONSTRAINTS_OVERRIDE,
240
241 /**
242 * Whether we should skip constraints checking on this attribute even if default enforcement
243 * policy would check it.
244 */
245 SKIP_CONSTRAINTS_OVERRIDE,
Irina Iancu2f235992017-01-10 16:03:29 +0000246
247 /**
248 * Whether we should use output_licenses to check the licences on this attribute.
249 */
250 OUTPUT_LICENSES,
Googlerc2200fd2018-09-14 17:35:59 -0700251
252 /**
253 * Has a function-based split transition.
254 */
255 HAS_FUNCTION_TRANSITION,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100256 }
257
258 // TODO(bazel-team): modify this interface to extend Predicate and have an extra error
259 // message function like AllowedValues does
260 /**
261 * A predicate-like class that determines whether an edge between two rules is valid or not.
262 */
263 public interface ValidityPredicate {
264 /**
265 * This method should return null if the edge is valid, or a suitable error message
266 * if it is not. Note that warnings are not supported.
267 */
268 String checkValid(Rule from, Rule to);
269 }
270
mjhalupkacfa0bb72018-03-12 12:43:15 -0700271 @AutoCodec
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272 public static final ValidityPredicate ANY_EDGE =
273 new ValidityPredicate() {
274 @Override
275 public String checkValid(Rule from, Rule to) {
276 return null;
277 }
278 };
279
280 /**
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000281 * Provides a {@link SplitTransition} given the originating target {@link Rule}. The split
282 * transition may be constant for all instances of the originating rule, or it may differ
283 * based on attributes of that rule. For instance, a split transition on a rule's deps may differ
284 * depending on the 'platform' attribute of the rule.
285 */
cparsonse29c1832018-05-25 14:55:00 -0700286 public interface SplitTransitionProvider extends SplitTransitionProviderApi {
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000287 /**
cparsons88821922017-10-11 01:21:46 +0200288 * Returns the {@link SplitTransition} given the attribute mapper of the originating rule.
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000289 */
gregce6bc35ed2017-12-22 11:51:39 -0800290 SplitTransition apply(AttributeMap attributeMap);
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000291 }
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000292
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000293 /**
294 * Implementation of {@link SplitTransitionProvider} that returns a single {@link SplitTransition}
295 * regardless of the originating rule.
296 */
janakr8688b682018-03-26 09:07:11 -0700297 @AutoCodec.VisibleForSerialization
298 @AutoCodec
299 static class BasicSplitTransitionProvider implements SplitTransitionProvider {
gregce6bc35ed2017-12-22 11:51:39 -0800300 private final SplitTransition splitTransition;
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000301
janakr8688b682018-03-26 09:07:11 -0700302 @AutoCodec.VisibleForSerialization
gregce6bc35ed2017-12-22 11:51:39 -0800303 BasicSplitTransitionProvider(SplitTransition splitTransition) {
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000304 this.splitTransition = splitTransition;
305 }
306
307 @Override
gregce6bc35ed2017-12-22 11:51:39 -0800308 public SplitTransition apply(AttributeMap attributeMap) {
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000309 return splitTransition;
310 }
311 }
312
mjhalupkacfa0bb72018-03-12 12:43:15 -0700313 /** A predicate class to check if the value of the attribute comes from a predefined set. */
314 @AutoCodec
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100315 public static class AllowedValueSet implements PredicateWithMessage<Object> {
316
317 private final Set<Object> allowedValues;
318
Carmi Grushkoe80cccd2015-11-11 19:12:31 +0000319 public <T> AllowedValueSet(T... values) {
320 this(Arrays.asList(values));
321 }
322
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100323 public AllowedValueSet(Iterable<?> values) {
324 Preconditions.checkNotNull(values);
325 Preconditions.checkArgument(!Iterables.isEmpty(values));
brandjoned249612017-07-11 22:06:22 +0200326 allowedValues = ImmutableSet.copyOf(values);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100327 }
328
mjhalupkacfa0bb72018-03-12 12:43:15 -0700329 @AutoCodec.Instantiator
330 @VisibleForSerialization
331 AllowedValueSet(Set<Object> allowedValues) {
332 this.allowedValues = allowedValues;
333 }
334
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100335 @Override
336 public boolean apply(Object input) {
337 return allowedValues.contains(input);
338 }
339
340 @Override
341 public String getErrorReason(Object value) {
342 return String.format("has to be one of %s instead of '%s'",
343 StringUtil.joinEnglishList(allowedValues, "or", "'"), value);
344 }
345
346 @VisibleForTesting
347 public Collection<Object> getAllowedValues() {
348 return allowedValues;
349 }
350 }
351
Googler74558fc2016-05-06 21:47:42 +0000352 public ImmutableMap<String, ImmutableSet<String>> getRequiredAspectParameters() {
353 ImmutableMap.Builder<String, ImmutableSet<String>> paramBuilder = ImmutableMap.builder();
354 for (RuleAspect<?> aspect : aspects) {
355 paramBuilder.put(aspect.getName(), aspect.getRequiredParameters());
356 }
357 return paramBuilder.build();
358 }
Dmitry Lomove8040172016-04-06 14:53:43 +0000359
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100360 /**
361 * Creates a new attribute builder.
362 *
363 * @param name attribute name
364 * @param type attribute type
365 * @return attribute builder
366 *
367 * @param <TYPE> attribute type class
368 */
369 public static <TYPE> Attribute.Builder<TYPE> attr(String name, Type<TYPE> type) {
370 return new Builder<>(name, type);
371 }
372
janakr33439dc2018-03-22 13:44:05 -0700373 /** A factory to generate {@link Attribute} instances. */
374 @AutoCodec
375 public static class ImmutableAttributeFactory {
376 private final Type<?> type;
377 private final ConfigurationTransition configTransition;
378 private final RuleClassNamePredicate allowedRuleClassesForLabels;
379 private final RuleClassNamePredicate allowedRuleClassesForLabelsWarning;
380 private final SplitTransitionProvider splitTransitionProvider;
381 private final FileTypeSet allowedFileTypesForLabels;
382 private final ValidityPredicate validityPredicate;
383 private final Object value;
384 private final AttributeValueSource valueSource;
385 private final boolean valueSet;
386 private final Predicate<AttributeMap> condition;
387 private final ImmutableSet<PropertyFlag> propertyFlags;
388 private final PredicateWithMessage<Object> allowedValues;
389 private final RequiredProviders requiredProviders;
390 private final ImmutableList<RuleAspect<?>> aspects;
391
392 @AutoCodec.VisibleForSerialization
393 ImmutableAttributeFactory(
394 Type<?> type,
395 ImmutableSet<PropertyFlag> propertyFlags,
396 Object value,
397 ConfigurationTransition configTransition,
398 RuleClassNamePredicate allowedRuleClassesForLabels,
399 RuleClassNamePredicate allowedRuleClassesForLabelsWarning,
400 SplitTransitionProvider splitTransitionProvider,
401 FileTypeSet allowedFileTypesForLabels,
402 ValidityPredicate validityPredicate,
403 AttributeValueSource valueSource,
404 boolean valueSet,
405 Predicate<AttributeMap> condition,
406 PredicateWithMessage<Object> allowedValues,
407 RequiredProviders requiredProviders,
408 ImmutableList<RuleAspect<?>> aspects) {
409 this.type = type;
410 this.configTransition = configTransition;
411 this.allowedRuleClassesForLabels = allowedRuleClassesForLabels;
412 this.allowedRuleClassesForLabelsWarning = allowedRuleClassesForLabelsWarning;
413 this.splitTransitionProvider = splitTransitionProvider;
414 this.allowedFileTypesForLabels = allowedFileTypesForLabels;
415 this.validityPredicate = validityPredicate;
416 this.value = value;
417 this.valueSource = valueSource;
418 this.valueSet = valueSet;
419 this.condition = condition;
420 this.propertyFlags = propertyFlags;
421 this.allowedValues = allowedValues;
422 this.requiredProviders = requiredProviders;
423 this.aspects = aspects;
424 }
425
426 public AttributeValueSource getValueSource() {
427 return valueSource;
428 }
429
430 public boolean isValueSet() {
431 return valueSet;
432 }
433
434 public Attribute build(String name) {
435 Preconditions.checkState(!name.isEmpty(), "name has not been set");
436 if (valueSource == AttributeValueSource.LATE_BOUND) {
437 Preconditions.checkState(isLateBound(name));
438 }
439 // TODO(bazel-team): Set the default to be no file type, then remove this check, and also
440 // remove all allowedFileTypes() calls without parameters.
441
442 // do not modify this.allowedFileTypesForLabels, instead create a copy.
443 FileTypeSet allowedFileTypesForLabels = this.allowedFileTypesForLabels;
444 if (type.getLabelClass() == LabelClass.DEPENDENCY) {
445 if (isPrivateAttribute(name) && allowedFileTypesForLabels == null) {
446 allowedFileTypesForLabels = FileTypeSet.ANY_FILE;
447 }
448 Preconditions.checkNotNull(
449 allowedFileTypesForLabels, "allowedFileTypesForLabels not set for %s", name);
450 } else if (type.getLabelClass() == LabelClass.OUTPUT) {
451 // TODO(bazel-team): Set the default to no file type and make explicit calls instead.
452 if (allowedFileTypesForLabels == null) {
453 allowedFileTypesForLabels = FileTypeSet.ANY_FILE;
454 }
455 }
456
457 return new Attribute(
458 name,
459 type,
460 propertyFlags,
461 value,
462 configTransition,
463 splitTransitionProvider,
464 allowedRuleClassesForLabels,
465 allowedRuleClassesForLabelsWarning,
466 allowedFileTypesForLabels,
467 validityPredicate,
468 condition,
469 allowedValues,
470 requiredProviders,
471 aspects);
472 }
473 }
474
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100475 /**
476 * A fluent builder for the {@code Attribute} instances.
477 *
478 * <p>All methods could be called only once per builder. The attribute
479 * already undocumented based on its name cannot be marked as undocumented.
480 */
481 public static class Builder <TYPE> {
Kevin Bierhoff6f1d6082017-03-24 21:17:13 +0000482 private final String name;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100483 private final Type<TYPE> type;
gregcebe55e112018-01-30 11:04:53 -0800484 private ConfigurationTransition configTransition = NoTransition.INSTANCE;
Googler72f3a102017-12-01 16:28:28 -0800485 private RuleClassNamePredicate allowedRuleClassesForLabels = ANY_RULE;
486 private RuleClassNamePredicate allowedRuleClassesForLabelsWarning = NO_RULE;
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000487 private SplitTransitionProvider splitTransitionProvider;
Ulf Adams788fd1a2015-03-12 13:54:09 +0000488 private FileTypeSet allowedFileTypesForLabels;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100489 private ValidityPredicate validityPredicate = ANY_EDGE;
490 private Object value;
Florian Weikert438ff162016-05-12 08:49:12 +0000491 private AttributeValueSource valueSource = AttributeValueSource.DIRECT;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100492 private boolean valueSet;
493 private Predicate<AttributeMap> condition;
494 private Set<PropertyFlag> propertyFlags = EnumSet.noneOf(PropertyFlag.class);
495 private PredicateWithMessage<Object> allowedValues = null;
dslomovc13bb392017-08-02 23:29:54 +0200496 private RequiredProviders.Builder requiredProvidersBuilder =
497 RequiredProviders.acceptAnyBuilder();
Dmitry Lomovf188dc22016-07-19 09:00:55 +0000498 private HashMap<String, RuleAspect<?>> aspects = new LinkedHashMap<>();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100499
500 /**
501 * Creates an attribute builder with given name and type. This attribute is optional, uses
502 * target configuration and has a default value the same as its type default value. This
503 * attribute will be marked as undocumented if its name starts with the dollar sign ({@code $})
504 * or colon ({@code :}).
505 *
506 * @param name attribute name
507 * @param type attribute type
508 */
509 public Builder(String name, Type<TYPE> type) {
510 this.name = Preconditions.checkNotNull(name);
511 this.type = Preconditions.checkNotNull(type);
512 if (isImplicit(name) || isLateBound(name)) {
513 setPropertyFlag(PropertyFlag.UNDOCUMENTED, "undocumented");
514 }
515 }
516
517 private Builder<TYPE> setPropertyFlag(PropertyFlag flag, String propertyName) {
Ulf Adams07dba942015-03-05 14:47:37 +0000518 Preconditions.checkState(
519 !propertyFlags.contains(flag), "%s flag is already set", propertyName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100520 propertyFlags.add(flag);
521 return this;
522 }
523
524 /**
525 * Sets the property flag of the corresponding name if exists, otherwise throws an Exception.
526 * Only meant to use from Skylark, do not use from Java.
527 */
528 public Builder<TYPE> setPropertyFlag(String propertyName) {
529 PropertyFlag flag = null;
530 try {
531 flag = PropertyFlag.valueOf(propertyName);
532 } catch (IllegalArgumentException e) {
533 throw new IllegalArgumentException("unknown attribute flag " + propertyName);
534 }
535 setPropertyFlag(flag, propertyName);
536 return this;
537 }
538
539 /**
540 * Makes the built attribute mandatory.
541 */
542 public Builder<TYPE> mandatory() {
543 return setPropertyFlag(PropertyFlag.MANDATORY, "mandatory");
544 }
545
546 /**
547 * Makes the built attribute non empty, meaning the attribute cannot have an empty list value.
548 * Only applicable for list type attributes.
549 */
550 public Builder<TYPE> nonEmpty() {
Ulf Adams07dba942015-03-05 14:47:37 +0000551 Preconditions.checkNotNull(type.getListElementType(), "attribute '%s' must be a list", name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100552 return setPropertyFlag(PropertyFlag.NON_EMPTY, "non_empty");
553 }
554
555 /**
556 * Makes the built attribute producing a single artifact.
557 */
558 public Builder<TYPE> singleArtifact() {
Michael Staiba751f922017-02-14 15:50:04 +0000559 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Ulf Adams07dba942015-03-05 14:47:37 +0000560 "attribute '%s' must be a label-valued type", name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100561 return setPropertyFlag(PropertyFlag.SINGLE_ARTIFACT, "single_artifact");
562 }
563
564 /**
565 * Forces silent ruleclass filtering on the label type attribute.
566 * This flag is introduced to handle plugins, do not use it in other cases.
567 */
568 public Builder<TYPE> silentRuleClassFilter() {
Michael Staiba751f922017-02-14 15:50:04 +0000569 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100570 "must be a label-valued type");
571 return setPropertyFlag(PropertyFlag.SILENT_RULECLASS_FILTER, "silent_ruleclass_filter");
572 }
573
574 /**
575 * Skip analysis time filetype check. Don't use it if avoidable.
576 */
577 public Builder<TYPE> skipAnalysisTimeFileTypeCheck() {
Michael Staiba751f922017-02-14 15:50:04 +0000578 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100579 "must be a label-valued type");
580 return setPropertyFlag(PropertyFlag.SKIP_ANALYSIS_TIME_FILETYPE_CHECK,
581 "skip_analysis_time_filetype_check");
582 }
583
584 /**
585 * Mark the built attribute as order-independent.
586 */
587 public Builder<TYPE> orderIndependent() {
Ulf Adams07dba942015-03-05 14:47:37 +0000588 Preconditions.checkNotNull(type.getListElementType(), "attribute '%s' must be a list", name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100589 return setPropertyFlag(PropertyFlag.ORDER_INDEPENDENT, "order-independent");
590 }
591
592 /**
Irina Iancu2f235992017-01-10 16:03:29 +0000593 * Mark the built attribute as to use output_licenses for license checking.
594 */
595 public Builder<TYPE> useOutputLicenses() {
596 Preconditions.checkState(BuildType.isLabelType(type), "must be a label type");
597 return setPropertyFlag(PropertyFlag.OUTPUT_LICENSES, "output_license");
598 }
599
600 /**
Googlerc2200fd2018-09-14 17:35:59 -0700601 * Indicate the attribute uses function-based split transition.
602 */
603 public Builder<TYPE> hasFunctionTransition() {
604 return setPropertyFlag(PropertyFlag.HAS_FUNCTION_TRANSITION,
605 "function-based split transition");
606 }
607
608 /**
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000609 * Defines the configuration transition for this attribute.
610 */
611 public Builder<TYPE> cfg(SplitTransitionProvider splitTransitionProvider) {
gregce7fa23ea2018-01-18 12:46:04 -0800612 Preconditions.checkState(this.configTransition == NoTransition.INSTANCE,
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000613 "the configuration transition is already set");
614
615 this.splitTransitionProvider = Preconditions.checkNotNull(splitTransitionProvider);
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000616 return this;
617 }
618
619 /**
gregce74a895d2018-05-29 11:26:03 -0700620 * Defines the configuration transition for this attribute (e.g. a {@link PatchTransition} or
621 * {@link SplitTransition}). Defaults to {@code NONE}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100622 */
gregcebe55e112018-01-30 11:04:53 -0800623 public Builder<TYPE> cfg(ConfigurationTransition configTransition) {
gregce74a895d2018-05-29 11:26:03 -0700624 Preconditions.checkNotNull(configTransition);
gregce7fa23ea2018-01-18 12:46:04 -0800625 Preconditions.checkState(this.configTransition == NoTransition.INSTANCE,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100626 "the configuration transition is already set");
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000627 if (configTransition instanceof SplitTransition) {
gregce74a895d2018-05-29 11:26:03 -0700628 return cfg(new BasicSplitTransitionProvider((SplitTransition) configTransition));
Chris Parsons2e62c0d2016-04-19 22:13:59 +0000629 } else {
630 this.configTransition = configTransition;
631 return this;
632 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100633 }
634
Greg Estren4ccabd32017-03-14 17:12:45 +0000635 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100636 * Requires the attribute target to be executable; only for label or label
637 * list attributes. Defaults to {@code false}.
638 */
639 public Builder<TYPE> exec() {
640 return setPropertyFlag(PropertyFlag.EXECUTABLE, "executable");
641 }
642
643 /**
644 * Indicates that the attribute (like srcs or hdrs) should be used as an input when calculating
645 * compile_one_dependency.
646 */
647 public Builder<TYPE> direct_compile_time_input() {
648 return setPropertyFlag(PropertyFlag.DIRECT_COMPILE_TIME_INPUT,
649 "direct_compile_time_input");
650 }
651
652 /**
653 * Makes the built attribute undocumented.
654 *
655 * @param reason explanation why the attribute is undocumented. This is not
656 * used but required for documentation
657 */
658 public Builder<TYPE> undocumented(String reason) {
659 return setPropertyFlag(PropertyFlag.UNDOCUMENTED, "undocumented");
660 }
661
662 /**
663 * Sets the attribute default value. The type of the default value must
664 * match the type parameter. (e.g. list=[], integer=0, string="",
665 * label=null). The {@code defaultValue} must be immutable.
666 *
667 * <p>If defaultValue is of type Label and is a target, that target will
668 * become an implicit dependency of the Rule; we will load the target
669 * (and its dependencies) if it encounters the Rule and build the target
670 * if needs to apply the Rule.
671 */
672 public Builder<TYPE> value(TYPE defaultValue) {
673 Preconditions.checkState(!valueSet, "the default value is already set");
674 value = defaultValue;
675 valueSet = true;
676 return this;
677 }
678
679 /**
680 * See value(TYPE) above. This method is only meant for Skylark usage.
Florian Weikertcb3d7992016-09-06 14:54:22 +0000681 *
vladmos9c787fa2017-07-04 11:45:22 -0400682 * <p>The parameter {@code context} is relevant iff the default value is a Label string. In this
683 * case, {@code context} must point to the parent Label in order to be able to convert the
684 * default value string to a proper Label.
685 *
686 * @param parameterName The name of the attribute to use in error messages
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100687 */
vladmos9c787fa2017-07-04 11:45:22 -0400688 public Builder<TYPE> defaultValue(
689 Object defaultValue, Object context, @Nullable String parameterName)
Florian Weikertcb3d7992016-09-06 14:54:22 +0000690 throws ConversionException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100691 Preconditions.checkState(!valueSet, "the default value is already set");
vladmos9c787fa2017-07-04 11:45:22 -0400692 value =
693 type.convert(
694 defaultValue,
695 ((parameterName == null) ? "" : String.format("parameter '%s' of ", parameterName))
696 + String.format("attribute '%s'", name),
697 context);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100698 valueSet = true;
699 return this;
700 }
701
Florian Weikertcb3d7992016-09-06 14:54:22 +0000702 /** See value(TYPE) above. This method is only meant for Skylark usage. */
703 public Builder<TYPE> defaultValue(Object defaultValue) throws ConversionException {
vladmos9c787fa2017-07-04 11:45:22 -0400704 return defaultValue(defaultValue, null, null);
Florian Weikertcb3d7992016-09-06 14:54:22 +0000705 }
706
Dmitry Lomovace678e2015-12-16 15:10:20 +0000707 public boolean isValueSet() {
708 return valueSet;
709 }
710
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100711 /**
Florian Weikertea6c82d2016-09-05 12:15:31 +0000712 * Sets the attribute default value to a computed default value - use this when the default
713 * value is a function of other attributes of the Rule. The type of the computed default value
714 * for a mandatory attribute must match the type parameter: (e.g. list=[], integer=0, string="",
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100715 * label=null). The {@code defaultValue} implementation must be immutable.
716 *
Florian Weikertea6c82d2016-09-05 12:15:31 +0000717 * <p>If the computed default returns a Label that is a target, that target will become an
718 * implicit dependency of this Rule; we will load the target (and its dependencies) if it
719 * encounters the Rule and build the target if needs to apply the Rule.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100720 */
721 public Builder<TYPE> value(ComputedDefault defaultValue) {
722 Preconditions.checkState(!valueSet, "the default value is already set");
723 value = defaultValue;
Florian Weikert438ff162016-05-12 08:49:12 +0000724 valueSource = AttributeValueSource.COMPUTED_DEFAULT;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100725 valueSet = true;
726 return this;
727 }
728
729 /**
Florian Weikertea6c82d2016-09-05 12:15:31 +0000730 * Sets the attribute default value to a Skylark computed default template. Like a native
731 * Computed Default, this allows a Skylark-defined Rule Class to specify that the default value
732 * of an attribute is a function of other attributes of the Rule.
733 *
734 * <p>During the loading phase, the computed default template will be specialized for each rule
735 * it applies to. Those rules' attribute values will not be references to {@link
736 * SkylarkComputedDefaultTemplate}s, but instead will be references to {@link
737 * SkylarkComputedDefault}s.
738 *
739 * <p>If the computed default returns a Label that is a target, that target will become an
740 * implicit dependency of this Rule; we will load the target (and its dependencies) if it
741 * encounters the Rule and build the target if needs to apply the Rule.
742 */
743 public Builder<TYPE> value(SkylarkComputedDefaultTemplate skylarkComputedDefaultTemplate) {
744 Preconditions.checkState(!valueSet, "the default value is already set");
745 value = skylarkComputedDefaultTemplate;
746 valueSource = AttributeValueSource.COMPUTED_DEFAULT;
747 valueSet = true;
748 return this;
749 }
750
751 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100752 * Sets the attribute default value to be late-bound, i.e., it is derived from the build
mstaib807a9b22017-09-19 17:06:32 +0200753 * configuration and/or the rule's configured attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100754 */
mstaib807a9b22017-09-19 17:06:32 +0200755 public Builder<TYPE> value(LateBoundDefault<?, ? extends TYPE> defaultValue) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100756 Preconditions.checkState(!valueSet, "the default value is already set");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100757 value = defaultValue;
Florian Weikert438ff162016-05-12 08:49:12 +0000758 valueSource = AttributeValueSource.LATE_BOUND;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100759 valueSet = true;
760 return this;
761 }
762
763 /**
Florian Weikert438ff162016-05-12 08:49:12 +0000764 * Returns where the value of this attribute comes from. Useful only for Skylark.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100765 */
Florian Weikert438ff162016-05-12 08:49:12 +0000766 public AttributeValueSource getValueSource() {
767 return valueSource;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100768 }
769
770 /**
771 * Sets a condition predicate. The default value of the attribute only applies if the condition
772 * evaluates to true. If the value is explicitly provided, then this condition is ignored.
773 *
774 * <p>The condition is only evaluated if the attribute is not explicitly set, and after all
775 * explicit attributes have been set. It can generally not access default values of other
776 * attributes.
777 */
778 public Builder<TYPE> condition(Predicate<AttributeMap> condition) {
779 Preconditions.checkState(this.condition == null, "the condition is already set");
780 this.condition = condition;
781 return this;
782 }
783
784 /**
785 * Switches on the capability of an attribute to be published to the rule's
786 * tag set.
787 */
788 public Builder<TYPE> taggable() {
789 return setPropertyFlag(PropertyFlag.TAGGABLE, "taggable");
790 }
791
792 /**
Greg Estren875c7a72015-09-24 19:57:54 +0000793 * Disables dependency checks done by
794 * {@link com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.PrerequisiteValidator}.
Ulf Adams0b638972015-09-08 13:25:35 +0000795 */
Greg Estren875c7a72015-09-24 19:57:54 +0000796 public Builder<TYPE> skipPrereqValidatorCheck() {
797 return setPropertyFlag(PropertyFlag.SKIP_PREREQ_VALIDATOR_CHECKS,
798 "skip_prereq_validator_checks");
Ulf Adams0b638972015-09-08 13:25:35 +0000799 }
800
801 /**
Greg Estren9d837842016-12-01 21:36:59 +0000802 * Enforces constraint checking on this attribute even if default enforcement policy would skip
803 * it. If default policy checks the attribute, this is a no-op.
804 *
805 * <p>Most attributes are enforced by default, so in the common case this call is unnecessary.
Greg Estren4a102512015-10-28 20:49:22 +0000806 *
807 * <p>See {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics#getConstraintCheckedDependencies}
Greg Estren9d837842016-12-01 21:36:59 +0000808 * for enforcement policy details.
Greg Estren4a102512015-10-28 20:49:22 +0000809 */
810 public Builder<TYPE> checkConstraints() {
Greg Estren9d837842016-12-01 21:36:59 +0000811 Verify.verify(!propertyFlags.contains(PropertyFlag.SKIP_CONSTRAINTS_OVERRIDE),
812 "constraint checking is already overridden to be skipped");
813 return setPropertyFlag(PropertyFlag.CHECK_CONSTRAINTS_OVERRIDE, "check_constraints");
814 }
815
816 /**
817 * Skips constraint checking on this attribute even if default enforcement policy would check
818 * it. If default policy skips the attribute, this is a no-op.
819 *
820 * <p>See {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics#getConstraintCheckedDependencies}
821 * for enforcement policy details.
822 */
823 public Builder<TYPE> dontCheckConstraints() {
824 Verify.verify(!propertyFlags.contains(PropertyFlag.CHECK_CONSTRAINTS_OVERRIDE),
825 "constraint checking is already overridden to be checked");
826 return setPropertyFlag(PropertyFlag.SKIP_CONSTRAINTS_OVERRIDE, "dont_check_constraints");
Greg Estren4a102512015-10-28 20:49:22 +0000827 }
828
829 /**
gregceda4c9592017-07-27 22:09:34 +0200830 * If this is a label or label-list attribute, then this sets the allowed rule types for the
831 * labels occurring in the attribute.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100832 *
gregceda4c9592017-07-27 22:09:34 +0200833 * <p>If the attribute contains Labels of any other rule type, then if they're in
834 * {@link #allowedRuleClassesForLabelsWarning}, the build continues with a warning. Else if
835 * they fulfill {@link #getMandatoryNativeProvidersList()}, the build continues without error.
836 * Else the build fails during analysis.
837 *
838 * <p>If neither this nor {@link #allowedRuleClassesForLabelsWarning} is set, only rules that
839 * fulfill {@link #getMandatoryNativeProvidersList()} build without error.
840 *
841 * <p>This only works on a per-target basis, not on a per-file basis; with other words, it
842 * works for 'deps' attributes, but not 'srcs' attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100843 */
844 public Builder<TYPE> allowedRuleClasses(Iterable<String> allowedRuleClasses) {
845 return allowedRuleClasses(
Googler72f3a102017-12-01 16:28:28 -0800846 RuleClassNamePredicate.only(allowedRuleClasses));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100847 }
848
849 /**
gregceda4c9592017-07-27 22:09:34 +0200850 * If this is a label or label-list attribute, then this sets the allowed rule types for the
851 * labels occurring in the attribute.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100852 *
gregceda4c9592017-07-27 22:09:34 +0200853 * <p>If the attribute contains Labels of any other rule type, then if they're in
854 * {@link #allowedRuleClassesForLabelsWarning}, the build continues with a warning. Else if
855 * they fulfill {@link #getMandatoryNativeProvidersList()}, the build continues without error.
856 * Else the build fails during analysis.
857 *
858 * <p>If neither this nor {@link #allowedRuleClassesForLabelsWarning} is set, only rules that
859 * fulfill {@link #getMandatoryNativeProvidersList()} build without error.
860 *
861 * <p>This only works on a per-target basis, not on a per-file basis; with other words, it
862 * works for 'deps' attributes, but not 'srcs' attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100863 */
Googler72f3a102017-12-01 16:28:28 -0800864 public Builder<TYPE> allowedRuleClasses(RuleClassNamePredicate allowedRuleClasses) {
Michael Staiba751f922017-02-14 15:50:04 +0000865 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100866 "must be a label-valued type");
867 propertyFlags.add(PropertyFlag.STRICT_LABEL_CHECKING);
868 allowedRuleClassesForLabels = allowedRuleClasses;
869 return this;
870 }
871
872 /**
gregceda4c9592017-07-27 22:09:34 +0200873 * If this is a label or label-list attribute, then this sets the allowed rule types for the
874 * labels occurring in the attribute.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100875 *
gregceda4c9592017-07-27 22:09:34 +0200876 * <p>If the attribute contains Labels of any other rule type, then if they're in
877 * {@link #allowedRuleClassesForLabelsWarning}, the build continues with a warning. Else if
878 * they fulfill {@link #getMandatoryNativeProvidersList()}, the build continues without error.
879 * Else the build fails during analysis.
880 *
881 * <p>If neither this nor {@link #allowedRuleClassesForLabelsWarning} is set, only rules that
882 * fulfill {@link #getMandatoryNativeProvidersList()} build without error.
883 *
884 * <p>This only works on a per-target basis, not on a per-file basis; with other words, it
885 * works for 'deps' attributes, but not 'srcs' attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100886 */
887 public Builder<TYPE> allowedRuleClasses(String... allowedRuleClasses) {
888 return allowedRuleClasses(ImmutableSet.copyOf(allowedRuleClasses));
889 }
890
891 /**
892 * If this is a label or label-list attribute, then this sets the allowed
893 * file types for file labels occurring in the attribute. If the attribute
894 * contains labels that correspond to files of any other type, then an error
895 * is produced during the analysis phase.
896 *
897 * <p>This only works on a per-target basis, not on a per-file basis; with
898 * other words, it works for 'deps' attributes, but not 'srcs' attributes.
899 */
900 public Builder<TYPE> allowedFileTypes(FileTypeSet allowedFileTypes) {
Michael Staiba751f922017-02-14 15:50:04 +0000901 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100902 "must be a label-valued type");
903 propertyFlags.add(PropertyFlag.STRICT_LABEL_CHECKING);
Ulf Adams788fd1a2015-03-12 13:54:09 +0000904 allowedFileTypesForLabels = Preconditions.checkNotNull(allowedFileTypes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100905 return this;
906 }
907
908 /**
909 * Allow all files for legacy compatibility. All uses of this method should be audited and then
910 * removed. In some cases, it's correct to allow any file, but mostly the set of files should be
911 * restricted to a reasonable set.
912 */
913 public Builder<TYPE> legacyAllowAnyFileType() {
914 return allowedFileTypes(FileTypeSet.ANY_FILE);
915 }
916
917 /**
918 * If this is a label or label-list attribute, then this sets the allowed
919 * file types for file labels occurring in the attribute. If the attribute
920 * contains labels that correspond to files of any other type, then an error
921 * is produced during the analysis phase.
922 *
923 * <p>This only works on a per-target basis, not on a per-file basis; with
924 * other words, it works for 'deps' attributes, but not 'srcs' attributes.
925 */
926 public Builder<TYPE> allowedFileTypes(FileType... allowedFileTypes) {
927 return allowedFileTypes(FileTypeSet.of(allowedFileTypes));
928 }
929
930 /**
gregceda4c9592017-07-27 22:09:34 +0200931 * If this is a label or label-list attribute, then this sets the allowed rule types with
932 * warning for the labels occurring in the attribute. This must be a disjoint set from
933 * {@link #allowedRuleClasses}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100934 *
gregceda4c9592017-07-27 22:09:34 +0200935 * <p>If the attribute contains Labels of any other rule type (other than this or those set in
936 * allowedRuleClasses()) and they fulfill {@link #getMandatoryNativeProvidersList()}}, the build
937 * continues without error. Else the build fails during analysis.
938 *
939 * <p>If neither this nor {@link #allowedRuleClassesForLabels} is set, only rules that
940 * fulfill {@link #getMandatoryNativeProvidersList()} build without error.
941 *
942 * <p>This only works on a per-target basis, not on a per-file basis; with other words, it
943 * works for 'deps' attributes, but not 'srcs' attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100944 */
945 public Builder<TYPE> allowedRuleClassesWithWarning(Collection<String> allowedRuleClasses) {
946 return allowedRuleClassesWithWarning(
Googler72f3a102017-12-01 16:28:28 -0800947 RuleClassNamePredicate.only(allowedRuleClasses));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100948 }
949
950 /**
gregceda4c9592017-07-27 22:09:34 +0200951 * If this is a label or label-list attribute, then this sets the allowed rule types with
952 * warning for the labels occurring in the attribute. This must be a disjoint set from
953 * {@link #allowedRuleClasses}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100954 *
gregceda4c9592017-07-27 22:09:34 +0200955 * <p>If the attribute contains Labels of any other rule type (other than this or those set in
956 * allowedRuleClasses()) and they fulfill {@link #getMandatoryNativeProvidersList()}}, the build
957 * continues without error. Else the build fails during analysis.
958 *
959 * <p>If neither this nor {@link #allowedRuleClassesForLabels} is set, only rules that
960 * fulfill {@link #getMandatoryNativeProvidersList()} build without error.
961 *
962 * <p>This only works on a per-target basis, not on a per-file basis; with other words, it
963 * works for 'deps' attributes, but not 'srcs' attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100964 */
Googler72f3a102017-12-01 16:28:28 -0800965 public Builder<TYPE> allowedRuleClassesWithWarning(RuleClassNamePredicate allowedRuleClasses) {
Michael Staiba751f922017-02-14 15:50:04 +0000966 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100967 "must be a label-valued type");
968 propertyFlags.add(PropertyFlag.STRICT_LABEL_CHECKING);
969 allowedRuleClassesForLabelsWarning = allowedRuleClasses;
970 return this;
971 }
972
973 /**
gregceda4c9592017-07-27 22:09:34 +0200974 * If this is a label or label-list attribute, then this sets the allowed rule types with
dslomovde965ac2017-07-31 21:07:51 +0200975 * warning for the labels occurring in the attribute. This must be a disjoint set from {@link
976 * #allowedRuleClasses}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100977 *
gregceda4c9592017-07-27 22:09:34 +0200978 * <p>If the attribute contains Labels of any other rule type (other than this or those set in
dslomovc13bb392017-08-02 23:29:54 +0200979 * allowedRuleClasses()) and they fulfill {@link #getRequiredProviders()}}, the build continues
980 * without error. Else the build fails during analysis.
gregceda4c9592017-07-27 22:09:34 +0200981 *
dslomovc13bb392017-08-02 23:29:54 +0200982 * <p>If neither this nor {@link #allowedRuleClassesForLabels} is set, only rules that fulfill
983 * {@link #getRequiredProviders()} build without error.
gregceda4c9592017-07-27 22:09:34 +0200984 *
dslomovde965ac2017-07-31 21:07:51 +0200985 * <p>This only works on a per-target basis, not on a per-file basis; with other words, it works
986 * for 'deps' attributes, but not 'srcs' attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100987 */
988 public Builder<TYPE> allowedRuleClassesWithWarning(String... allowedRuleClasses) {
989 return allowedRuleClassesWithWarning(ImmutableSet.copyOf(allowedRuleClasses));
990 }
991
992 /**
Googler861ed2c2016-09-07 19:13:17 +0000993 * Sets a list of lists of mandatory native providers. Every configured target occurring in this
994 * label type attribute has to provide all the providers from one of those lists, otherwise an
995 * error is produced during the analysis phase.
Liam Miller-Cushonbbae4d92016-05-03 18:23:03 +0000996 */
Googler861ed2c2016-09-07 19:13:17 +0000997 public final Builder<TYPE> mandatoryNativeProvidersList(
998 Iterable<? extends Iterable<Class<? extends TransitiveInfoProvider>>> providersList) {
Michael Staiba751f922017-02-14 15:50:04 +0000999 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Liam Miller-Cushonbbae4d92016-05-03 18:23:03 +00001000 "must be a label-valued type");
dslomovc13bb392017-08-02 23:29:54 +02001001
Googler861ed2c2016-09-07 19:13:17 +00001002 for (Iterable<Class<? extends TransitiveInfoProvider>> providers : providersList) {
dslomovc13bb392017-08-02 23:29:54 +02001003 this.requiredProvidersBuilder.addNativeSet(ImmutableSet.copyOf(providers));
Googler861ed2c2016-09-07 19:13:17 +00001004 }
Googler861ed2c2016-09-07 19:13:17 +00001005 return this;
1006 }
1007
1008 public Builder<TYPE> mandatoryNativeProviders(
1009 Iterable<Class<? extends TransitiveInfoProvider>> providers) {
1010 if (providers.iterator().hasNext()) {
1011 mandatoryNativeProvidersList(ImmutableList.of(providers));
1012 }
Liam Miller-Cushonbbae4d92016-05-03 18:23:03 +00001013 return this;
1014 }
1015
1016 /**
Yun Peng5c34e962016-02-22 15:13:19 +00001017 * Sets a list of sets of mandatory Skylark providers. Every configured target occurring in
1018 * this label type attribute has to provide all the providers from one of those sets,
Dmitry Lomovfd2bdc32016-10-07 08:52:10 +00001019 * or be one of {@link #allowedRuleClasses}, otherwise an error is produced during
1020 * the analysis phase.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001021 */
Dmitry Lomovfd2bdc32016-10-07 08:52:10 +00001022 public Builder<TYPE> mandatoryProvidersList(
1023 Iterable<? extends Iterable<SkylarkProviderIdentifier>> providersList){
Michael Staiba751f922017-02-14 15:50:04 +00001024 Preconditions.checkState(type.getLabelClass() == LabelClass.DEPENDENCY,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001025 "must be a label-valued type");
Dmitry Lomovfd2bdc32016-10-07 08:52:10 +00001026 for (Iterable<SkylarkProviderIdentifier> providers : providersList) {
dslomovc13bb392017-08-02 23:29:54 +02001027 this.requiredProvidersBuilder.addSkylarkSet(ImmutableSet.copyOf(providers));
Yun Peng5c34e962016-02-22 15:13:19 +00001028 }
Yun Peng5c34e962016-02-22 15:13:19 +00001029 return this;
1030 }
1031
Dmitry Lomovfd2bdc32016-10-07 08:52:10 +00001032 public Builder<TYPE> legacyMandatoryProviders(String... ids) {
1033 return mandatoryProviders(
laurentlb3d2a68c2017-06-30 00:32:04 +02001034 Iterables.transform(
1035 Arrays.asList(ids),
1036 s -> {
1037 Preconditions.checkNotNull(s);
1038 return SkylarkProviderIdentifier.forLegacy(s);
1039 }));
Dmitry Lomovfd2bdc32016-10-07 08:52:10 +00001040 }
1041
1042 public Builder<TYPE> mandatoryProviders(Iterable<SkylarkProviderIdentifier> providers) {
Yun Pengefd7ca12016-03-03 13:14:38 +00001043 if (providers.iterator().hasNext()) {
1044 mandatoryProvidersList(ImmutableList.of(providers));
1045 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001046 return this;
1047 }
1048
dslomov77baa4c2017-07-10 17:15:27 +02001049 public Builder<TYPE> mandatoryProviders(SkylarkProviderIdentifier... providers) {
1050 mandatoryProviders(Arrays.asList(providers));
1051 return this;
1052 }
1053
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001054 /**
Dmitry Lomov5a8f1c02015-11-26 10:49:16 +00001055 * Asserts that a particular parameterized aspect probably needs to be computed for all direct
1056 * dependencies through this attribute.
1057 *
Googler459f1302017-04-05 19:40:35 +00001058 * @param evaluator function that extracts aspect parameters from rule. If it returns null,
1059 * then the aspect will not be attached.
Dmitry Lomov5a8f1c02015-11-26 10:49:16 +00001060 */
Dmitry Lomove8040172016-04-06 14:53:43 +00001061 public Builder<TYPE> aspect(
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +00001062 NativeAspectClass aspect, Function<Rule, AspectParameters> evaluator) {
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001063 NativeRuleAspect nativeRuleAspect = new NativeRuleAspect(aspect, evaluator);
1064 RuleAspect<?> oldAspect = this.aspects.put(nativeRuleAspect.getName(), nativeRuleAspect);
1065 if (oldAspect != null) {
1066 throw new AssertionError(
1067 String.format("Aspect %s has already been added", oldAspect.getName()));
1068 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001069 return this;
1070 }
Marian Lobur702cad72015-09-02 09:53:58 +00001071
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001072 /**
Dmitry Lomov5a8f1c02015-11-26 10:49:16 +00001073 * Asserts that a particular parameterized aspect probably needs to be computed for all direct
1074 * dependencies through this attribute.
1075 */
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +00001076 public Builder<TYPE> aspect(NativeAspectClass aspect) {
janakr123d7842018-06-19 10:30:15 -07001077 return this.aspect(aspect, EMPTY_FUNCTION);
Dmitry Lomov5a8f1c02015-11-26 10:49:16 +00001078 }
1079
janakr123d7842018-06-19 10:30:15 -07001080 @AutoCodec @AutoCodec.VisibleForSerialization
1081 static final Function<Rule, AspectParameters> EMPTY_FUNCTION = input -> AspectParameters.EMPTY;
1082
cparsons0d55f4c2017-12-20 14:49:13 -08001083 public Builder<TYPE> aspect(SkylarkDefinedAspect skylarkAspect, Location location)
1084 throws EvalException {
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001085 SkylarkRuleAspect skylarkRuleAspect = new SkylarkRuleAspect(skylarkAspect);
1086 RuleAspect<?> oldAspect = this.aspects.put(skylarkAspect.getName(), skylarkRuleAspect);
1087 if (oldAspect != null) {
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001088 throw new EvalException(
1089 location, String.format("aspect %s added more than once", skylarkAspect.getName()));
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001090 }
Googler74558fc2016-05-06 21:47:42 +00001091 return this;
1092 }
1093
Dmitry Lomov65fde002017-02-07 17:24:04 +00001094 /**
1095 * Should only be used for deserialization.
1096 */
Googler74558fc2016-05-06 21:47:42 +00001097 public Builder<TYPE> aspect(final Aspect aspect) {
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001098 PredefinedRuleAspect predefinedRuleAspect = new PredefinedRuleAspect(aspect);
1099 RuleAspect<?> oldAspect =
1100 this.aspects.put(predefinedRuleAspect.getName(), predefinedRuleAspect);
1101 if (oldAspect != null) {
1102 throw new AssertionError(
1103 String.format("Aspect %s has already been added", oldAspect.getName()));
1104 }
Dmitry Lomove8040172016-04-06 14:53:43 +00001105 return this;
1106 }
1107
Dmitry Lomov5a8f1c02015-11-26 10:49:16 +00001108 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001109 * Sets the predicate-like edge validity checker.
1110 */
1111 public Builder<TYPE> validityPredicate(ValidityPredicate validityPredicate) {
1112 propertyFlags.add(PropertyFlag.STRICT_LABEL_CHECKING);
1113 this.validityPredicate = validityPredicate;
1114 return this;
1115 }
1116
1117 /**
1118 * The value of the attribute must be one of allowedValues.
1119 */
1120 public Builder<TYPE> allowedValues(PredicateWithMessage<Object> allowedValues) {
1121 this.allowedValues = allowedValues;
1122 propertyFlags.add(PropertyFlag.CHECK_ALLOWED_VALUES);
1123 return this;
1124 }
1125
1126 /**
1127 * Makes the built attribute "non-configurable", i.e. its value cannot be influenced by
1128 * the build configuration. Attributes are "configurable" unless explicitly opted out here.
1129 *
1130 * <p>Non-configurability indicates an exceptional state: there exists Blaze logic that needs
1131 * the attribute's value, has no access to configurations, and can't apply a workaround
1132 * through an appropriate {@link AbstractAttributeMapper} implementation. Scenarios like
1133 * this should be as uncommon as possible, so it's important we maintain clear documentation
1134 * on what causes them and why users consequently can't configure certain attributes.
1135 *
1136 * @param reason why this attribute can't be configurable. This isn't used by Blaze - it's
1137 * solely a documentation mechanism.
1138 */
1139 public Builder<TYPE> nonconfigurable(String reason) {
1140 Preconditions.checkState(!reason.isEmpty());
1141 return setPropertyFlag(PropertyFlag.NONCONFIGURABLE, "nonconfigurable");
1142 }
1143
janakr33439dc2018-03-22 13:44:05 -07001144 /** Returns an {@link ImmutableAttributeFactory} that can be invoked to create attributes. */
1145 public ImmutableAttributeFactory buildPartial() {
Googler72f3a102017-12-01 16:28:28 -08001146 Preconditions.checkState(
1147 !allowedRuleClassesForLabels.consideredOverlapping(allowedRuleClassesForLabelsWarning),
1148 "allowedRuleClasses %s and allowedRuleClassesWithWarning %s "
1149 + "may not contain the same rule classes",
1150 allowedRuleClassesForLabels,
1151 allowedRuleClassesForLabelsWarning);
gregceda4c9592017-07-27 22:09:34 +02001152
janakr33439dc2018-03-22 13:44:05 -07001153 return new ImmutableAttributeFactory(
Yun Peng5c34e962016-02-22 15:13:19 +00001154 type,
1155 Sets.immutableEnumSet(propertyFlags),
1156 valueSet ? value : type.getDefaultValue(),
1157 configTransition,
Yun Peng5c34e962016-02-22 15:13:19 +00001158 allowedRuleClassesForLabels,
1159 allowedRuleClassesForLabelsWarning,
janakr33439dc2018-03-22 13:44:05 -07001160 splitTransitionProvider,
Yun Peng5c34e962016-02-22 15:13:19 +00001161 allowedFileTypesForLabels,
1162 validityPredicate,
janakr33439dc2018-03-22 13:44:05 -07001163 valueSource,
1164 valueSet,
Yun Peng5c34e962016-02-22 15:13:19 +00001165 condition,
1166 allowedValues,
dslomovc13bb392017-08-02 23:29:54 +02001167 requiredProvidersBuilder.build(),
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001168 ImmutableList.copyOf(aspects.values()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001169 }
janakr33439dc2018-03-22 13:44:05 -07001170
1171 /**
1172 * Creates the attribute. Uses name, type, optionality, configuration type and the default value
1173 * configured by the builder.
1174 */
1175 public Attribute build() {
1176 return build(this.name);
1177 }
1178
1179 /**
1180 * Creates the attribute. Uses type, optionality, configuration type and the default value
1181 * configured by the builder. Use the name passed as an argument. This function is used by
1182 * Skylark where the name is provided only when we build. We don't want to modify the builder,
1183 * as it is shared in a multithreaded environment.
1184 */
1185 public Attribute build(String name) {
1186 return buildPartial().build(name);
1187 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001188 }
1189
1190 /**
Florian Weikertea6c82d2016-09-05 12:15:31 +00001191 * A strategy for dealing with too many computations, used when creating lookup tables for {@link
1192 * ComputedDefault}s.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001193 *
Florian Weikertea6c82d2016-09-05 12:15:31 +00001194 * @param <TException> The type of exception this strategy throws if too many computations are
1195 * attempted.
1196 */
1197 interface ComputationLimiter<TException extends Exception> {
1198 void onComputationCount(int count) throws TException;
1199 }
1200
1201 /**
1202 * An implementation of {@link ComputationLimiter} that never throws. For use with
1203 * natively-defined {@link ComputedDefault}s, which are limited in the number of configurable
1204 * attributes they depend on, not on the number of different combinations of possible inputs.
1205 */
1206 private static final ComputationLimiter<RuntimeException> NULL_COMPUTATION_LIMITER =
1207 new ComputationLimiter<RuntimeException>() {
1208 @Override
1209 public void onComputationCount(int count) throws RuntimeException {}
1210 };
1211
1212 /** Exception for computed default attributes that depend on too many configurable attributes. */
1213 private static class TooManyConfigurableAttributesException extends Exception {
1214 TooManyConfigurableAttributesException(int max) {
1215 super(
1216 String.format(
1217 "Too many configurable attributes to compute all possible values: "
1218 + "Found more than %d possible values.",
1219 max));
1220 }
1221 }
1222
1223 private static class FixedComputationLimiter
1224 implements ComputationLimiter<TooManyConfigurableAttributesException> {
1225
1226 /** Upper bound of the number of combinations of values for a computed default attribute. */
1227 private static final int COMPUTED_DEFAULT_MAX_COMBINATIONS = 64;
1228
1229 private static final FixedComputationLimiter INSTANCE = new FixedComputationLimiter();
1230
1231 @Override
1232 public void onComputationCount(int count) throws TooManyConfigurableAttributesException {
1233 if (count > COMPUTED_DEFAULT_MAX_COMBINATIONS) {
1234 throw new TooManyConfigurableAttributesException(COMPUTED_DEFAULT_MAX_COMBINATIONS);
1235 }
1236 }
1237 }
1238
1239 /**
1240 * Specifies how values of {@link ComputedDefault} attributes are computed based on the values of
1241 * other attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001242 *
Florian Weikertea6c82d2016-09-05 12:15:31 +00001243 * <p>The {@code TComputeException} type parameter allows the two specializations of this class to
1244 * describe whether and how their computations throw. For natively defined computed defaults,
1245 * computation does not throw, but for Skylark-defined computed defaults, computation may throw
1246 * {@link InterruptedException}.
1247 */
1248 private abstract static class ComputationStrategy<TComputeException extends Exception> {
1249 abstract Object compute(AttributeMap map) throws TComputeException;
1250
1251 /**
1252 * Returns a lookup table mapping from:
1253 *
1254 * <ul>
1255 * <li>tuples of values that may be assigned by {@code rule} to attributes with names in {@code
1256 * dependencies} (note that there may be more than one such tuple for any given rule, if any
1257 * of the dependencies are configurable)
1258 * </ul>
1259 *
1260 * <p>to:
1261 *
1262 * <ul>
1263 * <li>the value {@link #compute(AttributeMap)} evaluates to when the provided {@link
1264 * AttributeMap} contains the values specified by that assignment, or {@code null} if the
1265 * {@link ComputationStrategy} failed to evaluate.
1266 * </ul>
1267 *
1268 * <p>The lookup table contains a tuple for each possible assignment to the {@code dependencies}
1269 * attributes. The meaning of each tuple is well-defined because {@code dependencies} is
1270 * ordered.
1271 *
1272 * <p>This is useful because configurable attributes may have many possible values. During the
1273 * loading phase a configurable attribute can't be resolved to a single value. Configuration
1274 * information, needed to resolve such an attribute, is only available during analysis. However,
1275 * any labels that a ComputedDefault attribute may evaluate to must be loaded during the loading
1276 * phase.
1277 */
1278 <T, TLimitException extends Exception> Map<List<Object>, T> computeValuesForAllCombinations(
1279 List<String> dependencies,
1280 Type<T> type,
1281 Rule rule,
1282 ComputationLimiter<TLimitException> limiter)
1283 throws TComputeException, TLimitException {
1284 // This will hold every (value1, value2, ..) combination of the declared dependencies.
1285 // Collect those combinations.
1286 AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
1287 List<Map<String, Object>> depMaps = mapper.visitAttributes(dependencies, limiter);
1288 // For each combination, call compute() on a specialized AttributeMap providing those
1289 // values.
Michajlo Matijkiw69d9b412016-10-06 20:06:59 +00001290 Map<List<Object>, T> valueMap = new HashMap<>(depMaps.size());
Florian Weikertea6c82d2016-09-05 12:15:31 +00001291 for (Map<String, Object> depMap : depMaps) {
1292 AttributeMap attrMap = mapper.createMapBackedAttributeMap(depMap);
1293 Object value = compute(attrMap);
1294 List<Object> key = createDependencyAssignmentTuple(dependencies, attrMap);
1295 valueMap.put(key, type.cast(value));
1296 }
1297 return valueMap;
1298 }
1299
1300 /**
1301 * Given an {@link AttributeMap}, containing an assignment to each attribute in {@code
1302 * dependencies}, this returns a list of the assigned values, ordered as {@code dependencies} is
1303 * ordered.
1304 */
1305 static List<Object> createDependencyAssignmentTuple(
1306 List<String> dependencies, AttributeMap attrMap) {
1307 ArrayList<Object> tuple = new ArrayList<>(dependencies.size());
1308 for (String attrName : dependencies) {
1309 Type<?> attrType = attrMap.getAttributeType(attrName);
1310 tuple.add(attrMap.get(attrName, attrType));
1311 }
1312 return tuple;
1313 }
1314 }
1315
1316 /**
1317 * A computed default is a default value for a Rule attribute that is a function of other
1318 * attributes of the rule.
1319 *
1320 * <p>Attributes whose defaults are computed are first initialized to the default for their type,
1321 * and then the computed defaults are evaluated after all non-computed defaults have been
1322 * initialized. There is no defined order among computed defaults, so they must not depend on each
1323 * other.
1324 *
1325 * <p>If a computed default reads the value of another attribute, at least one of the following
1326 * must be true:
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001327 *
1328 * <ol>
Florian Weikertea6c82d2016-09-05 12:15:31 +00001329 * <li>The other attribute must be declared in the computed default's constructor
1330 * <li>The other attribute must be non-configurable ({@link Builder#nonconfigurable}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001331 * </ol>
1332 *
Florian Weikertea6c82d2016-09-05 12:15:31 +00001333 * <p>The reason for enforced declarations is that, since attribute values might be configurable,
1334 * a computed default that depends on them may itself take multiple values. Since we have no
1335 * access to a target's configuration at the time these values are computed, we need the ability
1336 * to probe the default's *complete* dependency space. Declared dependencies allow us to do so
1337 * sanely. Non-configurable attributes don't have this problem because their value is fixed and
1338 * known even without configuration information.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001339 *
1340 * <p>Implementations of this interface must be immutable.
1341 */
1342 public abstract static class ComputedDefault {
Mark Schaller93c7da62016-07-26 16:59:59 +00001343 private final ImmutableList<String> dependencies;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001344
1345 /**
1346 * Create a computed default that can read all non-configurable attribute values and no
1347 * configurable attribute values.
1348 */
1349 public ComputedDefault() {
Florian Weikertea6c82d2016-09-05 12:15:31 +00001350 this(ImmutableList.<String>of());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001351 }
1352
1353 /**
1354 * Create a computed default that can read all non-configurable attributes values and one
1355 * explicitly specified configurable attribute value
1356 */
1357 public ComputedDefault(String depAttribute) {
Florian Weikertea6c82d2016-09-05 12:15:31 +00001358 this(ImmutableList.of(depAttribute));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001359 }
1360
1361 /**
1362 * Create a computed default that can read all non-configurable attributes values and two
1363 * explicitly specified configurable attribute values.
1364 */
1365 public ComputedDefault(String depAttribute1, String depAttribute2) {
Florian Weikertea6c82d2016-09-05 12:15:31 +00001366 this(ImmutableList.of(depAttribute1, depAttribute2));
1367 }
1368
1369 /**
1370 * Creates a computed default that can read all non-configurable attributes and some explicitly
1371 * specified configurable attribute values.
1372 *
1373 * <p>This constructor should not be used by native {@link ComputedDefault} functions. The limit
1374 * of at-most-two depended-on configurable attributes is intended, to limit the exponential
1375 * growth of possible values. {@link SkylarkComputedDefault} uses this, but is limited by {@link
1376 * FixedComputationLimiter#COMPUTED_DEFAULT_MAX_COMBINATIONS}.
1377 */
1378 protected ComputedDefault(ImmutableList<String> dependencies) {
1379 // Order is important for #createDependencyAssignmentTuple.
1380 this.dependencies = Ordering.natural().immutableSortedCopy(dependencies);
1381 }
1382
1383 <T> Iterable<T> getPossibleValues(Type<T> type, Rule rule) {
1384 final ComputedDefault owner = ComputedDefault.this;
1385 ComputationStrategy<RuntimeException> strategy =
1386 new ComputationStrategy<RuntimeException>() {
1387 @Override
1388 public Object compute(AttributeMap map) {
1389 return owner.getDefault(map);
1390 }
1391 };
1392 // Note that this uses ArrayList instead of something like ImmutableList because some
1393 // values may be null.
1394 return new ArrayList<>(
1395 strategy
1396 .computeValuesForAllCombinations(dependencies, type, rule, NULL_COMPUTATION_LIMITER)
1397 .values());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001398 }
1399
Mark Schaller93c7da62016-07-26 16:59:59 +00001400 /** The list of configurable attributes this ComputedDefault declares it may read. */
1401 public ImmutableList<String> dependencies() {
1402 return dependencies;
1403 }
1404
Florian Weikertea6c82d2016-09-05 12:15:31 +00001405 /**
1406 * Returns the value this {@link ComputedDefault} evaluates to, given the inputs contained in
1407 * {@code rule}.
1408 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001409 public abstract Object getDefault(AttributeMap rule);
1410 }
1411
1412 /**
Florian Weikertea6c82d2016-09-05 12:15:31 +00001413 * A Skylark-defined computed default, which can be precomputed for a specific {@link Rule} by
1414 * calling {@link #computePossibleValues}, which returns a {@link SkylarkComputedDefault} that
1415 * contains a lookup table.
1416 */
janakr83fe8792018-03-23 15:26:31 -07001417 @AutoCodec
Florian Weikertea6c82d2016-09-05 12:15:31 +00001418 public static final class SkylarkComputedDefaultTemplate {
1419 private final Type<?> type;
1420 private final SkylarkCallbackFunction callback;
1421 private final Location location;
1422 private final ImmutableList<String> dependencies;
1423
1424 /**
1425 * Creates a new SkylarkComputedDefaultTemplate that allows the computation of attribute values
1426 * via a callback function during loading phase.
1427 *
1428 * @param type The type of the value of this attribute.
1429 * @param dependencies A list of all names of other attributes that are accessed by this
1430 * attribute.
1431 * @param callback A function to compute the actual attribute value.
1432 * @param location The location of the Skylark function.
1433 */
1434 public SkylarkComputedDefaultTemplate(
1435 Type<?> type,
1436 ImmutableList<String> dependencies,
1437 SkylarkCallbackFunction callback,
1438 Location location) {
1439 this.type = Preconditions.checkNotNull(type);
1440 // Order is important for #createDependencyAssignmentTuple.
1441 this.dependencies =
1442 Ordering.natural().immutableSortedCopy(Preconditions.checkNotNull(dependencies));
1443 this.callback = Preconditions.checkNotNull(callback);
1444 this.location = Preconditions.checkNotNull(location);
1445 }
1446
1447 /**
1448 * Returns a {@link SkylarkComputedDefault} containing a lookup table specifying the output of
1449 * this {@link SkylarkComputedDefaultTemplate}'s callback given each possible assignment {@code
1450 * rule} might make to the attributes specified by {@link #dependencies}.
1451 *
1452 * <p>If the rule is missing an attribute specified by {@link #dependencies}, or if there are
1453 * too many possible assignments, or if any evaluation fails, this throws {@link
1454 * CannotPrecomputeDefaultsException}.
1455 *
1456 * <p>May only be called after all non-{@link ComputedDefault} attributes have been set on the
1457 * {@code rule}.
1458 */
1459 SkylarkComputedDefault computePossibleValues(
1460 Attribute attr, final Rule rule, final EventHandler eventHandler)
1461 throws InterruptedException, CannotPrecomputeDefaultsException {
1462
1463 final SkylarkComputedDefaultTemplate owner = SkylarkComputedDefaultTemplate.this;
1464 final String msg =
1465 String.format(
1466 "Cannot compute default value of attribute '%s' in rule '%s': ",
Florian Weikertba405252017-01-30 14:42:50 +00001467 attr.getPublicName(), rule.getLabel());
Florian Weikertea6c82d2016-09-05 12:15:31 +00001468 final AtomicReference<EvalException> caughtEvalExceptionIfAny = new AtomicReference<>();
1469 ComputationStrategy<InterruptedException> strategy =
1470 new ComputationStrategy<InterruptedException>() {
1471 @Override
1472 public Object compute(AttributeMap map) throws InterruptedException {
1473 try {
vladmos076977e2017-12-02 14:15:32 -08001474 return owner.computeValue(eventHandler, map);
Florian Weikertea6c82d2016-09-05 12:15:31 +00001475 } catch (EvalException ex) {
1476 caughtEvalExceptionIfAny.compareAndSet(null, ex);
1477 return null;
1478 }
1479 }
1480 };
1481
1482 ImmutableList.Builder<Type<?>> dependencyTypesBuilder = ImmutableList.builder();
1483 Map<List<Object>, Object> lookupTable = new HashMap<>();
1484 try {
1485 for (String dependency : dependencies) {
1486 Attribute attribute = rule.getRuleClassObject().getAttributeByNameMaybe(dependency);
1487 if (attribute == null) {
1488 throw new AttributeNotFoundException(
1489 String.format("No such attribute %s in rule %s", dependency, rule.getLabel()));
1490 }
1491 dependencyTypesBuilder.add(attribute.getType());
1492 }
1493 lookupTable.putAll(
1494 strategy.computeValuesForAllCombinations(
1495 dependencies, attr.getType(), rule, FixedComputationLimiter.INSTANCE));
1496 if (caughtEvalExceptionIfAny.get() != null) {
1497 throw caughtEvalExceptionIfAny.get();
1498 }
1499 } catch (AttributeNotFoundException
1500 | TooManyConfigurableAttributesException
1501 | EvalException ex) {
1502 String error = msg + ex.getMessage();
1503 rule.reportError(error, eventHandler);
1504 throw new CannotPrecomputeDefaultsException(error);
1505 }
1506 return new SkylarkComputedDefault(dependencies, dependencyTypesBuilder.build(), lookupTable);
1507 }
1508
vladmos076977e2017-12-02 14:15:32 -08001509 private Object computeValue(EventHandler eventHandler, AttributeMap rule)
1510 throws EvalException, InterruptedException {
Florian Weikertea6c82d2016-09-05 12:15:31 +00001511 Map<String, Object> attrValues = new HashMap<>();
1512 for (String attrName : rule.getAttributeNames()) {
1513 Attribute attr = rule.getAttributeDefinition(attrName);
1514 if (!attr.hasComputedDefault()) {
1515 Object value = rule.get(attrName, attr.getType());
1516 if (!EvalUtils.isNullOrNone(value)) {
1517 attrValues.put(attr.getName(), value);
1518 }
1519 }
1520 }
vladmos076977e2017-12-02 14:15:32 -08001521 return invokeCallback(eventHandler, attrValues);
Florian Weikertea6c82d2016-09-05 12:15:31 +00001522 }
1523
vladmos076977e2017-12-02 14:15:32 -08001524 private Object invokeCallback(EventHandler eventHandler, Map<String, Object> attrValues)
Florian Weikertea6c82d2016-09-05 12:15:31 +00001525 throws EvalException, InterruptedException {
1526 ClassObject attrs =
cparsons0c5c1c62018-05-24 10:37:03 -07001527 StructProvider.STRUCT.create(
Florian Weikertea6c82d2016-09-05 12:15:31 +00001528 attrValues, "No such regular (non computed) attribute '%s'.");
vladmos076977e2017-12-02 14:15:32 -08001529 Object result = callback.call(eventHandler, attrs);
Florian Weikertea6c82d2016-09-05 12:15:31 +00001530 try {
1531 return type.cast((result == Runtime.NONE) ? type.getDefaultValue() : result);
1532 } catch (ClassCastException ex) {
1533 throw new EvalException(
1534 location,
1535 String.format(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001536 "expected '%s', but got '%s'", type, EvalUtils.getDataTypeName(result, true)));
Florian Weikertea6c82d2016-09-05 12:15:31 +00001537 }
1538 }
1539
1540 private static class AttributeNotFoundException extends Exception {
1541 private AttributeNotFoundException(String message) {
1542 super(message);
1543 }
1544 }
1545
1546 static class CannotPrecomputeDefaultsException extends Exception {
1547 private CannotPrecomputeDefaultsException(String message) {
1548 super(message);
1549 }
1550 }
1551 }
1552
1553 /**
1554 * A class for computed attributes defined in Skylark.
1555 *
1556 * <p>Unlike {@link ComputedDefault}, instances of this class contain a pre-computed table of all
1557 * possible assignments of depended-on attributes and what the Skylark function evaluates to, and
1558 * {@link #getPossibleValues(Type, Rule)} and {@link #getDefault(AttributeMap)} do lookups in that
1559 * table.
1560 */
mjhalupka7b398f92018-03-08 12:08:25 -08001561 @AutoCodec
Florian Weikertea6c82d2016-09-05 12:15:31 +00001562 static final class SkylarkComputedDefault extends ComputedDefault {
1563
1564 private final List<Type<?>> dependencyTypes;
1565 private final Map<List<Object>, Object> lookupTable;
1566
1567 /**
1568 * Creates a new SkylarkComputedDefault containing a lookup table.
1569 *
mjhalupka7b398f92018-03-08 12:08:25 -08001570 * @param dependencies A list of all names of other attributes that are accessed by this
Florian Weikertea6c82d2016-09-05 12:15:31 +00001571 * attribute.
1572 * @param dependencyTypes A list of requiredAttributes' types.
1573 * @param lookupTable An exhaustive mapping from requiredAttributes assignments to values this
1574 * computed default evaluates to.
1575 */
1576 SkylarkComputedDefault(
mjhalupka7b398f92018-03-08 12:08:25 -08001577 ImmutableList<String> dependencies,
Florian Weikertea6c82d2016-09-05 12:15:31 +00001578 ImmutableList<Type<?>> dependencyTypes,
1579 Map<List<Object>, Object> lookupTable) {
mjhalupka7b398f92018-03-08 12:08:25 -08001580 super(Preconditions.checkNotNull(dependencies));
Florian Weikertea6c82d2016-09-05 12:15:31 +00001581 this.dependencyTypes = Preconditions.checkNotNull(dependencyTypes);
1582 this.lookupTable = Preconditions.checkNotNull(lookupTable);
1583 }
1584
1585 List<Type<?>> getDependencyTypes() {
1586 return dependencyTypes;
1587 }
1588
1589 Map<List<Object>, Object> getLookupTable() {
1590 return lookupTable;
1591 }
1592
1593 @Override
1594 public Object getDefault(AttributeMap rule) {
1595 List<Object> key = ComputationStrategy.createDependencyAssignmentTuple(dependencies(), rule);
1596 Preconditions.checkState(
1597 lookupTable.containsKey(key),
1598 "Error in rule '%s': precomputed value missing for dependencies: %s. Available keys: %s.",
1599 rule.getLabel(),
1600 Iterables.toString(key),
1601 Iterables.toString(lookupTable.keySet()));
1602 return lookupTable.get(key);
1603 }
1604
1605 @Override
1606 <T> Iterable<T> getPossibleValues(Type<T> type, Rule rule) {
1607 List<T> result = new ArrayList<>(lookupTable.size());
1608 for (Object obj : lookupTable.values()) {
1609 result.add(type.cast(obj));
1610 }
1611 return result;
1612 }
1613 }
1614
janakr8688b682018-03-26 09:07:11 -07001615 @AutoCodec.VisibleForSerialization
1616 static class SimpleLateBoundDefault<FragmentT, ValueT>
cparsonsd8d91722017-11-03 19:10:05 +01001617 extends LateBoundDefault<FragmentT, ValueT> {
janakr8688b682018-03-26 09:07:11 -07001618 @AutoCodec.VisibleForSerialization protected final Resolver<FragmentT, ValueT> resolver;
cparsonsd8d91722017-11-03 19:10:05 +01001619
1620 private SimpleLateBoundDefault(boolean useHostConfiguration,
1621 Class<FragmentT> fragmentClass,
1622 ValueT defaultValue, Resolver<FragmentT, ValueT> resolver) {
1623 super(useHostConfiguration, fragmentClass, defaultValue);
1624
1625 this.resolver = resolver;
1626 }
1627
1628 @Override
1629 public ValueT resolve(Rule rule, AttributeMap attributes, FragmentT input) {
1630 return resolver.resolve(rule, attributes, input);
1631 }
1632 }
1633
mstaib807a9b22017-09-19 17:06:32 +02001634 // TODO(b/65746853): Remove documentation about accepting BuildConfiguration when uses are cleaned
1635 // up.
Florian Weikertea6c82d2016-09-05 12:15:31 +00001636 /**
janakra56a6ad2018-02-02 15:52:22 -08001637 * Provider of values for late-bound attributes. See {@link Attribute#value(LateBoundDefault<?, ?
1638 * extends TYPE> value)}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001639 *
1640 * <p>Use sparingly - having different values for attributes during loading and analysis can
1641 * confuse users.
mstaib807a9b22017-09-19 17:06:32 +02001642 *
1643 * @param <FragmentT> The type of value that is used to compute this value. This is usually a
1644 * subclass of BuildConfiguration.Fragment. It may also be Void to receive null, or
1645 * BuildConfiguration itself to receive the entire configuration.
janakra56a6ad2018-02-02 15:52:22 -08001646 * @param <ValueT> The type of value returned by this class. Must be either {@link Void}, a {@link
1647 * Label}, or a {@link List} of {@link Label} objects.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001648 */
mstaib807a9b22017-09-19 17:06:32 +02001649 @Immutable
cparsonsd8d91722017-11-03 19:10:05 +01001650 public abstract static class LateBoundDefault<FragmentT, ValueT> {
mstaib807a9b22017-09-19 17:06:32 +02001651 /**
1652 * Functional interface for computing the value of a late-bound attribute.
1653 *
1654 * <p>Implementations of this interface must be immutable.
1655 */
1656 @FunctionalInterface
1657 public interface Resolver<FragmentT, ValueT> {
1658 ValueT resolve(Rule rule, AttributeMap attributeMap, FragmentT input);
1659 }
1660
1661 private final boolean useHostConfiguration;
1662 private final ValueT defaultValue;
1663 private final Class<FragmentT> fragmentClass;
mstaib807a9b22017-09-19 17:06:32 +02001664
1665 /**
mstaib807a9b22017-09-19 17:06:32 +02001666 * Creates a new LateBoundDefault which always returns the given value.
1667 *
1668 * <p>This is used primarily for matching names with late-bound attributes on other rules and
1669 * for testing. Use normal default values if the name does not matter.
1670 */
janakra56a6ad2018-02-02 15:52:22 -08001671 @VisibleForTesting
1672 public static LabelLateBoundDefault<Void> fromConstantForTesting(Label defaultValue) {
1673 return new LabelLateBoundDefault<Void>(
1674 false,
1675 Void.class,
1676 Preconditions.checkNotNull(defaultValue),
1677 (rule, attributes, unused) -> defaultValue) {};
mstaib807a9b22017-09-19 17:06:32 +02001678 }
1679
1680 /**
1681 * Creates a new LateBoundDefault which always returns null.
1682 *
1683 * <p>This is used primarily for matching names with late-bound attributes on other rules and
1684 * for testing. Use normal default values if the name does not matter.
1685 */
1686 @SuppressWarnings("unchecked") // bivariant implementation
1687 public static <ValueT> LateBoundDefault<Void, ValueT> alwaysNull() {
janakra56a6ad2018-02-02 15:52:22 -08001688 return (LateBoundDefault<Void, ValueT>) AlwaysNullLateBoundDefault.INSTANCE;
mstaib807a9b22017-09-19 17:06:32 +02001689 }
1690
cparsonscaceacd2017-11-04 01:00:59 +01001691 protected LateBoundDefault(
mstaib807a9b22017-09-19 17:06:32 +02001692 boolean useHostConfiguration,
1693 Class<FragmentT> fragmentClass,
cparsonsd8d91722017-11-03 19:10:05 +01001694 ValueT defaultValue) {
mstaib807a9b22017-09-19 17:06:32 +02001695 this.useHostConfiguration = useHostConfiguration;
1696 this.defaultValue = defaultValue;
1697 this.fragmentClass = fragmentClass;
mstaib807a9b22017-09-19 17:06:32 +02001698 }
1699
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001700 /**
Greg Estren974bbd92016-07-27 14:22:41 +00001701 * Whether to look up the label in the host configuration. This is only here for host
1702 * compilation tools - we usually need to look up labels in the target configuration.
mstaib807a9b22017-09-19 17:06:32 +02001703 */
cparsonsd8d91722017-11-03 19:10:05 +01001704 public final boolean useHostConfiguration() {
mstaib807a9b22017-09-19 17:06:32 +02001705 return useHostConfiguration;
1706 }
1707
1708 /**
1709 * Returns the input type that the attribute expects. This is almost always a configuration
1710 * fragment to be retrieved from the target's configuration (or the host configuration).
Greg Estren974bbd92016-07-27 14:22:41 +00001711 *
mstaib807a9b22017-09-19 17:06:32 +02001712 * <p>It may also be {@link Void} to receive null. This is rarely necessary, but can be used,
1713 * e.g., if the attribute is named to match an attribute in another rule which is late-bound.
1714 *
1715 * <p>It may also be BuildConfiguration to receive the entire configuration. This is deprecated,
1716 * and only necessary when the default is computed from methods of BuildConfiguration itself.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001717 */
cparsonsd8d91722017-11-03 19:10:05 +01001718 public final Class<FragmentT> getFragmentClass() {
mstaib807a9b22017-09-19 17:06:32 +02001719 return fragmentClass;
1720 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001721
mstaib807a9b22017-09-19 17:06:32 +02001722 /** The default value for the attribute that is set during the loading phase. */
cparsonsd8d91722017-11-03 19:10:05 +01001723 public final ValueT getDefault() {
mstaib807a9b22017-09-19 17:06:32 +02001724 return defaultValue;
1725 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001726
1727 /**
1728 * The actual value for the attribute for the analysis phase, which depends on the build
1729 * configuration. Note that configurations transitions are applied after the late-bound
1730 * attribute was evaluated.
Greg Estren33ec1912016-02-10 15:57:58 +00001731 *
1732 * @param rule the rule being evaluated
1733 * @param attributes interface for retrieving the values of the rule's other attributes
mstaib807a9b22017-09-19 17:06:32 +02001734 * @param input the configuration fragment to evaluate with
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001735 */
cparsonsd8d91722017-11-03 19:10:05 +01001736 public abstract ValueT resolve(Rule rule, AttributeMap attributes, FragmentT input);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001737 }
1738
janakra56a6ad2018-02-02 15:52:22 -08001739 /**
1740 * An abstract {@link LateBoundDefault} class so that {@code SkylarkLateBoundDefault} can derive
1741 * from {@link LateBoundDefault} without compromising the type-safety of the second generic
1742 * parameter to {@link LateBoundDefault}.
1743 */
1744 public abstract static class AbstractLabelLateBoundDefault<FragmentT>
1745 extends LateBoundDefault<FragmentT, Label> {
1746 protected AbstractLabelLateBoundDefault(
1747 boolean useHostConfiguration, Class<FragmentT> fragmentClass, Label defaultValue) {
1748 super(useHostConfiguration, fragmentClass, defaultValue);
1749 }
1750 }
1751
1752 private static class AlwaysNullLateBoundDefault extends SimpleLateBoundDefault<Void, Void> {
1753 static final AlwaysNullLateBoundDefault INSTANCE = new AlwaysNullLateBoundDefault();
1754
1755 private AlwaysNullLateBoundDefault() {
1756 super(false, Void.class, null, (rule, attributes, unused) -> null);
1757 }
1758 }
1759
1760 /** A {@link LateBoundDefault} for a {@link Label}. */
janakr8688b682018-03-26 09:07:11 -07001761 @AutoCodec
janakra56a6ad2018-02-02 15:52:22 -08001762 public static class LabelLateBoundDefault<FragmentT>
1763 extends SimpleLateBoundDefault<FragmentT, Label> {
janakr8688b682018-03-26 09:07:11 -07001764 @AutoCodec.VisibleForSerialization
1765 LabelLateBoundDefault(
janakra56a6ad2018-02-02 15:52:22 -08001766 boolean useHostConfiguration,
1767 Class<FragmentT> fragmentClass,
1768 Label defaultValue,
1769 Resolver<FragmentT, Label> resolver) {
1770 super(useHostConfiguration, fragmentClass, defaultValue, resolver);
1771 }
1772
1773 /**
1774 * Creates a new LabelLateBoundDefault which uses the rule, its configured attributes, and a
1775 * fragment of the target configuration.
1776 *
1777 * <p>Note that the configuration fragment here does not take into account any transitions that
1778 * are on the attribute with this LabelLateBoundDefault as its value. The configuration will be
1779 * the same as the configuration given to the target bearing the attribute.
1780 *
1781 * <p>Nearly all LateBoundDefaults should use this constructor or {@link
1782 * LabelListLateBoundDefault#fromTargetConfiguration}. There are few situations where it isn't
1783 * the appropriate option.
1784 *
1785 * <p>If you want a late-bound dependency which is configured in the host configuration, just
1786 * use this method with {@link com.google.devtools.build.lib.analysis.config.HostTransition}. If
1787 * you also need to decide the label of the dependency with information gained from the host
1788 * configuration - and it's very unlikely that you do - you can use {@link
1789 * LabelLateBoundDefault#fromHostConfiguration} as well.
1790 *
1791 * <p>If you want to decide an attribute's value based on the value of its other attributes, use
1792 * a subclass of {@link ComputedDefault}. The only time you should need {@link
1793 * LabelListLateBoundDefault#fromRuleAndAttributesOnly} is if you need access to three or more
1794 * configurable attributes, or if you need to match names with a late-bound attribute on another
1795 * rule.
1796 *
1797 * <p>If you have a constant-valued attribute, but you need it to have the same name as an
1798 * attribute on another rule which is late-bound, use {@link #alwaysNull}.
1799 *
1800 * @param fragmentClass The fragment to receive from the target configuration. May also be
1801 * BuildConfiguration.class to receive the entire configuration (deprecated) - in this case,
1802 * you must only use methods of BuildConfiguration itself, and not use any fragments.
1803 * @param defaultValue The default {@link Label} to return at loading time, when the
1804 * configuration is not available.
1805 * @param resolver A function which will compute the actual value with the configuration.
1806 */
1807 public static <FragmentT> LabelLateBoundDefault<FragmentT> fromTargetConfiguration(
1808 Class<FragmentT> fragmentClass, Label defaultValue, Resolver<FragmentT, Label> resolver) {
1809 Preconditions.checkArgument(
1810 !fragmentClass.equals(Void.class),
1811 "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use "
1812 + "configuration.");
1813 return new LabelLateBoundDefault<>(false, fragmentClass, defaultValue, resolver);
1814 }
1815
1816 /**
1817 * Creates a new LateBoundDefault which uses the rule, its configured attributes, and a fragment
1818 * of the host configuration.
1819 *
1820 * <p>This should only be necessary in very specialized cases. In almost all cases, you don't
1821 * need this method, just {@link #fromTargetConfiguration} and {@link
1822 * com.google.devtools.build.lib.analysis.config.HostTransition}.
1823 *
1824 * <p>This method only affects the configuration fragment passed to {@link #resolve}. You must
1825 * also use {@link com.google.devtools.build.lib.analysis.config.HostTransition}, so that the
1826 * dependency will be analyzed in the host configuration.
1827 *
1828 * @param fragmentClass The fragment to receive from the host configuration. May also be
1829 * BuildConfiguration.class to receive the entire configuration (deprecated) - in this case,
1830 * you must only use methods of BuildConfiguration itself, and not use any fragments. It is
1831 * very rare that a LateBoundDefault should need a host configuration fragment; use {@link
1832 * #fromTargetConfiguration} in most cases.
1833 * @param defaultValue The default {@link Label} to return at loading time, when the
1834 * configuration is not available.
1835 * @param resolver A function which will compute the actual value with the configuration.
1836 */
1837 public static <FragmentT> LabelLateBoundDefault<FragmentT> fromHostConfiguration(
1838 Class<FragmentT> fragmentClass, Label defaultValue, Resolver<FragmentT, Label> resolver) {
1839 Preconditions.checkArgument(
1840 !fragmentClass.equals(Void.class),
1841 "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use "
1842 + "configuration.");
1843 return new LabelLateBoundDefault<>(true, fragmentClass, defaultValue, resolver);
1844 }
1845 }
1846
1847 /** A {@link LateBoundDefault} for a {@link List} of {@link Label} objects. */
janakr8688b682018-03-26 09:07:11 -07001848 @AutoCodec
janakra56a6ad2018-02-02 15:52:22 -08001849 public static class LabelListLateBoundDefault<FragmentT>
1850 extends SimpleLateBoundDefault<FragmentT, List<Label>> {
janakr8688b682018-03-26 09:07:11 -07001851 @AutoCodec.VisibleForSerialization
1852 LabelListLateBoundDefault(
janakra56a6ad2018-02-02 15:52:22 -08001853 boolean useHostConfiguration,
1854 Class<FragmentT> fragmentClass,
1855 Resolver<FragmentT, List<Label>> resolver) {
1856 super(useHostConfiguration, fragmentClass, ImmutableList.of(), resolver);
1857 }
1858
1859 public static <FragmentT> LabelListLateBoundDefault<FragmentT> fromTargetConfiguration(
1860 Class<FragmentT> fragmentClass, Resolver<FragmentT, List<Label>> resolver) {
1861 Preconditions.checkArgument(
1862 !fragmentClass.equals(Void.class),
1863 "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use "
1864 + "configuration.");
1865 return new LabelListLateBoundDefault<>(false, fragmentClass, resolver);
1866 }
1867
1868 /**
1869 * Creates a new LabelListLateBoundDefault which uses only the rule and its configured
1870 * attributes.
1871 *
1872 * <p>This should only be necessary in very specialized cases. In almost all cases, you don't
1873 * need this method, just use {@link ComputedDefault}.
1874 *
1875 * <p>This is used primarily for computing values based on three or more configurable attributes
1876 * and/or matching names with late-bound attributes on other rules.
1877 *
1878 * @param resolver A function which will compute the actual value with the configuration.
1879 */
1880 public static LabelListLateBoundDefault<Void> fromRuleAndAttributesOnly(
1881 Resolver<Void, List<Label>> resolver) {
1882 return new LabelListLateBoundDefault<>(false, Void.class, resolver);
1883 }
1884 }
1885
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001886 private final String name;
1887
1888 private final Type<?> type;
1889
1890 private final Set<PropertyFlag> propertyFlags;
1891
1892 // Exactly one of these conditions is true:
1893 // 1. defaultValue == null.
1894 // 2. defaultValue instanceof ComputedDefault &&
1895 // type.isValid(defaultValue.getDefault())
Florian Weikertea6c82d2016-09-05 12:15:31 +00001896 // 3. defaultValue instanceof SkylarkComputedDefaultTemplate &&
1897 // type.isValid(defaultValue.computePossibleValues().getDefault())
1898 // 4. type.isValid(defaultValue).
1899 // 5. defaultValue instanceof LateBoundDefault &&
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001900 // type.isValid(defaultValue.getDefault(configuration))
1901 // (We assume a hypothetical Type.isValid(Object) predicate.)
1902 private final Object defaultValue;
1903
gregcebe55e112018-01-30 11:04:53 -08001904 private final ConfigurationTransition configTransition;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001905
Chris Parsons2e62c0d2016-04-19 22:13:59 +00001906 private final SplitTransitionProvider splitTransitionProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001907
1908 /**
1909 * For label or label-list attributes, this predicate returns which rule
1910 * classes are allowed for the targets in the attribute.
1911 */
Googler72f3a102017-12-01 16:28:28 -08001912 private final RuleClassNamePredicate allowedRuleClassesForLabels;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001913
1914 /**
1915 * For label or label-list attributes, this predicate returns which rule
1916 * classes are allowed for the targets in the attribute with warning.
1917 */
Googler72f3a102017-12-01 16:28:28 -08001918 private final RuleClassNamePredicate allowedRuleClassesForLabelsWarning;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001919
1920 /**
1921 * For label or label-list attributes, this predicate returns which file
1922 * types are allowed for targets in the attribute that happen to be file
1923 * targets (rather than rules).
1924 */
1925 private final FileTypeSet allowedFileTypesForLabels;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001926
1927 /**
1928 * This predicate-like object checks
1929 * if the edge between two rules using this attribute is valid
1930 * in the dependency graph. Returns null if valid, otherwise an error message.
1931 */
1932 private final ValidityPredicate validityPredicate;
1933
1934 private final Predicate<AttributeMap> condition;
1935
1936 private final PredicateWithMessage<Object> allowedValues;
1937
dslomovc13bb392017-08-02 23:29:54 +02001938 private final RequiredProviders requiredProviders;
Liam Miller-Cushonbbae4d92016-05-03 18:23:03 +00001939
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001940 private final ImmutableList<RuleAspect<?>> aspects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001941
nharmata977c8802018-03-21 12:18:21 -07001942 private final int hashCode;
1943
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001944 /**
dslomovde965ac2017-07-31 21:07:51 +02001945 * Constructs a rule attribute with the specified name, type and default value.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001946 *
1947 * @param name the name of the attribute
1948 * @param type the type of the attribute
dslomovde965ac2017-07-31 21:07:51 +02001949 * @param defaultValue the default value to use for this attribute if none is specified in rule
1950 * declaration in the BUILD file. Must be null, or of type "type". May be an instance of
1951 * ComputedDefault, in which case its getDefault() method must return an instance of "type",
1952 * or null. Must be immutable.
1953 * @param configTransition the configuration transition for this attribute (which must be of type
1954 * LABEL, LABEL_LIST, NODEP_LABEL or NODEP_LABEL_LIST).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001955 */
mjhalupkacfa0bb72018-03-12 12:43:15 -07001956 @VisibleForSerialization
1957 Attribute(
Yun Peng5c34e962016-02-22 15:13:19 +00001958 String name,
1959 Type<?> type,
1960 Set<PropertyFlag> propertyFlags,
1961 Object defaultValue,
gregcebe55e112018-01-30 11:04:53 -08001962 ConfigurationTransition configTransition,
Chris Parsons2e62c0d2016-04-19 22:13:59 +00001963 SplitTransitionProvider splitTransitionProvider,
Googler72f3a102017-12-01 16:28:28 -08001964 RuleClassNamePredicate allowedRuleClassesForLabels,
1965 RuleClassNamePredicate allowedRuleClassesForLabelsWarning,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001966 FileTypeSet allowedFileTypesForLabels,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001967 ValidityPredicate validityPredicate,
1968 Predicate<AttributeMap> condition,
1969 PredicateWithMessage<Object> allowedValues,
dslomovc13bb392017-08-02 23:29:54 +02001970 RequiredProviders requiredProviders,
Dmitry Lomovf188dc22016-07-19 09:00:55 +00001971 ImmutableList<RuleAspect<?>> aspects) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001972 Preconditions.checkNotNull(configTransition);
1973 Preconditions.checkArgument(
gregce7fa23ea2018-01-18 12:46:04 -08001974 (configTransition == NoTransition.INSTANCE)
Michael Staiba751f922017-02-14 15:50:04 +00001975 || type.getLabelClass() == LabelClass.DEPENDENCY
1976 || type.getLabelClass() == LabelClass.NONDEP_REFERENCE,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001977 "Configuration transitions can only be specified for label or label list attributes");
Ulf Adams07dba942015-03-05 14:47:37 +00001978 Preconditions.checkArgument(
1979 isLateBound(name) == (defaultValue instanceof LateBoundDefault),
1980 "late bound attributes require a default value that is late bound (and vice versa): %s",
1981 name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001982 if (isLateBound(name)) {
mstaib807a9b22017-09-19 17:06:32 +02001983 LateBoundDefault<?, ?> lateBoundDefault = (LateBoundDefault<?, ?>) defaultValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001984 Preconditions.checkArgument(!lateBoundDefault.useHostConfiguration()
gregce614dc502017-12-20 17:24:46 -08001985 || (configTransition.isHostTransition()),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001986 "a late bound default value using the host configuration must use the host transition");
1987 }
1988
Googlerc2200fd2018-09-14 17:35:59 -07001989 if (name.equals(FunctionSplitTransitionWhitelist.WHITELIST_ATTRIBUTE_NAME)) {
1990 Preconditions.checkArgument(
1991 BuildType.isLabelType(type),
1992 "_whitelist_function_transition attribute must be a label");
1993 Preconditions.checkArgument(
1994 defaultValue != null,
1995 "_whitelist_function_transition attribute must have a default value");
1996 Preconditions.checkArgument(
1997 ((Label) defaultValue).equals(FunctionSplitTransitionWhitelist.WHITELIST_LABEL),
1998 "_whitelist_function_transition attribute does not have the expected value "
1999 + FunctionSplitTransitionWhitelist.WHITELIST_LABEL);
2000 }
2001
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002002 this.name = name;
2003 this.type = type;
2004 this.propertyFlags = propertyFlags;
2005 this.defaultValue = defaultValue;
2006 this.configTransition = configTransition;
Chris Parsons2e62c0d2016-04-19 22:13:59 +00002007 this.splitTransitionProvider = splitTransitionProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002008 this.allowedRuleClassesForLabels = allowedRuleClassesForLabels;
2009 this.allowedRuleClassesForLabelsWarning = allowedRuleClassesForLabelsWarning;
2010 this.allowedFileTypesForLabels = allowedFileTypesForLabels;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002011 this.validityPredicate = validityPredicate;
2012 this.condition = condition;
2013 this.allowedValues = allowedValues;
dslomovc13bb392017-08-02 23:29:54 +02002014 this.requiredProviders = requiredProviders;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002015 this.aspects = aspects;
nharmata977c8802018-03-21 12:18:21 -07002016 this.hashCode = Objects.hash(
2017 name,
2018 type,
2019 propertyFlags,
2020 defaultValue,
2021 configTransition,
2022 splitTransitionProvider,
2023 allowedRuleClassesForLabels,
2024 allowedRuleClassesForLabelsWarning,
2025 allowedFileTypesForLabels,
2026 validityPredicate,
2027 condition,
2028 allowedValues,
2029 requiredProviders,
2030 aspects);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002031 }
2032
2033 /**
2034 * Returns the name of this attribute.
2035 */
2036 public String getName() {
2037 return name;
2038 }
2039
2040 /**
Laurent Le Brun7d903532015-08-20 20:04:41 +00002041 * Returns the public name of this attribute. This is the name we use in Skylark code
2042 * and we can use it to display to the end-user.
2043 * Implicit and late-bound attributes start with '_' (instead of '$' or ':').
2044 */
2045 public String getPublicName() {
Florian Weikertba405252017-01-30 14:42:50 +00002046 return getSkylarkName(getName());
Laurent Le Brun7d903532015-08-20 20:04:41 +00002047 }
2048
2049 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002050 * Returns the logical type of this attribute. (May differ from the actual
2051 * representation as a value in the build interpreter; for example, an
2052 * attribute may logically be a list of labels, but be represented as a list
2053 * of strings.)
2054 */
2055 public Type<?> getType() {
2056 return type;
2057 }
2058
2059 private boolean getPropertyFlag(PropertyFlag flag) {
2060 return propertyFlags.contains(flag);
2061 }
2062
2063 /**
2064 * Returns true if this parameter is mandatory.
2065 */
2066 public boolean isMandatory() {
2067 return getPropertyFlag(PropertyFlag.MANDATORY);
2068 }
2069
2070 /**
2071 * Returns true if this list parameter cannot have an empty list as a value.
2072 */
2073 public boolean isNonEmpty() {
2074 return getPropertyFlag(PropertyFlag.NON_EMPTY);
2075 }
2076
2077 /**
2078 * Returns true if this label parameter must produce a single artifact.
2079 */
2080 public boolean isSingleArtifact() {
2081 return getPropertyFlag(PropertyFlag.SINGLE_ARTIFACT);
2082 }
2083
2084 /**
2085 * Returns true if this label type parameter is checked by silent ruleclass filtering.
2086 */
2087 public boolean isSilentRuleClassFilter() {
2088 return getPropertyFlag(PropertyFlag.SILENT_RULECLASS_FILTER);
2089 }
2090
2091 /**
2092 * Returns true if this label type parameter skips the analysis time filetype check.
2093 */
2094 public boolean isSkipAnalysisTimeFileTypeCheck() {
2095 return getPropertyFlag(PropertyFlag.SKIP_ANALYSIS_TIME_FILETYPE_CHECK);
2096 }
2097
2098 /**
2099 * Returns true if this parameter is order-independent.
2100 */
2101 public boolean isOrderIndependent() {
2102 return getPropertyFlag(PropertyFlag.ORDER_INDEPENDENT);
2103 }
2104
2105 /**
Irina Iancu2f235992017-01-10 16:03:29 +00002106 * Returns true if output_licenses should be used for checking licensing.
2107 */
2108 public boolean useOutputLicenses() {
2109 return getPropertyFlag(PropertyFlag.OUTPUT_LICENSES);
2110 }
2111
2112 /**
Googlerc2200fd2018-09-14 17:35:59 -07002113 * Returns true if this attribute uses a function-based split transition provider. See
2114 * {@link FunctionSplitTransitionProvider}.
2115 */
2116 public boolean hasFunctionTransition() {
2117 return getPropertyFlag(PropertyFlag.HAS_FUNCTION_TRANSITION);
2118 }
2119
2120 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002121 * Returns the configuration transition for this attribute for label or label
2122 * list attributes. For other attributes it will always return {@code NONE}.
2123 */
gregcebe55e112018-01-30 11:04:53 -08002124 public ConfigurationTransition getConfigurationTransition() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002125 return configTransition;
2126 }
2127
2128 /**
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +00002129 * Returns the split configuration transition for this attribute.
2130 *
cparsons88821922017-10-11 01:21:46 +02002131 * @param attributeMapper the attribute mapper of the current {@link Rule}
Greg Estren66cadd32016-08-05 21:07:02 +00002132 * @return a SplitTransition<BuildOptions> object
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +00002133 * @throws IllegalStateException if {@link #hasSplitConfigurationTransition} is not true
Chris Parsons2e62c0d2016-04-19 22:13:59 +00002134 */
gregce6bc35ed2017-12-22 11:51:39 -08002135 public SplitTransition getSplitTransition(AttributeMap attributeMapper) {
Chris Parsons2e62c0d2016-04-19 22:13:59 +00002136 Preconditions.checkState(hasSplitConfigurationTransition());
cparsons88821922017-10-11 01:21:46 +02002137 return splitTransitionProvider.apply(attributeMapper);
Chris Parsons2e62c0d2016-04-19 22:13:59 +00002138 }
2139
2140 /**
2141 * Returns true if this attribute transitions on a split transition.
2142 * See {@link SplitTransition}.
2143 */
2144 public boolean hasSplitConfigurationTransition() {
2145 return (splitTransitionProvider != null);
2146 }
2147
2148 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002149 * Returns whether the target is required to be executable for label or label
2150 * list attributes. For other attributes it always returns {@code false}.
2151 */
2152 public boolean isExecutable() {
2153 return getPropertyFlag(PropertyFlag.EXECUTABLE);
2154 }
2155
2156 /**
2157 * Returns {@code true} iff the rule is a direct input for an action.
2158 */
2159 public boolean isDirectCompileTimeInput() {
2160 return getPropertyFlag(PropertyFlag.DIRECT_COMPILE_TIME_INPUT);
2161 }
2162
2163 /**
2164 * Returns {@code true} iff this attribute requires documentation.
2165 */
2166 public boolean isDocumented() {
2167 return !getPropertyFlag(PropertyFlag.UNDOCUMENTED);
2168 }
2169
2170 /**
2171 * Returns {@code true} iff this attribute should be published to the rule's
2172 * tag set. Note that not all Type classes support tag conversion.
2173 */
2174 public boolean isTaggable() {
2175 return getPropertyFlag(PropertyFlag.TAGGABLE);
2176 }
2177
2178 public boolean isStrictLabelCheckingEnabled() {
2179 return getPropertyFlag(PropertyFlag.STRICT_LABEL_CHECKING);
2180 }
2181
2182 /**
2183 * Returns true if the value of this attribute should be a part of a given set.
2184 */
2185 public boolean checkAllowedValues() {
2186 return getPropertyFlag(PropertyFlag.CHECK_ALLOWED_VALUES);
2187 }
2188
Greg Estren875c7a72015-09-24 19:57:54 +00002189 public boolean performPrereqValidatorCheck() {
2190 return !getPropertyFlag(PropertyFlag.SKIP_PREREQ_VALIDATOR_CHECKS);
Ulf Adams0b638972015-09-08 13:25:35 +00002191 }
2192
Greg Estren4a102512015-10-28 20:49:22 +00002193 public boolean checkConstraintsOverride() {
Greg Estren9d837842016-12-01 21:36:59 +00002194 return getPropertyFlag(PropertyFlag.CHECK_CONSTRAINTS_OVERRIDE);
2195 }
2196
2197 public boolean skipConstraintsOverride() {
2198 return getPropertyFlag(PropertyFlag.SKIP_CONSTRAINTS_OVERRIDE);
Greg Estren4a102512015-10-28 20:49:22 +00002199 }
2200
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002201 /**
2202 * Returns true if this attribute's value can be influenced by the build configuration.
2203 */
2204 public boolean isConfigurable() {
Michael Staiba751f922017-02-14 15:50:04 +00002205 // Output types are excluded because of Rule#populateExplicitOutputFiles.
2206 return !(type.getLabelClass() == LabelClass.OUTPUT
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002207 || getPropertyFlag(PropertyFlag.NONCONFIGURABLE));
2208 }
2209
2210 /**
Googler72f3a102017-12-01 16:28:28 -08002211 * Returns a predicate that evaluates to true for rule classes that are allowed labels in this
2212 * attribute. If this is not a label or label-list attribute, the returned predicate always
2213 * evaluates to true.
2214 *
2215 * <p>NOTE: This may return Predicates.<RuleClass>alwaysTrue() as a sentinel meaning "do the right
2216 * thing", rather than actually allowing all rule classes in that attribute. Others parts of bazel
2217 * code check for that specific instance.
2218 */
2219 public Predicate<RuleClass> getAllowedRuleClassesPredicate() {
2220 return allowedRuleClassesForLabels.asPredicateOfRuleClass();
2221 }
2222
2223 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002224 * Returns a predicate that evaluates to true for rule classes that are
2225 * allowed labels in this attribute. If this is not a label or label-list
2226 * attribute, the returned predicate always evaluates to true.
2227 */
Googler72f3a102017-12-01 16:28:28 -08002228 // TODO(b/69917891) Remove these methods once checkbuilddeps no longer depends on them.
2229 public Predicate<String> getAllowedRuleClassNamesPredicate() {
2230 return allowedRuleClassesForLabels.asPredicateOfRuleClassName();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002231 }
2232
2233 /**
2234 * Returns a predicate that evaluates to true for rule classes that are
2235 * allowed labels in this attribute with warning. If this is not a label or label-list
2236 * attribute, the returned predicate always evaluates to true.
2237 */
2238 public Predicate<RuleClass> getAllowedRuleClassesWarningPredicate() {
Googler72f3a102017-12-01 16:28:28 -08002239 return allowedRuleClassesForLabelsWarning.asPredicateOfRuleClass();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002240 }
2241
dslomovc13bb392017-08-02 23:29:54 +02002242 public RequiredProviders getRequiredProviders() {
2243 return requiredProviders;
Liam Miller-Cushonbbae4d92016-05-03 18:23:03 +00002244 }
2245
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002246 public FileTypeSet getAllowedFileTypesPredicate() {
2247 return allowedFileTypesForLabels;
2248 }
2249
2250 public ValidityPredicate getValidityPredicate() {
2251 return validityPredicate;
2252 }
2253
2254 public Predicate<AttributeMap> getCondition() {
2255 return condition == null ? Predicates.<AttributeMap>alwaysTrue() : condition;
2256 }
2257
2258 public PredicateWithMessage<Object> getAllowedValues() {
2259 return allowedValues;
2260 }
2261
2262 /**
Dmitry Lomovb487ac62015-11-09 13:09:12 +00002263 * Returns the list of aspects required for dependencies through this attribute.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002264 */
Dmitry Lomovb487ac62015-11-09 13:09:12 +00002265 public ImmutableList<Aspect> getAspects(Rule rule) {
shreyax6b9b6072018-02-26 18:22:13 -08002266 ImmutableList.Builder<Aspect> builder = null;
Marian Lobur702cad72015-09-02 09:53:58 +00002267 for (RuleAspect aspect : aspects) {
Googler459f1302017-04-05 19:40:35 +00002268 Aspect a = aspect.getAspect(rule);
2269 if (a != null) {
shreyax6b9b6072018-02-26 18:22:13 -08002270 if (builder == null) {
2271 builder = ImmutableList.builder();
2272 }
Googler459f1302017-04-05 19:40:35 +00002273 builder.add(a);
2274 }
Marian Lobur702cad72015-09-02 09:53:58 +00002275 }
shreyax6b9b6072018-02-26 18:22:13 -08002276 return builder == null ? ImmutableList.of() : builder.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002277 }
2278
Carmi Grushkodf9e5e12016-11-08 23:07:57 +00002279 public ImmutableList<AspectClass> getAspectClasses() {
2280 ImmutableList.Builder<AspectClass> result = ImmutableList.builder();
2281 for (RuleAspect<?> aspect : aspects) {
2282 result.add(aspect.getAspectClass());
2283 }
2284 return result.build();
2285 }
2286
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002287 /**
2288 * Returns the default value of this attribute in the context of the
2289 * specified Rule. For attributes with a computed default, i.e. {@code
2290 * hasComputedDefault()}, {@code rule} must be non-null since the result may
2291 * depend on the values of its other attributes.
2292 *
2293 * <p>The result may be null (although this is not a value in the build
2294 * language).
2295 *
2296 * <p>During population of the rule's attribute dictionary, all non-computed
2297 * defaults must be set before all computed ones.
2298 *
2299 * @param rule the rule to which this attribute belongs; non-null if
2300 * {@code hasComputedDefault()}; ignored otherwise.
2301 */
2302 public Object getDefaultValue(Rule rule) {
2303 if (!getCondition().apply(rule == null ? null : NonconfigurableAttributeMapper.of(rule))) {
2304 return null;
mstaib807a9b22017-09-19 17:06:32 +02002305 } else if (defaultValue instanceof LateBoundDefault<?, ?>) {
2306 return ((LateBoundDefault<?, ?>) defaultValue).getDefault();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002307 } else {
2308 return defaultValue;
2309 }
2310 }
2311
2312 /**
2313 * Returns the default value of this attribute, even if it has a condition, is a computed default,
2314 * or a late-bound default.
2315 */
2316 @VisibleForTesting
2317 public Object getDefaultValueForTesting() {
2318 return defaultValue;
2319 }
2320
mstaib807a9b22017-09-19 17:06:32 +02002321 public LateBoundDefault<?, ?> getLateBoundDefault() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002322 Preconditions.checkState(isLateBound());
mstaib807a9b22017-09-19 17:06:32 +02002323 return (LateBoundDefault<?, ?>) defaultValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002324 }
2325
2326 /**
2327 * Returns true iff this attribute has a computed default or a condition.
2328 *
2329 * @see #getDefaultValue(Rule)
2330 */
2331 boolean hasComputedDefault() {
Florian Weikertea6c82d2016-09-05 12:15:31 +00002332 return (defaultValue instanceof ComputedDefault)
2333 || (defaultValue instanceof SkylarkComputedDefaultTemplate)
2334 || (condition != null);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002335 }
2336
2337 /**
2338 * Returns if this attribute is an implicit dependency according to the naming policy that
2339 * designates implicit attributes.
2340 */
2341 public boolean isImplicit() {
2342 return isImplicit(getName());
2343 }
2344
2345 /**
2346 * Returns if an attribute with the given name is an implicit dependency according to the
2347 * naming policy that designates implicit attributes.
2348 */
2349 public static boolean isImplicit(String name) {
2350 return name.startsWith("$");
2351 }
2352
2353 /**
2354 * Returns if this attribute is late-bound according to the naming policy that designates
2355 * late-bound attributes.
2356 */
2357 public boolean isLateBound() {
2358 return isLateBound(getName());
2359 }
2360
2361 /**
2362 * Returns if an attribute with the given name is late-bound according to the naming policy
2363 * that designates late-bound attributes.
2364 */
2365 public static boolean isLateBound(String name) {
2366 return name.startsWith(":");
2367 }
2368
Florian Weikertba405252017-01-30 14:42:50 +00002369 /** Returns whether this attribute is considered private in Skylark. */
2370 private static boolean isPrivateAttribute(String nativeAttrName) {
2371 return isLateBound(nativeAttrName) || isImplicit(nativeAttrName);
2372 }
2373
2374 /**
2375 * Returns the Skylark-usable name of this attribute.
2376 *
2377 * Implicit and late-bound attributes start with '_' (instead of '$' or ':').
2378 */
2379 public static String getSkylarkName(String nativeAttrName) {
2380 if (isPrivateAttribute(nativeAttrName)) {
2381 return "_" + nativeAttrName.substring(1);
2382 }
2383 return nativeAttrName;
2384 }
2385
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002386 @Override
2387 public String toString() {
2388 return "Attribute(" + name + ", " + type + ")";
2389 }
2390
2391 @Override
2392 public int compareTo(Attribute other) {
2393 return name.compareTo(other.name);
2394 }
2395
janakr9ba46f82018-03-13 13:07:52 -07002396 @Override
2397 public boolean equals(Object o) {
2398 if (this == o) {
2399 return true;
2400 }
2401 if (o == null || getClass() != o.getClass()) {
2402 return false;
2403 }
2404 Attribute attribute = (Attribute) o;
nharmata977c8802018-03-21 12:18:21 -07002405 return Objects.equals(hashCode, attribute.hashCode)
2406 && Objects.equals(name, attribute.name)
janakr9ba46f82018-03-13 13:07:52 -07002407 && Objects.equals(type, attribute.type)
2408 && Objects.equals(propertyFlags, attribute.propertyFlags)
2409 && Objects.equals(defaultValue, attribute.defaultValue)
2410 && Objects.equals(configTransition, attribute.configTransition)
2411 && Objects.equals(splitTransitionProvider, attribute.splitTransitionProvider)
2412 && Objects.equals(allowedRuleClassesForLabels, attribute.allowedRuleClassesForLabels)
2413 && Objects.equals(
2414 allowedRuleClassesForLabelsWarning, attribute.allowedRuleClassesForLabelsWarning)
2415 && Objects.equals(allowedFileTypesForLabels, attribute.allowedFileTypesForLabels)
2416 && Objects.equals(validityPredicate, attribute.validityPredicate)
2417 && Objects.equals(condition, attribute.condition)
2418 && Objects.equals(allowedValues, attribute.allowedValues)
2419 && Objects.equals(requiredProviders, attribute.requiredProviders)
2420 && Objects.equals(aspects, attribute.aspects);
2421 }
2422
2423 @Override
2424 public int hashCode() {
nharmata977c8802018-03-21 12:18:21 -07002425 return hashCode;
janakr9ba46f82018-03-13 13:07:52 -07002426 }
2427
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002428 /**
2429 * Returns a replica builder of this Attribute.
2430 */
Googler74558fc2016-05-06 21:47:42 +00002431 public <TYPE> Attribute.Builder<TYPE> cloneBuilder(Type<TYPE> tp) {
2432 Preconditions.checkArgument(tp == this.type);
Michajlo Matijkiw69d9b412016-10-06 20:06:59 +00002433 Builder<TYPE> builder = new Builder<>(name, tp);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002434 builder.allowedFileTypesForLabels = allowedFileTypesForLabels;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002435 builder.allowedRuleClassesForLabels = allowedRuleClassesForLabels;
2436 builder.allowedRuleClassesForLabelsWarning = allowedRuleClassesForLabelsWarning;
dslomovc13bb392017-08-02 23:29:54 +02002437 builder.requiredProvidersBuilder = requiredProviders.copyAsBuilder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002438 builder.validityPredicate = validityPredicate;
2439 builder.condition = condition;
2440 builder.configTransition = configTransition;
Chris Parsons2e62c0d2016-04-19 22:13:59 +00002441 builder.splitTransitionProvider = splitTransitionProvider;
Greg Estren4ccabd32017-03-14 17:12:45 +00002442 builder.propertyFlags = newEnumSet(propertyFlags, PropertyFlag.class);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002443 builder.value = defaultValue;
2444 builder.valueSet = false;
2445 builder.allowedValues = allowedValues;
Dmitry Lomovf188dc22016-07-19 09:00:55 +00002446 builder.aspects = new LinkedHashMap<>();
2447 for (RuleAspect<?> aspect : aspects) {
2448 builder.aspects.put(aspect.getName(), aspect);
2449 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002450
2451 return builder;
2452 }
Googler74558fc2016-05-06 21:47:42 +00002453
2454 public Attribute.Builder<?> cloneBuilder() {
2455 return cloneBuilder(this.type);
2456 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002457}