/// <summary>
        /// Parses the target's "Inputs" and "Outputs" attributes and gathers up referenced items.
        /// </summary>
        /// <param name="bucket"></param>
        /// <param name="itemVectorsInTargetInputs"></param>
        /// <param name="itemVectorTransformsInTargetInputs"></param>
        /// <param name="discreteItemsInTargetInputs"></param>
        /// <param name="itemVectorsInTargetOutputs"></param>
        /// <param name="discreteItemsInTargetOutputs"></param>
        /// <param name="targetOutputItemSpecs"></param>
        /// <owner>SumedhK</owner>
        private void ParseTargetInputOutputSpecifications
        (
            ItemBucket bucket,
            out Hashtable itemVectorsInTargetInputs,
            out Hashtable itemVectorTransformsInTargetInputs,
            out Hashtable discreteItemsInTargetInputs,
            out Hashtable itemVectorsInTargetOutputs,
            out Hashtable discreteItemsInTargetOutputs,
            out ArrayList targetOutputItemSpecs
        )
        {
            // break down the input/output specifications along the standard separator, after expanding all embedded properties
            // and item metadata
            Expander propertyAndMetadataExpander = new Expander(bucket.Expander, ExpanderOptions.ExpandPropertiesAndMetadata);
            List<string> targetInputs = propertyAndMetadataExpander.ExpandAllIntoStringListLeaveEscaped(TargetInputSpecification, this.targetInputsAttribute);
            List<string> targetOutputs = propertyAndMetadataExpander.ExpandAllIntoStringListLeaveEscaped(TargetOutputSpecification, this.targetOutputsAttribute);

            itemVectorTransformsInTargetInputs = new Hashtable(StringComparer.OrdinalIgnoreCase);

            // figure out which of the inputs are:
            // 1) item vectors
            // 2) item vectors with transforms
            // 3) "discrete" items i.e. items that do not reference item vectors
            SeparateItemVectorsFromDiscreteItems(this.targetInputsAttribute, targetInputs, bucket,
                out itemVectorsInTargetInputs,
                itemVectorTransformsInTargetInputs,
                out discreteItemsInTargetInputs);

            // figure out which of the outputs are:
            // 1) item vectors (with or without transforms)
            // 2) "discrete" items i.e. items that do not reference item vectors
            SeparateItemVectorsFromDiscreteItems(this.targetOutputsAttribute, targetOutputs, bucket,
                out itemVectorsInTargetOutputs,
                null /* don't want transforms separated */,
                out discreteItemsInTargetOutputs);

            // list out all the output item-specs
            targetOutputItemSpecs = GetItemSpecsFromItemVectors(itemVectorsInTargetOutputs);
            targetOutputItemSpecs.AddRange(discreteItemsInTargetOutputs.Values);
        }
