Example #1
0
        /// <summary>
        /// Populate the lists of evaluated and unevaluated metadata with all metadata that have true conditions.
        /// </summary>
        /// <remarks>
        /// FUTURE: Currently this isn't done when the item is constructed; so for example HasMetadata will always return
        /// false until EvaluatedAllItemMetadata is explicitly called. The reason for this is that Metadata are
        /// not first class objects, they are merely string pairs produced by running over the child XML with a particular expander.
        /// When Metadata are first class objects this method can be changed to merely evaluate them, 
        /// just as BuildItemGroup.Evaluate does for BuildItem, then methods like HasMetadata behave more sanely. Of course this
        /// could be a breaking change.
        /// </remarks>
        internal void EvaluateAllItemMetadata
        (
            Expander expander,
            ParserOptions parserOptions,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext
        )
        {
            ErrorUtilities.VerifyThrow(expander != null, "Null expander passed in.");

            // Cache all custom attributes on the item. For a persisted item, this will walk the item's child nodes, and
            // cache the custom attributes using a "last one wins" policy. For a virtual item, this method does nothing.

            // We only evaluate metadata by reading XML
            if (IsBackedByXml)
            {
                ErrorUtilities.VerifyThrow((this.evaluatedCustomMetadata != null) && (this.unevaluatedCustomMetadata != null),
                    "Item is not initialized properly.");

                // We're evaluating from scratch, so clear out any old cached attributes.
                this.evaluatedCustomMetadata.Clear();
                this.unevaluatedCustomMetadata.Clear();

                // Let the expander know about our own item type, so it can
                // expand unqualified metadata expressions
                SpecificItemDefinitionLibrary specificItemDefinitionLibrary = new SpecificItemDefinitionLibrary(name, itemDefinitionLibrary);
                expander = new Expander(expander, specificItemDefinitionLibrary);

                List<XmlElement> metadataElements = xml.GetChildren();

                // look at all the item's child nodes
                foreach (XmlElement metadataElement in metadataElements)
                {
                    // confirm that the child node is not conditionally disabled
                    bool condition = true;
                    XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(metadataElement, true /*no other attributes allowed*/);

                    if (conditionAttribute != null)
                    {
                        condition = Utilities.EvaluateCondition(conditionAttribute.Value,
                            conditionAttribute, expander, null, parserOptions,
                            loggingServices, buildEventContext);
                    }

                    if (condition)
                    {
                        // cache its value, both the evaluated and unevaluated.
                        string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(metadataElement);
                        unevaluatedCustomMetadata[metadataElement.Name] = unevaluatedMetadataValue;
                        string evaluatedMetadataValue = expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, metadataElement);
                        evaluatedCustomMetadata[metadataElement.Name] = evaluatedMetadataValue;

                        // Add this metadata to the running table we're using, so that one piece of metadata can refer to another one above
                        expander.SetMetadataInMetadataTable(name, metadataElement.Name, evaluatedMetadataValue);

                    }
                }
            }
        }
Example #2
0
        public void PropertyFunctionConsumingItemMetadata()
        {
            MockLogger logger = new MockLogger();
            Project project = ObjectModelHelpers.CreateInMemoryProject(@"
                <Project ToolsVersion=`3.5` xmlns=`msbuildnamespace`>
                </Project>
            ", logger);


            BuildPropertyGroup pg = new BuildPropertyGroup();
            pg.SetProperty("SomePath", @"c:\some\path");

            BuildItemGroup ig = new BuildItemGroup();
            BuildItem item = new BuildItem("Compile", "fOo.Cs");
            item.SetMetadata("SomeMeta", "fOo.Cs");
            ig.AddItem(item);

            Hashtable itemsByType = new Hashtable(StringComparer.OrdinalIgnoreCase);
            itemsByType["Compile"] = ig;

            Expander expander = new Expander(pg, itemsByType, ExpanderOptions.ExpandAll);
            expander.SetMetadataInMetadataTable("Compile", "SomeMeta", "fOo.Cs");

            string result = expander.ExpandAllIntoStringLeaveEscaped(@"$([System.IO.Path]::Combine($(SomePath),%(Compile.SomeMeta)))", null);

            Assertion.AssertEquals(@"c:\some\path\fOo.Cs", result);
        }