/// <summary> /// Add items to the world. This is the in-target equivalent of an item include expression outside of a target. /// </summary> private void ExecuteAdd(BuildItemGroupChildXml child, ItemBucket bucket) { // By making the items "not persisted", we ensure they are cleaned away when the project is reset BuildItem item = new BuildItem(child.Element, false /* not imported */, false /* not persisted */, itemDefinitionLibrary); // If the condition on the item is false, Evaluate returns an empty group BuildItemGroup itemsToAdd = item.Evaluate(bucket.Expander, executionDirectory, true /* expand metadata */, ParserOptions.AllowAll, loggingServices, buildEventContext); bucket.Lookup.AddNewItems(itemsToAdd); }
/// <summary> /// Modifies items in the world - specifically, changes their metadata. Changes to items that are part of the project manifest are backed up, so /// they can be reverted when the project is reset after the end of the build. /// </summary> /// <param name="child"></param> /// <param name="bucket"></param> private void ExecuteModify(BuildItemGroupChildXml child, ItemBucket bucket) { if (!Utilities.EvaluateCondition(child.Condition, child.ConditionAttribute, bucket.Expander, ParserOptions.AllowAll, loggingServices, buildEventContext)) { return; } BuildItemGroup group = (BuildItemGroup)bucket.Lookup.GetItems(child.Name); if (group == null) { // No items of this type to modify return; } // Figure out what metadata names and values we need to set Dictionary <string, string> metadataToSet = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); List <XmlElement> metadataElements = child.GetChildren(); foreach (XmlElement metadataElement in metadataElements) { bool metadataCondition = true; XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(metadataElement, true /*no other attributes allowed*/); if (conditionAttribute != null) { metadataCondition = Utilities.EvaluateCondition(conditionAttribute.Value, conditionAttribute, bucket.Expander, ParserOptions.AllowAll, loggingServices, buildEventContext); } if (metadataCondition) { string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(metadataElement); string evaluatedMetadataValue = bucket.Expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, metadataElement); // The last metadata with a particular name, wins, so we just set through the indexer here. metadataToSet[metadataElement.Name] = evaluatedMetadataValue; } } bucket.Lookup.ModifyItems(child.Name, group, metadataToSet); }
/// <summary> /// Remove items from the world. Removes to items that are part of the project manifest are backed up, so /// they can be reverted when the project is reset after the end of the build. /// </summary> private void ExecuteRemove(BuildItemGroupChildXml child, ItemBucket bucket) { if (!Utilities.EvaluateCondition(child.Condition, child.ConditionAttribute, bucket.Expander, ParserOptions.AllowAll, loggingServices, buildEventContext)) { return; } BuildItemGroup group = bucket.Lookup.GetItems(child.Name); if (group == null) { // No items of this type to remove return; } List <BuildItem> itemsToRemove = BuildItemGroup.FindItemsMatchingSpecification(group, child.Remove, child.RemoveAttribute, bucket.Expander, executionDirectory); if (itemsToRemove != null) { bucket.Lookup.RemoveItems(itemsToRemove); } }
/// <summary> /// Creates an IntrinsicTask object around a "task" node /// </summary> internal IntrinsicTask(XmlElement taskNodeXmlElement, EngineLoggingServices loggingServices, BuildEventContext eventContext, string executionDirectory, ItemDefinitionLibrary itemDefinitionLibrary) { this.taskNodeXmlElement = taskNodeXmlElement; this.conditionAttribute = taskNodeXmlElement.Attributes[XMakeAttributes.condition]; this.loggingServices = loggingServices; this.buildEventContext = eventContext; this.executionDirectory = executionDirectory; this.itemDefinitionLibrary = itemDefinitionLibrary; ErrorUtilities.VerifyThrow(IsIntrinsicTaskName(taskNodeXmlElement.Name), "Only PropertyGroup and ItemGroup are known intrinsic tasks"); switch (taskNodeXmlElement.Name) { case XMakeElements.propertyGroup: backingType = BackingType.PropertyGroup; // If the backing type is a property group, we can just use a property group object; its semantics aren't // tangled up with the project object. Put another way, we only really need the code that understands the XML // format of a property group, and we can get that without the rest of BuildPropertyGroup getting in the way. // Specify that these properties are output properties, so they get reverted when the project is reset. backingPropertyGroup = new BuildPropertyGroup(null /* no parent project */, taskNodeXmlElement, PropertyType.OutputProperty); break; case XMakeElements.itemGroup: backingType = BackingType.ItemGroup; // If the backing type is an item group, we just re-use the code that understands the XML format of an item group; // the semantics of BuildItemGroup are too coupled to its current use in the Project object for us to re-use it. backingItemGroupXml = new BuildItemGroupXml(taskNodeXmlElement); List <XmlElement> children = backingItemGroupXml.GetChildren(); backingBuildItemGroupChildren = new List <BuildItemGroupChildXml>(children.Count); foreach (XmlElement child in children) { BuildItemGroupChildXml childXml = new BuildItemGroupChildXml(child, ChildType.Any); backingBuildItemGroupChildren.Add(childXml); } break; } }
/// <summary> /// Adds batchable parameters from an item element into the list. If the item element was a task, these /// would be its raw parameter values. /// </summary> private void GetBatchableValuesFromBuildItemGroupChild(List <string> parameterValues, BuildItemGroupChildXml child) { AddIfNotEmptyString(parameterValues, child.Include); AddIfNotEmptyString(parameterValues, child.Exclude); AddIfNotEmptyString(parameterValues, child.Remove); AddIfNotEmptyString(parameterValues, child.Condition); List <XmlElement> metadataElements = child.GetChildren(); foreach (XmlElement metadataElement in metadataElements) { AddIfNotEmptyString(parameterValues, Utilities.GetXmlNodeInnerContents(metadataElement)); XmlAttribute conditionAttribute = metadataElement.Attributes[XMakeAttributes.condition]; if (conditionAttribute != null) { AddIfNotEmptyString(parameterValues, conditionAttribute.Value); } } }