private static void addOutputGroups( Object value, Location loc, RuleConfiguredTargetBuilder builder) throws EvalException { Map<String, SkylarkValue> outputGroups = SkylarkType.castMap(value, String.class, SkylarkValue.class, "output_groups"); for (String outputGroup : outputGroups.keySet()) { SkylarkValue objects = outputGroups.get(outputGroup); NestedSet<Artifact> artifacts; String typeErrorMessage = "Output group '%s' is of unexpected type. " + "Should be list or set of Files, but got '%s' instead."; if (objects instanceof SkylarkList) { NestedSetBuilder<Artifact> nestedSetBuilder = NestedSetBuilder.stableOrder(); for (Object o : (SkylarkList) objects) { if (o instanceof Artifact) { nestedSetBuilder.add((Artifact) o); } else { throw new EvalException( loc, String.format( typeErrorMessage, outputGroup, "list with an element of " + EvalUtils.getDataTypeNameFromClass(o.getClass()))); } } artifacts = nestedSetBuilder.build(); } else { artifacts = SkylarkType.cast( objects, SkylarkNestedSet.class, Artifact.class, loc, typeErrorMessage, outputGroup, EvalUtils.getDataTypeName(objects, true)) .getSet(Artifact.class); } builder.addOutputGroup(outputGroup, artifacts); } }
private static <T> T cast( String paramName, ClassObject struct, Class<T> expectedType, Location loc) throws EvalException { Object value = struct.getValue(paramName); return SkylarkType.cast( value, expectedType, loc, "expected %s for '%s' but got %s instead: %s", SkylarkType.of(expectedType), paramName, EvalUtils.getDataTypeName(value, false), value); }
private void checkCompositeSkylarkObjectSafe(Object object) { if (object instanceof SkylarkApiProvider) { return; } else if (object instanceof SkylarkList) { SkylarkList list = (SkylarkList) object; if (list == SkylarkList.EMPTY_LIST || isSimpleSkylarkObjectSafe(list.getContentType().getType())) { // Try not to iterate over the list if avoidable. return; } // The list can be a tuple or a list of composite items. for (Object listItem : list) { checkSkylarkObjectSafe(listItem); } return; } else if (object instanceof SkylarkNestedSet) { // SkylarkNestedSets cannot have composite items. Class<?> contentType = ((SkylarkNestedSet) object).getContentType().getType(); if (!contentType.equals(Object.class) && !isSimpleSkylarkObjectSafe(contentType)) { throw new IllegalArgumentException(EvalUtils.getDataTypeName(contentType)); } return; } else if (object instanceof Map<?, ?>) { for (Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) { checkSkylarkObjectSafe(entry.getKey()); checkSkylarkObjectSafe(entry.getValue()); } return; } else if (object instanceof ClassObject) { ClassObject struct = (ClassObject) object; for (String key : struct.getKeys()) { checkSkylarkObjectSafe(struct.getValue(key)); } return; } throw new IllegalArgumentException(EvalUtils.getDataTypeName(object)); }
@Override public boolean containsKey(Object key, Location loc) throws EvalException { if (!(key instanceof SkylarkClassObjectConstructor)) { throw new EvalException( loc, String.format( "Type Target only supports querying by object constructors, got %s instead", EvalUtils.getDataTypeName(key))); } SkylarkClassObjectConstructor constructor = (SkylarkClassObjectConstructor) key; SkylarkProviders provider = getProvider(SkylarkProviders.class); if (provider != null) { Object declaredProvider = provider.getDeclaredProvider(constructor.getKey()); if (declaredProvider != null) { return true; } } return false; }
@Override public Object getIndex(Object key, Location loc) throws EvalException { if (!(key instanceof SkylarkClassObjectConstructor)) { throw new EvalException( loc, String.format( "Type Target only supports indexing by object constructors, got %s instead", EvalUtils.getDataTypeName(key))); } SkylarkClassObjectConstructor constructor = (SkylarkClassObjectConstructor) key; SkylarkProviders provider = getProvider(SkylarkProviders.class); if (provider != null) { Object declaredProvider = provider.getDeclaredProvider(constructor.getKey()); if (declaredProvider != null) { return declaredProvider; } } // Either provider or declaredProvider is null throw new EvalException( loc, String.format( "Object of type Target doesn't contain declared provider %s", constructor.getKey().getExportedName())); }
private void resolveLateBoundAttributes( Rule rule, BuildConfiguration configuration, BuildConfiguration hostConfiguration, AttributeMap attributeMap, Iterable<Attribute> attributes, ImmutableSortedKeyListMultimap.Builder<Attribute, LabelAndConfiguration> builder) throws EvalException, InterruptedException { for (Attribute attribute : attributes) { if (!attribute.isLateBound() || !attribute.getCondition().apply(attributeMap)) { continue; } List<BuildConfiguration> actualConfigurations = ImmutableList.of(configuration); if (attribute.getConfigurationTransition() instanceof SplitTransition<?>) { Preconditions.checkState(attribute.getConfigurator() == null); // TODO(bazel-team): This ends up applying the split transition twice, both here and in the // visitRule method below - this is not currently a problem, because the configuration graph // never contains nested split transitions, so the second application is idempotent. actualConfigurations = configuration.getSplitConfigurations( (SplitTransition<?>) attribute.getConfigurationTransition()); } for (BuildConfiguration actualConfig : actualConfigurations) { @SuppressWarnings("unchecked") LateBoundDefault<BuildConfiguration> lateBoundDefault = (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault(); if (lateBoundDefault.useHostConfiguration()) { actualConfig = hostConfiguration; } // TODO(bazel-team): This might be too expensive - can we cache this somehow? if (!lateBoundDefault.getRequiredConfigurationFragments().isEmpty()) { if (!actualConfig.hasAllFragments(lateBoundDefault.getRequiredConfigurationFragments())) { continue; } } // TODO(bazel-team): We should check if the implementation tries to access an undeclared // fragment. Object actualValue = lateBoundDefault.getDefault(rule, actualConfig); if (EvalUtils.isNullOrNone(actualValue)) { continue; } try { if (attribute.getType() == BuildType.LABEL) { Label label = BuildType.LABEL.cast(actualValue); builder.put(attribute, LabelAndConfiguration.of(label, actualConfig)); } else if (attribute.getType() == BuildType.LABEL_LIST) { for (Label label : BuildType.LABEL_LIST.cast(actualValue)) { builder.put(attribute, LabelAndConfiguration.of(label, actualConfig)); } } else { throw new IllegalStateException( String.format( "Late bound attribute '%s' is not a label or a label list", attribute.getName())); } } catch (ClassCastException e) { throw new EvalException( rule.getLocation(), String.format( "When computing the default value of %s, expected '%s', got '%s'", attribute.getName(), attribute.getType(), EvalUtils.getDataTypeName(actualValue, true))); } } } }