Exemple #2
0
        /// <summary>
        /// Determines if the new item spec that the user is trying to add to the project
        /// already matches an existing wildcarded item declared in the project.  We only
        /// consider it a "match" in very specific circumstances... if there's anything
        /// weird or not-mainline about the new item spec or the existing item, we fail
        /// the match in order to "play it safe".
        /// </summary>
        internal bool NewItemSpecMatchesExistingWildcard(string newItemSpec)
        {
            Project parentProject = GetParentProject();
            ErrorUtilities.VerifyThrow(parentProject != null, "This method should only get called on persisted items.");
            BuildPropertyGroup evaluatedProperties = parentProject.evaluatedProperties;

            if (
                    // The original item spec should have had at least one "*" or "?" in it.
                    FileMatcher.HasWildcards(this.Include) &&

                    // The original item should not have a Condition.
                    (this.Condition.Length == 0) &&

                    // The original item should not have an Exclude.
                    (this.Exclude.Length == 0) &&

                    // The new item spec should NOT have any wildcards.
                    !FileMatcher.HasWildcards(newItemSpec)
                )
            {
                Expander propertyExpander = new Expander(evaluatedProperties);
                string newItemSpecExpandedEscaped = propertyExpander.ExpandAllIntoStringLeaveEscaped(newItemSpec, null);
                // New item spec should not have any unescaped semicolons ... this can really mess us up.
                if (-1 == newItemSpecExpandedEscaped.IndexOf(';'))
                {
                    // Expand any properties in the new item spec that the user gave us.
                    string newItemSpecExpandedUnescaped = EscapingUtilities.UnescapeAll(newItemSpecExpandedEscaped);

                    // Loop over each piece separated by semicolons.
                    List<string> itemIncludePieces = propertyExpander.ExpandAllIntoStringListLeaveEscaped(this.Include, this.IncludeAttribute);
                    foreach (string itemIncludePiece in itemIncludePieces)
                    {
                        bool containsEscapedWildcards = EscapingUtilities.ContainsEscapedWildcards(itemIncludePiece);
                        bool containsRealWildcards = FileMatcher.HasWildcards(itemIncludePiece);

                        // If this is the piece that has the wildcards ...
                        if (containsRealWildcards && !containsEscapedWildcards)
                        {
                            string itemIncludePieceContainingWildcardUnescaped = EscapingUtilities.UnescapeAll(itemIncludePiece);

                            FileMatcher.Result match = FileMatcher.FileMatch(itemIncludePieceContainingWildcardUnescaped, newItemSpecExpandedUnescaped);

                            if (match.isLegalFileSpec && match.isMatch)
                            {
                                // The wildcard in the original item spec will match the new item that
                                // user is trying to add.
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
Exemple #3
0
        /// <summary>
        /// Sets the project's default targets from the given list of semi-colon-separated target names after expanding all
        /// embedded properties in the list.
        /// </summary>
        /// <owner>SumedhK</owner>
        /// <param name="defaultTargetsList"></param>
        /// <param name="propertyBag"></param>
        private void SetDefaultTargets(string defaultTargetsList, BuildPropertyGroup propertyBag)
        {
            Expander propertyExpander = new Expander(propertyBag);

            this.defaultTargetNames = propertyExpander.ExpandAllIntoStringListLeaveEscaped(defaultTargetsList, null).ToArray();

            BuildProperty defaultTargetsProperty = new BuildProperty(ReservedPropertyNames.projectDefaultTargets,
                                                           propertyExpander.ExpandAllIntoStringLeaveEscaped(defaultTargetsList, null),
                                                           PropertyType.ReservedProperty);

            this.ReservedProperties.SetProperty(defaultTargetsProperty);

            // we also need to push this property directly into the evaluatedProperties bucket
            // since this property was computed "late", i.e. after the initial evaluation.
            this.evaluatedProperties.SetProperty(defaultTargetsProperty);
        }
Exemple #4
0
        public void ExpandAllIntoStringListLeaveEscapedComplex()
        {
            ReadOnlyLookup lookup;
            Dictionary<string, string> itemMetadata;
            CreateComplexPropertiesItemsMetadata(out lookup, out itemMetadata);

            Expander expander = new Expander(lookup, itemMetadata);

            XmlAttribute xmlattribute = (new XmlDocument()).CreateAttribute("dummy");
            xmlattribute.Value = "@(Resource->'%(Filename)') ; @(Content) ; @(NonExistent) ; $(NonExistent) ; %(NonExistent) ; " +
                "$(OutputPath) ; $(TargetPath) ; %(Language)_%(Culture)";

            List<string> expanded = expander.ExpandAllIntoStringListLeaveEscaped(xmlattribute.Value, xmlattribute);

            Assertion.AssertEquals(9, expanded.Count);
            Assertion.AssertEquals(@"string$(p)", expanded[0]);
            Assertion.AssertEquals(@"dialogs%253b", expanded[1]);
            Assertion.AssertEquals(@"splash.bmp", expanded[2]);
            Assertion.AssertEquals(@"\jk", expanded[3]);
            Assertion.AssertEquals(@"l\mno%253bpqr\stu", expanded[4]);
            Assertion.AssertEquals(@"subdir1\", expanded[5]);
            Assertion.AssertEquals(@"subdir2\", expanded[6]);
            Assertion.AssertEquals(@"english_abc%253bdef", expanded[7]);
            Assertion.AssertEquals(@"ghi", expanded[8]);

            expanded = expander.ExpandAllIntoStringListLeaveEscaped(xmlattribute);

            Assertion.AssertEquals(9, expanded.Count);
            Assertion.AssertEquals(@"string$(p)", expanded[0]);
            Assertion.AssertEquals(@"dialogs%253b", expanded[1]);
            Assertion.AssertEquals(@"splash.bmp", expanded[2]);
            Assertion.AssertEquals(@"\jk", expanded[3]);
            Assertion.AssertEquals(@"l\mno%253bpqr\stu", expanded[4]);
            Assertion.AssertEquals(@"subdir1\", expanded[5]);
            Assertion.AssertEquals(@"subdir2\", expanded[6]);
            Assertion.AssertEquals(@"english_abc%253bdef", expanded[7]);
            Assertion.AssertEquals(@"ghi", expanded[8]);
        }
Exemple #5
0
        /// <summary>
        /// Returns a list of all items in the provided item group whose itemspecs match the specification, after it is split and any wildcards are expanded.
        /// If not items match, returns null.
        /// </summary>
        internal static List<BuildItem> FindItemsMatchingSpecification(BuildItemGroup items, string specification, XmlAttribute attribute, Expander expander, string baseDirectory)
        {
            if (items.Count == 0 || specification.Length == 0)
            {
                return null;
            }

            // This is a hashtable whose key is the filename for the individual items
            // in the Exclude list, after wildcard expansion.  The value in the hash table
            // is just an empty string.
            Hashtable specificationsToFind = new Hashtable(StringComparer.OrdinalIgnoreCase);

            // Split by semicolons
            List<string> specificationPieces = expander.ExpandAllIntoStringListLeaveEscaped(specification, attribute);

            foreach (string piece in specificationPieces)
            {
                // Take each individual path or file expression, and expand any
                // wildcards.  Then loop through each file returned, and add it
                // to our hashtable.

                // Don't unescape wildcards just yet - if there were any escaped, the caller wants to treat them
                // as literals. Everything else is safe to unescape at this point, since we're only matching
                // against the file system.
                string[] fileList = EngineFileUtilities.GetFileListEscaped(baseDirectory, piece);

                foreach (string file in fileList)
                {
                    // Now unescape everything, because this is the end of the road for this filename.
                    // We're just going to compare it to the unescaped include path to filter out the
                    // file excludes.
                    specificationsToFind[EscapingUtilities.UnescapeAll(file)] = String.Empty;
                }
            }

            if (specificationsToFind.Count == 0)
            {
                return null;
            }

            // Now loop through our list and filter out any that match a
            // filename in the remove list.
            List<BuildItem> itemsRemoved = new List<BuildItem>();

            foreach (BuildItem item in items)
            {
                // Even if the case for the excluded files is different, they
                // will still get excluded, as expected.  However, if the excluded path
                // references the same file in a different way, such as by relative
                // path instead of absolute path, we will not realize that they refer
                // to the same file, and thus we will not exclude it.
                if (specificationsToFind.ContainsKey(item.FinalItemSpec))
                {
                    itemsRemoved.Add(item);
                }
            }

            return itemsRemoved;
        }
Exemple #6
0
        /// <summary>
        /// Uses the given task output specification to (statically) infer the task's outputs.
        /// </summary>
        /// <param name="taskOutputSpecification"></param>
        /// <param name="taskParameterName"></param>
        /// <param name="itemName">can be null</param>
        /// <param name="propertyName">can be null</param>
        /// <param name="bucket"></param>
        private void InferTaskOutputs
        (
            Lookup lookup,
            TaskOutput taskOutputSpecification,
            string taskParameterName,
            string itemName,
            string propertyName,
            ItemBucket bucket
        )
        {
            // if the task has a value set for the output parameter, expand all embedded properties and item metadata in it
            XmlAttribute taskParameterAttribute = null;

            // Lookup attribute name needs to be case-insensitive
            // DevDiv bugs: 33981
            foreach (XmlAttribute taskNodeAttribute in taskNode.Attributes)
            {
                if (String.Compare(taskNodeAttribute.Name, taskParameterName, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    taskParameterAttribute = taskNodeAttribute;
                    break;
                }
            }
 
            if (taskParameterAttribute != null)
            {
                if (taskOutputSpecification.IsItemVector)
                {
                    // This is an output item.

                    ErrorUtilities.VerifyThrow((itemName != null) && (itemName.Length > 0), "Need item type.");

                    // Expand only with properties first, so that expressions like Include="@(foo)" will transfer the metadata of the "foo" items as well, not just their item specs.
                    Expander propertyAndMetadataExpander = new Expander(bucket.Expander, ExpanderOptions.ExpandPropertiesAndMetadata);
                    List<string> outputItemSpecs = propertyAndMetadataExpander.ExpandAllIntoStringListLeaveEscaped(taskParameterAttribute);

                    foreach (string outputItemSpec in outputItemSpecs)
                    {
                        BuildItemGroup items = bucket.Expander.ExpandSingleItemListExpressionIntoItemsLeaveEscaped(outputItemSpec, taskParameterAttribute);

                        // if the output item-spec is an item vector, get the items in it
                        if (items != null)
                        {
                            foreach (BuildItem item in items)
                            {
                                // we want to preserve the attributes on the item
                                BuildItem clonedItem = item.VirtualClone();
                                // but we do need to change the item type
                                clonedItem.Name = itemName;

                                lookup.AddNewItem(clonedItem);
                            }
                        }
                        else
                        {
                            // if the output item-spec is not an item vector, accept it as-is
                            lookup.AddNewItem(new BuildItem(itemName, outputItemSpec));
                        }
                    }
                }
                else
                {
                    // This is an output property.

                    Debug.Assert(taskOutputSpecification.IsProperty);
                    ErrorUtilities.VerifyThrow((propertyName != null) && (propertyName.Length > 0), "Need property name.");

                    string taskParameterValue = bucket.Expander.ExpandAllIntoString(taskParameterAttribute);

                    if (taskParameterValue.Length > 0)
                    {
                        lookup.SetProperty(new BuildProperty(propertyName, taskParameterValue, PropertyType.OutputProperty));
                    }
                }
            }
        }