/// <summary> /// Given the properties and dictionary of previously encountered item definitions, evaluates /// this specific item definition element and adds to the dictionary as necessary. /// </summary> /// <exception cref="InvalidProjectFileException">If the item definition is incorrectly defined</exception> private void EvaluateItemDefinitionElement(XmlElement itemDefinitionElement, BuildPropertyGroup properties, ItemDefinitionsDictionary itemDefinitionsDictionary) { ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(itemDefinitionElement); XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(itemDefinitionElement, /* sole attribute */ true); string condition = ProjectXmlUtilities.GetAttributeValue(conditionAttribute); MetadataDictionary metadataDictionary = null; string itemType = itemDefinitionElement.Name; itemDefinitionsDictionary.TryGetValue(itemType, out metadataDictionary); Expander expander = new Expander(properties, itemType, metadataDictionary); if (!Utilities.EvaluateCondition(condition, conditionAttribute, expander, ParserOptions.AllowPropertiesAndItemMetadata, parentProject)) { return; } List <XmlElement> childElements = ProjectXmlUtilities.GetValidChildElements(itemDefinitionElement); foreach (XmlElement child in childElements) { EvaluateItemDefinitionChildElement(child, properties, itemDefinitionsDictionary); } }
/// <summary> /// Given the properties and dictionary of previously encountered item definitions, evaluates /// this specific item definition child element and adds to the dictionary as necessary. /// </summary> /// <exception cref="InvalidProjectFileException">If the item definition is incorrectly defined</exception> private void EvaluateItemDefinitionChildElement(XmlElement itemDefinitionChildElement, BuildPropertyGroup properties, ItemDefinitionsDictionary itemDefinitionsDictionary) { ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(itemDefinitionChildElement); ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.IsItemSpecModifier(itemDefinitionChildElement.Name), itemDefinitionChildElement, "ItemSpecModifierCannotBeCustomMetadata", itemDefinitionChildElement.Name); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[itemDefinitionChildElement.Name] == null, itemDefinitionChildElement, "CannotModifyReservedItemMetadata", itemDefinitionChildElement.Name); XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(itemDefinitionChildElement, /* sole attribute */ true); string condition = ProjectXmlUtilities.GetAttributeValue(conditionAttribute); MetadataDictionary metadataDictionary = null; string itemType = itemDefinitionChildElement.ParentNode.Name; itemDefinitionsDictionary.TryGetValue(itemType, out metadataDictionary); Expander expander = new Expander(properties, itemType, metadataDictionary); if (!Utilities.EvaluateCondition(condition, conditionAttribute, expander, ParserOptions.AllowPropertiesAndItemMetadata, parentProject)) { return; } string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(itemDefinitionChildElement); bool containsItemVector = ItemExpander.ExpressionContainsItemVector(unevaluatedMetadataValue); // We don't allow expressions like @(foo) in the value, as no items exist at this point. ProjectErrorUtilities.VerifyThrowInvalidProject(!containsItemVector, itemDefinitionChildElement, "MetadataDefinitionCannotContainItemVectorExpression", unevaluatedMetadataValue, itemDefinitionChildElement.Name); string evaluatedMetadataValue = expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, itemDefinitionChildElement); if (metadataDictionary == null) { metadataDictionary = new MetadataDictionary(StringComparer.OrdinalIgnoreCase); itemDefinitionsDictionary.Add(itemType, metadataDictionary); } // We only store the evaluated value; build items store the unevaluated value as well, but apparently only to // gather recursive portions (its re-evaluation always goes back to the XML). // Overwrite any existing default value for this particular metadata metadataDictionary[itemDefinitionChildElement.Name] = evaluatedMetadataValue; }
internal BuildItemGroupChildXml(XmlElement element, ChildType childTypeExpected) { ErrorUtilities.VerifyThrow(element != null, "Need an XML node."); ErrorUtilities.VerifyThrowNoAssert(childTypeExpected != ChildType.Invalid, "Can't expect invalid childtype"); ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(element); this.element = element; // Loop through each of the attributes on the item element. foreach (XmlAttribute attribute in element.Attributes) { switch (attribute.Name) { case XMakeAttributes.include: this.includeAttribute = attribute; break; case XMakeAttributes.exclude: this.excludeAttribute = attribute; break; case XMakeAttributes.condition: this.conditionAttribute = attribute; break; case XMakeAttributes.xmlns: // We already verified that the namespace is correct break; case XMakeAttributes.remove: this.removeAttribute = attribute; break; case XMakeAttributes.keepMetadata: case XMakeAttributes.removeMetadata: case XMakeAttributes.keepDuplicates: // Ignore these - they are part of the new OM. break; default: ProjectXmlUtilities.ThrowProjectInvalidAttribute(attribute); break; } } this.childType = ChildType.Invalid; // Default to modify, if that's one of the child types we are told to expect. if ((childTypeExpected & ChildType.BuildItemModify) == ChildType.BuildItemModify) { this.childType = ChildType.BuildItemModify; } if (this.includeAttribute != null) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd, includeAttribute); ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(removeAttribute == null, removeAttribute); this.childType = ChildType.BuildItemAdd; } if (this.excludeAttribute != null) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd, excludeAttribute); ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(removeAttribute == null, removeAttribute); this.childType = ChildType.BuildItemAdd; } if (this.removeAttribute != null) { ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemRemove) == ChildType.BuildItemRemove, removeAttribute); ProjectErrorUtilities.VerifyThrowInvalidProject(Remove.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.remove, element.Name); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(includeAttribute == null, includeAttribute); ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(excludeAttribute == null, excludeAttribute); this.childType = ChildType.BuildItemRemove; } if (this.childType == ChildType.Invalid) { // So the xml wasn't consistent with any of the child types that we were told to expect. // Figure out the most reasonable message to produce. if ((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd) { ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name); } else if ((childTypeExpected & ChildType.BuildItemRemove) == ChildType.BuildItemRemove) { ProjectErrorUtilities.VerifyThrowInvalidProject(Remove.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.remove, element.Name); } else { ErrorUtilities.ThrowInternalError("Unexpected child type"); } } // Validate each of the child nodes beneath the item. List <XmlElement> children = ProjectXmlUtilities.GetValidChildElements(element); if (this.childType == ChildType.BuildItemRemove && children.Count != 0) { ProjectErrorUtilities.ThrowInvalidProject(element, "ChildElementsBelowRemoveNotAllowed", children[0].Name); } foreach (XmlElement child in children) { ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(child); ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.IsItemSpecModifier(child.Name), child, "ItemSpecModifierCannotBeCustomMetadata", child.Name); ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[child.Name] == null, child, "CannotModifyReservedItemMetadata", child.Name); } }