private void deserializeRule(DeserializationContext context, Build.Rule rulePb) throws PackageDeserializationException, InterruptedException { Location ruleLocation = EmptyLocation.INSTANCE; RuleClass ruleClass = packageDeserializationEnvironment.getRuleClass(rulePb, ruleLocation); Map<String, ParsedAttributeValue> attributeValues = new HashMap<>(); for (Build.Attribute attrPb : rulePb.getAttributeList()) { Type<?> type = ruleClass.getAttributeByName(attrPb.getName()).getType(); attributeValues.put(attrPb.getName(), deserializeAttribute(type, attrPb)); } Label ruleLabel = deserializeLabel(rulePb.getName()); try { Rule rule = ruleClass.createRuleWithParsedAttributeValues( ruleLabel, context.packageBuilder, ruleLocation, attributeValues, NullEventHandler.INSTANCE, new AttributeContainerWithoutLocation(ruleClass)); context.packageBuilder.addRule(rule); Preconditions.checkState(!rule.containsErrors()); } catch (NameConflictException | LabelSyntaxException e) { throw new PackageDeserializationException(e); } }
private static ParsedAttributeValue deserializeAttribute( Type<?> expectedType, Build.Attribute attrPb) throws PackageDeserializationException { Object value = deserializeAttributeValue(expectedType, attrPb); return new ParsedAttributeValue( attrPb.hasExplicitlySpecified() && attrPb.getExplicitlySpecified(), value, EmptyLocation.INSTANCE); }
private void deserializeRule(DeserializationContext context, Build.Rule rulePb) throws PackageDeserializationException, InterruptedException { Location ruleLocation = EmptyLocation.INSTANCE; RuleClass ruleClass = packageDeserializationEnvironment.getRuleClass(rulePb, ruleLocation); Map<String, ParsedAttributeValue> attributeValues = new HashMap<>(); AttributesToDeserialize attrToDeserialize = packageDeserializationEnvironment.attributesToDeserialize(); Hasher hasher = Hashing.md5().newHasher(); for (Build.Attribute attrPb : rulePb.getAttributeList()) { Type<?> type = ruleClass.getAttributeByName(attrPb.getName()).getType(); attributeValues.put(attrPb.getName(), deserializeAttribute(type, attrPb)); if (attrToDeserialize.addSyntheticAttributeHash) { // TODO(bazel-team): This might give false positives because of explicit vs implicit. hasher.putBytes(attrPb.toByteArray()); } } AttributeContainerWithoutLocation attributeContainer = new AttributeContainerWithoutLocation(ruleClass, hasher.hash()); Label ruleLabel = deserializeLabel(rulePb.getName()); try { Rule rule = createRuleWithParsedAttributeValues( ruleClass, ruleLabel, context.packageBuilder, ruleLocation, attributeValues, NullEventHandler.INSTANCE, attributeContainer); context.packageBuilder.addRule(rule); // Remove the attribute after it is added to package in order to pass the validations // and be able to compute all the outputs. if (attrToDeserialize != DESERIALIZE_ALL_ATTRS) { for (String attrName : attributeValues.keySet()) { Attribute attribute = ruleClass.getAttributeByName(attrName); if (!(attrToDeserialize.shouldKeepAttributeWithName.apply(attrName) || BuildType.isLabelType(attribute.getType()))) { attributeContainer.clearIfNotLabel(attrName); } } } Preconditions.checkState(!rule.containsErrors()); } catch (NameConflictException | LabelSyntaxException e) { throw new PackageDeserializationException(e); } }
private static List<?> deserializeGlobs(List<?> matches, Build.Attribute attrPb) { if (attrPb.getGlobCriteriaCount() == 0) { return matches; } Builder<GlobCriteria> criteriaBuilder = ImmutableList.builder(); for (Build.GlobCriteria criteriaPb : attrPb.getGlobCriteriaList()) { if (criteriaPb.hasGlob() && criteriaPb.getGlob()) { criteriaBuilder.add( GlobCriteria.fromGlobCall( ImmutableList.copyOf(criteriaPb.getIncludeList()), ImmutableList.copyOf(criteriaPb.getExcludeList()))); } else { criteriaBuilder.add( GlobCriteria.fromList(ImmutableList.copyOf(criteriaPb.getIncludeList()))); } } @SuppressWarnings({"unchecked", "rawtypes"}) GlobList<?> result = new GlobList(criteriaBuilder.build(), matches); return result; }
// TODO(bazel-team): Verify that these put sane values in the attribute @VisibleForTesting static Object deserializeAttributeValue(Type<?> expectedType, Build.Attribute attrPb) throws PackageDeserializationException { switch (attrPb.getType()) { case INTEGER: return attrPb.hasIntValue() ? new Integer(attrPb.getIntValue()) : null; case STRING: if (!attrPb.hasStringValue()) { return null; } else if (expectedType == BuildType.NODEP_LABEL) { return deserializeLabel(attrPb.getStringValue()); } else { return attrPb.getStringValue(); } case LABEL: case OUTPUT: return attrPb.hasStringValue() ? deserializeLabel(attrPb.getStringValue()) : null; case STRING_LIST: if (expectedType == BuildType.NODEP_LABEL_LIST) { return deserializeGlobs(deserializeLabels(attrPb.getStringListValueList()), attrPb); } else { return deserializeGlobs(ImmutableList.copyOf(attrPb.getStringListValueList()), attrPb); } case LABEL_LIST: case OUTPUT_LIST: return deserializeGlobs(deserializeLabels(attrPb.getStringListValueList()), attrPb); case DISTRIBUTION_SET: return deserializeDistribs(attrPb.getStringListValueList()); case LICENSE: return attrPb.hasLicense() ? deserializeLicense(attrPb.getLicense()) : null; case STRING_DICT: { // Building an immutable map will fail if the builder was given duplicate keys. These // entry // lists may contain duplicate keys if the serialized map value was configured (e.g. via // the select function) and the different configuration values had keys in common. This is // because serialization flattens configurable map-valued attributes. // // As long as serialization does this flattening, to avoid failure during deserialization, // we dedupe entries in the list by their keys. // TODO(bazel-team): Serialize and deserialize configured values with fidelity (without // flattening them). ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (Build.StringDictEntry entry : attrPb.getStringDictValueList()) { String key = entry.getKey(); if (keysSeenSoFar.add(key)) { builder.put(key, entry.getValue()); } } return builder.build(); } case STRING_DICT_UNARY: { // See STRING_DICT case's comment about why this dedupes entries by their keys. ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (StringDictUnaryEntry entry : attrPb.getStringDictUnaryValueList()) { String key = entry.getKey(); if (keysSeenSoFar.add(key)) { builder.put(key, entry.getValue()); } } return builder.build(); } case FILESET_ENTRY_LIST: return deserializeFilesetEntries(attrPb.getFilesetListValueList()); case LABEL_LIST_DICT: { // See STRING_DICT case's comment about why this dedupes entries by their keys. ImmutableMap.Builder<String, List<Label>> builder = ImmutableMap.builder(); HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (Build.LabelListDictEntry entry : attrPb.getLabelListDictValueList()) { String key = entry.getKey(); if (keysSeenSoFar.add(key)) { builder.put(key, deserializeLabels(entry.getValueList())); } } return builder.build(); } case STRING_LIST_DICT: { // See STRING_DICT case's comment about why this dedupes entries by their keys. ImmutableMap.Builder<String, List<String>> builder = ImmutableMap.builder(); HashSet<String> keysSeenSoFar = Sets.newHashSet(); for (Build.StringListDictEntry entry : attrPb.getStringListDictValueList()) { String key = entry.getKey(); if (keysSeenSoFar.add(key)) { builder.put(key, ImmutableList.copyOf(entry.getValueList())); } } return builder.build(); } case BOOLEAN: return attrPb.hasBooleanValue() ? attrPb.getBooleanValue() : null; case TRISTATE: return attrPb.hasStringValue() ? deserializeTriStateValue(attrPb.getStringValue()) : null; case INTEGER_LIST: return ImmutableList.copyOf(attrPb.getIntListValueList()); default: throw new PackageDeserializationException("Invalid discriminator: " + attrPb.getType()); } }