/// <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; } } } }
/// <summary> /// Internal constructor /// </summary> /// <param name="importElement"></param> /// <param name="isImported"></param> /// <owner>LukaszG</owner> internal Import(XmlElement importElement, Project parentProject, bool isImported) { this.importedFromAnotherProject = isImported; // Make sure the <Import> node has been given to us. ErrorUtilities.VerifyThrow(importElement != null, "Need an XML node representing the <Import> element."); this.importElement = importElement; // Make sure we have a valid parent Project ErrorUtilities.VerifyThrow(parentProject != null, "Need a parent Project object to instantiate an Import."); this.parentProject = parentProject; // Make sure this really is the <Import> node. ProjectXmlUtilities.VerifyThrowElementName(importElement, XMakeElements.import); // Loop through the list of attributes on the <Import> element. foreach (XmlAttribute importAttribute in importElement.Attributes) { switch (importAttribute.Name) { // The "project" attribute points us at the project file to import. case XMakeAttributes.project: // Just store the attribute value at this point. We want to make sure that we evaluate any // Condition attribute before looking at the Project attribute - if the Condition is going to be false, // it's legitimate for the value of the Project attribute to be completely invalid. // For example, <Import Project="$(A)" Condition="$(A)!=''"/> should not cause an error // that the Project attribute is empty. this.projectPathAttribute = importAttribute; break; // If the "condition" attribute is present, then it must evaluate to "true". case XMakeAttributes.condition: this.conditionAttribute = importAttribute; break; // We've come across an attribute in the <Import> element that we // don't recognize. Fail due to invalid project file. default: ProjectXmlUtilities.ThrowProjectInvalidAttribute(importAttribute); break; } } ProjectErrorUtilities.VerifyThrowInvalidProject((this.projectPathAttribute != null) && (this.projectPathAttribute.Value.Length != 0), importElement, "MissingRequiredAttribute", XMakeAttributes.project, XMakeElements.import); // Make sure this node has no children. Our schema doesn't support having // children beneath the <Import> element. if (importElement.HasChildNodes) { // Don't put the "if" condition inside the first parameter to // VerifyThrow..., because we'll get null reference exceptions, // since the parameter importElement.FirstChild.Name is being // passed in regardless of whether the condition holds true or not. ProjectXmlUtilities.ThrowProjectInvalidChildElement(importElement.FirstChild); } }
/// <summary> /// Creates a new UsingTask object /// </summary> /// <param name="usingTaskNode"></param> /// <param name="isImported"></param> /// <owner>LukaszG</owner> internal UsingTask(XmlElement usingTaskNode, bool isImported) { this.importedFromAnotherProject = isImported; // make sure this really is a <UsingTask> tag ErrorUtilities.VerifyThrow(usingTaskNode.Name == XMakeElements.usingTask, "Expected <{0}> element; received <{1}> element.", XMakeElements.usingTask, usingTaskNode.Name); bool illegalChildElementFound = false; XmlElement illegalChildElement = null; foreach (XmlElement childElement in usingTaskNode.ChildNodes) { switch (childElement.Name) { case XMakeElements.usingTaskBody: // ignore break; case XMakeElements.usingTaskParameter: // ignore break; case XMakeElements.usingTaskParameterGroup: // ignore break; default: illegalChildElementFound = true; illegalChildElement = childElement; break; } if (illegalChildElementFound) { break; } } // UsingTask has no valid child elements in 3.5 syntax, but in 4.0 syntax it does. // So ignore any valid 4.0 child elements and try to load the project as usual, but // still error out if something we don't expect is found. if (illegalChildElementFound) { ProjectXmlUtilities.ThrowProjectInvalidChildElement(illegalChildElement); } foreach (XmlAttribute usingTaskAttribute in usingTaskNode.Attributes) { switch (usingTaskAttribute.Name) { // get the task name case XMakeAttributes.taskName: taskNameAttribute = usingTaskAttribute; break; // get the assembly name or the assembly file/path, whichever is specified... case XMakeAttributes.assemblyName: assemblyNameAttribute = usingTaskAttribute; break; case XMakeAttributes.assemblyFile: assemblyFileAttribute = usingTaskAttribute; break; // ignore any RequiredRuntime XML attribute // (we'll make this actually do something when we run on a CLR other than v2.0) case XMakeAttributes.requiredRuntime: // Do nothing break; // get the condition, if any case XMakeAttributes.condition: conditionAttribute = usingTaskAttribute; break; // This is only recognized by the new OM: // Just ignore it case XMakeAttributes.requiredPlatform: // Do nothing break; // This is only recognized by the new OM: // Just ignore it case XMakeAttributes.taskFactory: // Do nothing break; // This is only recognized by the new OM: // Just ignore it case XMakeAttributes.runtime: // Do nothing break; // This is only recognized by the new OM: // Just ignore it case XMakeAttributes.architecture: // Do nothing break; default: ProjectXmlUtilities.ThrowProjectInvalidAttribute(usingTaskAttribute); break; } } ProjectErrorUtilities.VerifyThrowInvalidProject(taskNameAttribute != null, usingTaskNode, "MissingRequiredAttribute", XMakeAttributes.taskName, XMakeElements.usingTask); ProjectErrorUtilities.VerifyThrowInvalidProject(taskNameAttribute.Value.Length > 0, taskNameAttribute, "InvalidAttributeValue", taskNameAttribute.Value, XMakeAttributes.taskName, XMakeElements.usingTask); ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyNameAttribute != null) || (assemblyFileAttribute != null), usingTaskNode, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, XMakeAttributes.assemblyFile); ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyNameAttribute == null) || (assemblyFileAttribute == null), usingTaskNode, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, XMakeAttributes.assemblyFile); ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyNameAttribute == null) || (assemblyNameAttribute.Value.Length > 0), assemblyNameAttribute, "InvalidAttributeValue", String.Empty, XMakeAttributes.assemblyName, XMakeElements.usingTask); ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyFileAttribute == null) || (assemblyFileAttribute.Value.Length > 0), assemblyFileAttribute, "InvalidAttributeValue", String.Empty, XMakeAttributes.assemblyFile, XMakeElements.usingTask); }
/// <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"); }