/// <summary> /// Read in and validate an <ItemDefinitionGroup> element and all its children. /// This is currently only called from ItemDefinitionLibrary. Projects don't know about it. /// </summary> internal BuildItemDefinitionGroupXml(XmlElement element, Project parentProject) { ProjectXmlUtilities.VerifyThrowElementName(element, XMakeElements.itemDefinitionGroup); ProjectXmlUtilities.VerifyThrowProjectValidNamespace(element); this.element = element; this.parentProject = parentProject; this.conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(element, /* sole attribute */ true); this.condition = ProjectXmlUtilities.GetAttributeValue(conditionAttribute); // Currently, don't bother validating the children until evaluation time }
/// <summary> /// Constructor for the Choose object. Parses the contents of the Choose /// and sets up list of When blocks /// </summary> /// <remarks> /// </remarks> /// <owner>DavidLe</owner> /// <param name="parentProject"></param> /// <param name="parentGroupingCollection"></param> /// <param name="chooseElement"></param> /// <param name="importedFromAnotherProject"></param> /// <param name="nestingDepth">stack overflow guard</param> internal Choose ( Project parentProject, GroupingCollection parentGroupingCollection, XmlElement chooseElement, bool importedFromAnotherProject, int nestingDepth ) { whenClauseList = new ArrayList(); error.VerifyThrow(chooseElement != null, "Need valid <Choose> element."); // Make sure this really is the <Choose> node. ProjectXmlUtilities.VerifyThrowElementName(chooseElement, XMakeElements.choose); // Stack overflow guard. The only way in the MSBuild file format that MSBuild elements can be // legitimately nested without limit is the <Choose> construct. So, enforce a nesting limit // to avoid blowing our stack. nestingDepth++; ProjectErrorUtilities.VerifyThrowInvalidProject(nestingDepth <= maximumChooseNesting, chooseElement, "ChooseOverflow", maximumChooseNesting); this.importedFromAnotherProject = importedFromAnotherProject; // This <Choose> is coming from an existing XML element, so // walk through all the attributes and child elements, creating the // necessary When objects. // No attributes on the <Choose> element, so don't allow any. ProjectXmlUtilities.VerifyThrowProjectNoAttributes(chooseElement); bool foundOtherwise = false; // Loop through the child nodes of the <Choose> element. foreach (XmlNode chooseChildNode in chooseElement) { switch (chooseChildNode.NodeType) { // Handle XML comments under the <PropertyGroup> node (just ignore them). case XmlNodeType.Comment: // fall through case XmlNodeType.Whitespace: // ignore whitespace break; case XmlNodeType.Element: // The only two types of child nodes that a <Choose> element can contain // is are <When> elements and zero or one <Otherwise> elements. ProjectXmlUtilities.VerifyThrowProjectValidNamespace((XmlElement)chooseChildNode); if (chooseChildNode.Name == XMakeElements.when) { // don't allow <When> to follow <Otherwise> ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise, chooseChildNode, "WhenNotAllowedAfterOtherwise"); When newWhen = new When(parentProject, parentGroupingCollection, (XmlElement)chooseChildNode, importedFromAnotherProject, When.Options.ProcessWhen, nestingDepth); this.whenClauseList.Add(newWhen); } else if (chooseChildNode.Name == XMakeElements.otherwise) { ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise, chooseChildNode, "MultipleOtherwise"); When newWhen = new When(parentProject, parentGroupingCollection, (XmlElement)chooseChildNode, importedFromAnotherProject, When.Options.ProcessOtherwise, nestingDepth); otherwiseClause = newWhen; foundOtherwise = true; } else { ProjectXmlUtilities.ThrowProjectInvalidChildElement(chooseChildNode); } break; default: // Unrecognized child element. ProjectXmlUtilities.ThrowProjectInvalidChildElement(chooseChildNode); break; } } ProjectErrorUtilities.VerifyThrowInvalidProject(this.whenClauseList.Count != 0, chooseElement, "ChooseMustContainWhen"); }
/// <summary> /// Helper method for processing the children of a When. Only parses Choose, /// PropertyGroup, and ItemGroup. All other tags result in an error. /// </summary> /// <remarks> /// </remarks> /// <owner>DavidLe</owner> /// <param name="parentNode"></param> /// <param name="parentProjectForChildren"></param> /// <param name="importedFromAnotherProject"></param> /// <param name="options"></param> /// <param name="nestingDepth">Number of parent <Choose> elements this is nested inside</param> private void ProcessWhenChildren ( XmlElement parentNode, Project parentProjectForChildren, bool importedFromAnotherProject, int nestingDepth ) { // Loop through the child nodes of the <When> element. foreach (XmlNode whenChildNode in parentNode) { switch (whenChildNode.NodeType) { // Handle XML comments under the <When> node (just ignore them). case XmlNodeType.Comment: // fall through case XmlNodeType.Whitespace: // ignore whitespace break; case XmlNodeType.Element: { // Make sure this element doesn't have a custom namespace ProjectXmlUtilities.VerifyThrowProjectValidNamespace((XmlElement)whenChildNode); // The only three types of child nodes that a <When> element can contain // are <PropertyGroup>, <ItemGroup> and <Choose>. switch (whenChildNode.Name) { case XMakeElements.itemGroup: BuildItemGroup newItemGroup = new BuildItemGroup((XmlElement)whenChildNode, importedFromAnotherProject, parentProjectForChildren); this.propertyAndItemLists.InsertAtEnd(newItemGroup); break; // Process the <PropertyGroup> element. case XMakeElements.propertyGroup: BuildPropertyGroup newPropertyGroup = new BuildPropertyGroup(parentProjectForChildren, (XmlElement)whenChildNode, importedFromAnotherProject); newPropertyGroup.EnsureNoReservedProperties(); this.propertyAndItemLists.InsertAtEnd(newPropertyGroup); break; // Process the <Choose> element. case XMakeElements.choose: Choose newChoose = new Choose(parentProjectForChildren, this.PropertyAndItemLists, (XmlElement)whenChildNode, importedFromAnotherProject, nestingDepth); this.propertyAndItemLists.InsertAtEnd(newChoose); break; default: { ProjectXmlUtilities.ThrowProjectInvalidChildElement(whenChildNode); break; } } } break; default: { ProjectXmlUtilities.ThrowProjectInvalidChildElement(whenChildNode); break; } } } }