public void GetMetadataBeforeEvaluate() { XmlElement group = XmlTestUtilities.CreateBasicElement("ItemDefinitionGroup"); ItemDefinitionLibrary library = new ItemDefinitionLibrary(new Project()); library.Add(group); library.GetDefaultMetadataValue("ccompile", "defines"); }
internal Lookup(Hashtable itemsByName, BuildItemGroup projectItems, BuildPropertyGroup properties, ItemDefinitionLibrary itemDefinitionLibrary) { ErrorUtilities.VerifyThrow(itemDefinitionLibrary != null, "Expect library"); this.projectItems = projectItems; this.itemDefinitionLibrary = itemDefinitionLibrary; LookupEntry entry = new LookupEntry(itemsByName, properties); lookupEntries.AddFirst(entry); }
public void Basic() { XmlElement group = XmlTestUtilities.CreateBasicElement("ItemDefinitionGroup"); XmlElement item = XmlTestUtilities.AddChildElement(group, "CCompile"); XmlElement meta = XmlTestUtilities.AddChildElementWithInnerText(item, "Defines", "DEBUG"); ItemDefinitionLibrary library = new ItemDefinitionLibrary(new Project()); library.Add(group); library.Evaluate(null); Assertion.AssertEquals("DEBUG", library.GetDefaultMetadataValue("ccompile", "defines")); }
/// <summary> /// Copy constructor (called via Clone() - clearer semantics) /// </summary> private Lookup(Lookup that) { // Add the same tables from the original foreach (LookupEntry entry in that.lookupEntries) { this.lookupEntries.AddLast(entry); } this.projectItems = that.projectItems; this.itemDefinitionLibrary = that.itemDefinitionLibrary; // Clones need to share an (item)clone table; the batching engine asks for items from the lookup, // then populates buckets with them, which have clone lookups. this.cloneTable = that.cloneTable; }
public void SameGroupTwoChildrenSameItemTypeDifferentMetadata() { XmlElement group = XmlTestUtilities.CreateBasicElement("ItemDefinitionGroup"); XmlElement item1 = XmlTestUtilities.AddChildElement(group, "CCompile"); XmlElement meta1 = XmlTestUtilities.AddChildElementWithInnerText(item1, "Defines", "DEBUG"); XmlElement item2 = XmlTestUtilities.AddChildElement(group, "CCompile"); XmlElement meta2 = XmlTestUtilities.AddChildElementWithInnerText(item1, "WarningLevel", "W4"); ItemDefinitionLibrary library = new ItemDefinitionLibrary(new Project()); library.Add(group); library.Evaluate(null); Assertion.AssertEquals("DEBUG", library.GetDefaultMetadataValue("ccompile", "defines")); Assertion.AssertEquals("W4", library.GetDefaultMetadataValue("ccompile", "warninglevel")); }
/// <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> /// Creates a new item with an XML element backing it. Use this to add a new persisted item to the project file. /// </summary> /// <param name="ownerDocument">can be null</param> /// <param name="name">can be null</param> internal BuildItem(XmlDocument ownerDocument, string name, string include, ItemDefinitionLibrary itemDefinitionLibrary) : this(ownerDocument, name, include, true /* create custom metadata cache */, itemDefinitionLibrary) { }
/// <summary> /// Verifies that an item definition library is supplied. /// This is for internal error checking only. /// </summary> private void MustHaveItemDefinitionLibrary(ItemDefinitionLibrary library) { ErrorUtilities.VerifyThrow(library != null, "Item definition library required when item is owned by project"); }
/// <summary> /// Constructor /// </summary> internal SpecificItemDefinitionLibrary(string itemType, ItemDefinitionLibrary itemDefinitionLibrary) { this.itemType = itemType; this.itemDefinitionLibrary = itemDefinitionLibrary; }
private static BuildItem CreateBuildItemFromXmlDocument(XmlDocument doc) { ItemDefinitionLibrary itemDefinitionLibrary = new ItemDefinitionLibrary(new Project()); itemDefinitionLibrary.Evaluate(new BuildPropertyGroup()); BuildItem item = new BuildItem((XmlElement)doc.FirstChild, false, itemDefinitionLibrary); return item; }
private static ItemDefinitionLibrary NewAndEvaluateItemDefinitionLibraryXml(XmlElement group) { ItemDefinitionLibrary library = new ItemDefinitionLibrary(new Project()); library.Add(group); BuildPropertyGroup properties = new BuildPropertyGroup(); properties.SetProperty("p1", "v1"); library.Evaluate(properties); return library; }
/// <summary> /// This constructor initializes a persisted item from an existing item /// element which exists either in the main project file or one of the /// imported files. /// </summary> internal BuildItem(XmlElement itemElement, bool importedFromAnotherProject, ItemDefinitionLibrary itemDefinitionLibrary) : this(itemElement, importedFromAnotherProject, true /* part of project manifest */, itemDefinitionLibrary) { }
/// <summary> /// Creates either a new item with an XML element backing it, or a virtual /// item. To conserve memory, this constructor does not allocate storage /// for custom metadata, unless told to do so. /// </summary> /// <remarks> /// PERF WARNING: Allocating memory for the custom metadata cache is expensive /// when a build generates a large number of items. /// </remarks> /// <param name="ownerDocument">can be null</param> /// <param name="name">can be null</param> private BuildItem(XmlDocument ownerDocument, string name, string include, bool createCustomMetadataCache, ItemDefinitionLibrary itemDefinitionLibrary) { BuildItemHelper(ownerDocument, name, include, createCustomMetadataCache, itemDefinitionLibrary); }
internal static ItemDefinitionLibrary CreateEmptyEvaluatedItemDefinitionLibrary() { ItemDefinitionLibrary itemDefinitionLibrary = new ItemDefinitionLibrary(new Project()); itemDefinitionLibrary.Evaluate(new BuildPropertyGroup()); return itemDefinitionLibrary; }
public void PropertyInMetadataValue() { XmlElement group = XmlTestUtilities.CreateBasicElement("ItemDefinitionGroup"); XmlElement item = XmlTestUtilities.AddChildElement(group, "CCompile"); XmlElement meta = XmlTestUtilities.AddChildElementWithInnerText(item, "Defines", "$(p1)"); ItemDefinitionLibrary library = new ItemDefinitionLibrary(new Project()); library.Add(group); BuildPropertyGroup pg1 = new BuildPropertyGroup(); pg1.SetProperty("p1", "v1"); library.Evaluate(pg1); Assertion.AssertEquals("v1", library.GetDefaultMetadataValue("ccompile", "defines")); // Change the original property group -- should not affect the metadata value which was // already evaluated pg1.SetProperty("p1", "v1b"); Assertion.AssertEquals("v1", library.GetDefaultMetadataValue("ccompile", "defines")); // Reevaluate with another property value BuildPropertyGroup pg2 = new BuildPropertyGroup(); pg2.SetProperty("p1", "v2"); library.Evaluate(pg2); Assertion.AssertEquals("v2", library.GetDefaultMetadataValue("ccompile", "defines")); }
/// <summary> /// Common code for constructors. If an ownerDocument is passed in, it's a persisted element. /// </summary> /// <param name="itemName">can be null</param> /// <param name="itemDefinitionLibrary">can only be null if ownerDocument is null</param> private void BuildItemHelper(XmlDocument ownerDocument, string itemName, string itemInclude, bool createCustomMetadataCache, ItemDefinitionLibrary itemDefinitionLibraryToUse) { // Only check for null. It's legal to make BuildItems with empty // item specs -- this is to be consistent with how we shipped TaskItem. // See #567058. ErrorUtilities.VerifyThrowArgumentNull(itemInclude, "itemInclude"); // Validate that the item name doesn't contain any illegal characters. if (itemName != null) { XmlUtilities.VerifyThrowValidElementName(itemName); ErrorUtilities.VerifyThrowInvalidOperation(XMakeElements.IllegalItemPropertyNames[itemName] == null, "CannotModifyReservedItem", itemName); } // If no owner document was passed in, then it's not going to have an // XML element backing it. if (ownerDocument == null) { this.include = itemInclude; this.isPartOfProjectManifest = false; } else { ErrorUtilities.VerifyThrowArgumentLength(itemName, "itemType"); MustHaveItemDefinitionLibrary(itemDefinitionLibraryToUse); // The caller has given us an owner document, so we're going to create a // new item element associated with that document. The new item element // doesn't actually get added to the XML document automatically. this.xml = new BuildItemGroupChildXml(ownerDocument, itemName, itemInclude); this.isPartOfProjectManifest = true; } if (createCustomMetadataCache) { // PERF NOTE: only create cache if told to do so, because creating // this cache for a large number of items is expensive InitializeCustomMetadataCache(); } this.name = itemName; // The evaluated and final item specs start off initialized to the "Include" attribute. this.evaluatedItemSpecEscaped = itemInclude; this.finalItemSpecEscaped = itemInclude; this.importedFromAnotherProject = false; this.itemDefinitionLibrary = itemDefinitionLibraryToUse; }
/// <summary> /// Creates an instance of this class for the given engine, specifying a tools version to /// use during builds of this project. /// </summary> /// <owner>RGoel</owner> /// <param name="engine">Engine that will build this project. May be null if the global engine is expected.</param> /// <param name="toolsVersion">Tools version to use during builds of this project instance. May be null, /// in which case we will use the value in the Project's ToolsVersion attribute, or else the engine /// default value.</param> public Project ( Engine engine, string toolsVersion ) { #if MSBUILDENABLEVSPROFILING try { DataCollection.CommentMarkProfile(8808, "Construct Project Using Old OM - Start"); #endif #if (!STANDALONEBUILD) using (new CodeMarkerStartEnd(CodeMarkerEvent.perfMSBuildProjectConstructBegin, CodeMarkerEvent.perfMSBuildProjectConstructEnd)) #endif { if (engine == null) { engine = Engine.GlobalEngine; } this.parentEngine = engine; this.projectId = parentEngine.GetNextProjectId(); this.projectBuildEventContext = new BuildEventContext(parentEngine.NodeId, BuildEventContext.InvalidTargetId, parentEngine.GetNextProjectId(), BuildEventContext.InvalidTaskId); this.isLoadedByHost = true; this.buildEnabled = BuildEnabledSetting.UseParentEngineSetting; this.isValidated = false; // Create a new XML document and add a <Project> element. This way, the // project is always in a valid state from the beginning, and now somebody // can start programmatically adding stuff to the <Project>. this.mainProjectEntireContents = new XmlDocument(); this.mainProjectElement = mainProjectEntireContents.CreateElement(XMakeElements.project, XMakeAttributes.defaultXmlNamespace); this.mainProjectEntireContents.AppendChild(mainProjectElement); // initialize all case-insensitive hash-tables this.conditionedPropertiesTable = new Hashtable(StringComparer.OrdinalIgnoreCase); this.evaluatedItemsByName = new Hashtable(StringComparer.OrdinalIgnoreCase); this.evaluatedItemsByNameIgnoringCondition = new Hashtable(StringComparer.OrdinalIgnoreCase); // Create the group collection. All collection elements are stored here. this.rawGroups = new GroupingCollection(null /* null parent means this is the master collection */); // Initialize all property-related objects. // (see above for initialization of this.conditionedPropertiesTable) this.globalProperties = null; this.environmentProperties = null; this.reservedProperties = null; // We still create the rawPropertyGroups collection, but // it's just a facade over rawGroups this.rawPropertyGroups = new BuildPropertyGroupCollection(this.rawGroups); this.evaluatedProperties = new BuildPropertyGroup(); // Initialize all item-related objects. // (see above for initialization of this.evaluatedItemsByName and this.evaluatedItemsByNameIgnoringCondition // We still create the rawItemGroups collection, but it's just a facade over rawGroups this.rawItemGroups = new BuildItemGroupCollection(this.rawGroups); this.evaluatedItems = new BuildItemGroup(); this.evaluatedItemsIgnoringCondition = new BuildItemGroup(); this.itemDefinitionLibrary = new ItemDefinitionLibrary(this); // Initialize all target- and task-related objects. this.usingTasks = new UsingTaskCollection(); this.imports = new ImportCollection(this); this.taskRegistry = new TaskRegistry(); this.targets = new TargetCollection(this); // Initialize the default targets, initial targets, and project file name. this.defaultTargetNames = new string[0]; this.initialTargetNamesInMainProject = new ArrayList(); this.initialTargetNamesInImportedProjects = new ArrayList(); this.FullFileName = String.Empty; this.projectDirectory = String.Empty; this.projectExtensionsNode = null; // If the toolsVersion is null, we will use the value specified in // the Project element's ToolsVersion attribute, or else the default if that // attribute is not present. if (null != toolsVersion) { this.ToolsVersion = toolsVersion; } this.MarkProjectAsDirtyForReprocessXml(); // The project doesn't really need to be saved yet; there's nothing in it! this.dirtyNeedToSaveProjectFile = false; this.IsReset = false; // Grab some initial properties from the Engine. // Global properties and reserved properties need to be cloned, because // different projects may have different sets of properties or values // for these. Environment properties don't have to be cloned, because // the environment is captured once at engine instantiation, and // shared by all projects thereafter. this.GlobalProperties = this.parentEngine.GlobalProperties; this.EnvironmentProperties = this.parentEngine.EnvironmentProperties; } #if MSBUILDENABLEVSPROFILING } finally { DataCollection.CommentMarkProfile(8809, "Construct Project Using Old OM - End"); } #endif }
/// <summary> /// This constructor initializes an item from an item element. /// It is part of the project manifest or not as specified. /// </summary> internal BuildItem(XmlElement itemElement, bool importedFromAnotherProject, bool isPartOfProjectManifest, ItemDefinitionLibrary itemDefinitionLibrary) { MustHaveItemDefinitionLibrary(itemDefinitionLibrary); InitializeFromItemElement(itemElement); this.importedFromAnotherProject = importedFromAnotherProject; this.isPartOfProjectManifest = isPartOfProjectManifest; this.itemDefinitionLibrary = itemDefinitionLibrary; ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[name] == null, ItemElement, "CannotModifyReservedItem", name); }
/// <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; } }
internal Lookup(Hashtable itemsByName, BuildPropertyGroup properties, ItemDefinitionLibrary itemDefinitionLibrary) : this(itemsByName, new BuildItemGroup(), properties, itemDefinitionLibrary) { }
internal static BuildItem GetXmlBackedItemWithDefinitionLibrary() { string content = @"<i xmlns='http://schemas.microsoft.com/developer/msbuild/2003' Include='i1'/>"; XmlDocument doc = new XmlDocument(); doc.LoadXml(content); XmlElement groupElement = XmlTestUtilities.CreateBasicElement("ItemDefinitionGroup"); XmlElement itemElement = XmlTestUtilities.AddChildElement(groupElement, "i"); XmlElement metaElement = XmlTestUtilities.AddChildElementWithInnerText(itemElement, "m", "m1"); XmlElement metaElement2 = XmlTestUtilities.AddChildElementWithInnerText(itemElement, "o", "o1"); ItemDefinitionLibrary library = new ItemDefinitionLibrary(new Project()); library.Add(groupElement); library.Evaluate(null); BuildItem item = new BuildItem((XmlElement)doc.FirstChild, false, library); item.SetMetadata("n", "n1"); return item; }