Пример #1
0
        public void ExpandItemVectorFunctionsMetadataValueMultiItem()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateItemFunctionExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");

            IList<ProjectItemInstance> items = expander.ExpandIntoItemsLeaveEscaped("@(i->Metadata('Meta10')->DirectoryName())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(20, items.Count);
            Assert.Equal("i", items[5].ItemType);
            Assert.Equal("i", items[6].ItemType);
            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), @"secondd;rectory"), items[5].EvaluatedInclude);
            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), @"someo;herplace"), items[6].EvaluatedInclude);
        }
Пример #2
0
        public void ExpandItemVectorFunctionsClearMetadata()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateItemFunctionExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");

            IList<ProjectItemInstance> items = expander.ExpandIntoItemsLeaveEscaped("@(i->ClearMetadata())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(10, items.Count);
            Assert.Equal("i", items[5].ItemType);
            Assert.Equal(0, items[5].Metadata.Count());
        }
Пример #3
0
        public void ExpandItemVectorFunctionsItemSpecModifier2()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateItemFunctionExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");

            IList<ProjectItemInstance> itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->'%(Meta0)'->'%(Directory)')", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(10, itemsTrue.Count);
            Assert.Equal("i", itemsTrue[5].ItemType);
            Assert.Equal(@"firstdirectory\seconddirectory\", itemsTrue[5].EvaluatedInclude);

            itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->'%(Meta0)'->'%(Filename)')", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(10, itemsTrue.Count);
            Assert.Equal("i", itemsTrue[5].ItemType);
            Assert.Equal(@"file0", itemsTrue[5].EvaluatedInclude);

            itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->'%(Meta0)'->'%(Extension)'->Distinct())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(1, itemsTrue.Count);
            Assert.Equal("i", itemsTrue[0].ItemType);
            Assert.Equal(@".ext", itemsTrue[0].EvaluatedInclude);

            itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->'%(Meta0)'->'%(Filename)'->Substring($(Val)))", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(10, itemsTrue.Count);
            Assert.Equal("i", itemsTrue[5].ItemType);
            Assert.Equal(@"le0", itemsTrue[5].EvaluatedInclude);
        }
Пример #4
0
        public void ExpandItemVectorFunctionsGetDirectoryNameOfMetadataValue()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateItemFunctionExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");

            IList<ProjectItemInstance> itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->Metadata('Meta0')->DirectoryName())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(10, itemsTrue.Count);
            Assert.Equal("i", itemsTrue[5].ItemType);
            Assert.Equal(@"c:\firstdirectory\seconddirectory", itemsTrue[5].EvaluatedInclude);
        }
Пример #5
0
        public void ExpandItemVectorsIntoProjectItemInstancesWithoutSpecifyingItemType()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project);

            IList<ProjectItemInstance> items = expander.ExpandIntoItemsLeaveEscaped("@(i)", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(2, items.Count);
            Assert.Equal("i", items[0].ItemType);
            Assert.Equal("i", items[1].ItemType);
            Assert.Equal("i0", items[0].EvaluatedInclude);
            Assert.Equal("i1", items[1].EvaluatedInclude);
        }
Пример #6
0
        public void ExpandItemVectorFunctionsAnyHaveMetadataValue()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateItemFunctionExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");

            IList<ProjectItemInstance> itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->AnyHaveMetadataValue('Even', 'true'))", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(1, itemsTrue.Count);
            Assert.Equal("i", itemsTrue[0].ItemType);
            Assert.Equal("true", itemsTrue[0].EvaluatedInclude);

            IList<ProjectItemInstance> itemsFalse = expander.ExpandIntoItemsLeaveEscaped("@(i->AnyHaveMetadataValue('Even', 'goop'))", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.Equal(1, itemsFalse.Count);
            Assert.Equal("i", itemsFalse[0].ItemType);
            Assert.Equal("false", itemsFalse[0].EvaluatedInclude);
        }
Пример #7
0
        public void ExpandPropertiesIntoProjectPropertyInstances()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("a", "aaa"));
            pg.Set(ProjectPropertyInstance.Create("b", "bbb"));
            pg.Set(ProjectPropertyInstance.Create("c", "cc;dd"));

            Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg);

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");
            IList<ProjectItemInstance> itemsOut = expander.ExpandIntoItemsLeaveEscaped("foo$(a);$(b);$(c);$(d", itemFactory, ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(5, itemsOut.Count);
        }
Пример #8
0
        /// <summary>
        /// Takes an item specification, evaluates it and expands it into a list of items
        /// </summary>
        /// <param name="originalItem">The original item data</param>
        /// <param name="expander">The expander to use.</param>
        /// <remarks>
        /// This code is very close to that which exists in the Evaluator.EvaluateItemXml method.  However, because
        /// it invokes type constructors, and those constructors take arguments of fundamentally different types, it has not
        /// been refactored.
        /// </remarks>
        /// <returns>A list of items.</returns>
        private IList<ProjectItemInstance> ExpandItemIntoItems
        (
            ProjectItemGroupTaskItemInstance originalItem,
            Expander<ProjectPropertyInstance, ProjectItemInstance> expander,
            ISet<string> keepMetadata,
            ISet<string> removeMetadata
        )
        {
            ProjectErrorUtilities.VerifyThrowInvalidProject(!(keepMetadata != null && removeMetadata != null), originalItem.KeepMetadataLocation, "KeepAndRemoveMetadataMutuallyExclusive");
            IList<ProjectItemInstance> items = new List<ProjectItemInstance>();

            // UNDONE: (Refactor)  This code also exists in largely the same form in Evaluator.CreateItemsFromInclude.
            // STEP 1: Expand properties and metadata in Include
            string evaluatedInclude = expander.ExpandIntoStringLeaveEscaped(originalItem.Include, ExpanderOptions.ExpandPropertiesAndMetadata, originalItem.IncludeLocation);

            // STEP 2: Split Include on any semicolons, and take each split in turn
            if (evaluatedInclude.Length > 0)
            {
                IList<string> includeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedInclude);
                ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(this.Project, originalItem.ItemType);

                foreach (string includeSplit in includeSplits)
                {
                    // STEP 3: If expression is "@(x)" copy specified list with its metadata, otherwise just treat as string
                    bool throwaway;

                    IList<ProjectItemInstance> itemsFromSplit = expander.ExpandSingleItemVectorExpressionIntoItems(includeSplit, itemFactory, ExpanderOptions.ExpandItems, false /* do not include null expansion results */, out throwaway, originalItem.IncludeLocation);

                    if (itemsFromSplit != null)
                    {
                        // Expression is in form "@(X)", so add these items directly.
                        foreach (ProjectItemInstance item in itemsFromSplit)
                        {
                            items.Add(item);
                        }
                    }
                    else
                    {
                        // The expression is not of the form "@(X)". Treat as string
                        string[] includeSplitFiles = EngineFileUtilities.GetFileListEscaped(Project.Directory, includeSplit);

                        foreach (string includeSplitFile in includeSplitFiles)
                        {
                            items.Add(new ProjectItemInstance(Project, originalItem.ItemType, includeSplitFile, includeSplit /* before wildcard expansion */, null, null, originalItem.Location.File));
                        }
                    }
                }

                // STEP 4: Evaluate, split, expand and subtract any Exclude
                if (originalItem.Exclude.Length > 0)
                {
                    string evaluatedExclude = expander.ExpandIntoStringLeaveEscaped(originalItem.Exclude, ExpanderOptions.ExpandAll, originalItem.ExcludeLocation);

                    if (evaluatedExclude.Length > 0)
                    {
                        IList<string> excludeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedExclude);
                        HashSet<string> excludesUnescapedForComparison = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

                        foreach (string excludeSplit in excludeSplits)
                        {
                            string[] excludeSplitFiles = EngineFileUtilities.GetFileListUnescaped(Project.Directory, excludeSplit);

                            foreach (string excludeSplitFile in excludeSplitFiles)
                            {
                                excludesUnescapedForComparison.Add(excludeSplitFile);
                            }
                        }

                        List<ProjectItemInstance> remainingItems = new List<ProjectItemInstance>();

                        for (int i = 0; i < items.Count; i++)
                        {
                            if (!excludesUnescapedForComparison.Contains(((IItem)items[i]).EvaluatedInclude))
                            {
                                remainingItems.Add(items[i]);
                            }
                        }

                        items = remainingItems;
                    }
                }
            }

            // Filter the metadata as appropriate
            if (keepMetadata != null)
            {
                foreach (var item in items)
                {
                    var metadataToRemove = item.MetadataNames.Where(name => !keepMetadata.Contains(name));
                    foreach (var metadataName in metadataToRemove)
                    {
                        item.RemoveMetadata(metadataName);
                    }
                }
            }
            else if (removeMetadata != null)
            {
                foreach (var item in items)
                {
                    var metadataToRemove = item.MetadataNames.Where(name => removeMetadata.Contains(name));
                    foreach (var metadataName in metadataToRemove)
                    {
                        item.RemoveMetadata(metadataName);
                    }
                }
            }

            return items;
        }
Пример #9
0
        public void ExpandItemVectorFunctionsItemSpecModifier()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            var expander = CreateItemFunctionExpander();

            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(project, "i");

            IList<ProjectItemInstance> itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->Metadata('Meta0')->Directory())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.AreEqual(10, itemsTrue.Count);
            Assert.AreEqual("i", itemsTrue[5].ItemType);
            Assert.AreEqual(@"firstdirectory\seconddirectory\", itemsTrue[5].EvaluatedInclude);

            itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->Metadata('Meta0')->Filename())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.AreEqual(10, itemsTrue.Count);
            Assert.AreEqual("i", itemsTrue[5].ItemType);
            Assert.AreEqual(@"file0", itemsTrue[5].EvaluatedInclude);

            itemsTrue = expander.ExpandIntoItemsLeaveEscaped("@(i->Metadata('Meta0')->Extension())", itemFactory, ExpanderOptions.ExpandItems, MockElementLocation.Instance);

            Assert.AreEqual(10, itemsTrue.Count);
            Assert.AreEqual("i", itemsTrue[5].ItemType);
            Assert.AreEqual(@".ext", itemsTrue[5].EvaluatedInclude);
        }
Пример #10
0
        /// <summary>
        /// Takes an item specification, evaluates it and expands it into a list of items
        /// </summary>
        /// <param name="originalItem">The original item data</param>
        /// <param name="expander">The expander to use.</param>
        /// <param name="keepMetadata">An <see cref="ISet{String}"/> of metadata names to keep.</param>
        /// <param name="removeMetadata">An <see cref="ISet{String}"/> of metadata names to remove.</param>
        /// <remarks>
        /// This code is very close to that which exists in the Evaluator.EvaluateItemXml method.  However, because
        /// it invokes type constructors, and those constructors take arguments of fundamentally different types, it has not
        /// been refactored.
        /// </remarks>
        /// <returns>A list of items.</returns>
        private IList <ProjectItemInstance> ExpandItemIntoItems
        (
            ProjectItemGroupTaskItemInstance originalItem,
            Expander <ProjectPropertyInstance, ProjectItemInstance> expander,
            ISet <string> keepMetadata,
            ISet <string> removeMetadata
        )
        {
            //todo this is duplicated logic with the item computation logic from evaluation (in LazyIncludeOperation.SelectItems)

            ProjectErrorUtilities.VerifyThrowInvalidProject(!(keepMetadata != null && removeMetadata != null), originalItem.KeepMetadataLocation, "KeepAndRemoveMetadataMutuallyExclusive");
            IList <ProjectItemInstance> items = new List <ProjectItemInstance>();

            // Expand properties and metadata in Include
            string evaluatedInclude = expander.ExpandIntoStringLeaveEscaped(originalItem.Include, ExpanderOptions.ExpandPropertiesAndMetadata, originalItem.IncludeLocation);

            if (evaluatedInclude.Length == 0)
            {
                return(items);
            }

            // Compute exclude fragments, without expanding wildcards
            var excludes = ImmutableList <string> .Empty.ToBuilder();

            if (originalItem.Exclude.Length > 0)
            {
                string evaluatedExclude = expander.ExpandIntoStringLeaveEscaped(originalItem.Exclude, ExpanderOptions.ExpandAll, originalItem.ExcludeLocation);

                if (evaluatedExclude.Length > 0)
                {
                    var excludeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedExclude);

                    foreach (string excludeSplit in excludeSplits)
                    {
                        excludes.Add(excludeSplit);
                    }
                }
            }

            // Split Include on any semicolons, and take each split in turn
            var includeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedInclude);
            ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(this.Project, originalItem.ItemType);

            foreach (string includeSplit in includeSplits)
            {
                // If expression is "@(x)" copy specified list with its metadata, otherwise just treat as string
                bool throwaway;

                IList <ProjectItemInstance> itemsFromSplit = expander.ExpandSingleItemVectorExpressionIntoItems(includeSplit,
                                                                                                                itemFactory,
                                                                                                                ExpanderOptions.ExpandItems,
                                                                                                                false /* do not include null expansion results */,
                                                                                                                out throwaway,
                                                                                                                originalItem.IncludeLocation);

                if (itemsFromSplit != null)
                {
                    // Expression is in form "@(X)", so add these items directly.
                    foreach (ProjectItemInstance item in itemsFromSplit)
                    {
                        items.Add(item);
                    }
                }
                else
                {
                    // The expression is not of the form "@(X)". Treat as string

                    // Pass the non wildcard expanded excludes here to fix https://github.com/Microsoft/msbuild/issues/2621
                    string[] includeSplitFiles = _engineFileUtilities.GetFileListEscaped(
                        Project.Directory,
                        includeSplit,
                        excludes);

                    foreach (string includeSplitFile in includeSplitFiles)
                    {
                        items.Add(new ProjectItemInstance(
                                      Project,
                                      originalItem.ItemType,
                                      includeSplitFile,
                                      includeSplit /* before wildcard expansion */,
                                      null,
                                      null,
                                      originalItem.Location.File));
                    }
                }
            }

            // Evaluate, split, expand and subtract any Exclude
            HashSet <string> excludesUnescapedForComparison = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (string excludeSplit in excludes)
            {
                string[] excludeSplitFiles = _engineFileUtilities.GetFileListUnescaped(Project.Directory, excludeSplit);

                foreach (string excludeSplitFile in excludeSplitFiles)
                {
                    excludesUnescapedForComparison.Add(excludeSplitFile);
                }
            }

            List <ProjectItemInstance> remainingItems = new List <ProjectItemInstance>();

            for (int i = 0; i < items.Count; i++)
            {
                if (!excludesUnescapedForComparison.Contains(((IItem)items[i]).EvaluatedInclude))
                {
                    remainingItems.Add(items[i]);
                }
            }

            items = remainingItems;

            // Filter the metadata as appropriate
            if (keepMetadata != null)
            {
                foreach (var item in items)
                {
                    var metadataToRemove = item.MetadataNames.Where(name => !keepMetadata.Contains(name));
                    foreach (var metadataName in metadataToRemove)
                    {
                        item.RemoveMetadata(metadataName);
                    }
                }
            }
            else if (removeMetadata != null)
            {
                foreach (var item in items)
                {
                    var metadataToRemove = item.MetadataNames.Where(name => removeMetadata.Contains(name));
                    foreach (var metadataName in metadataToRemove)
                    {
                        item.RemoveMetadata(metadataName);
                    }
                }
            }

            return(items);
        }
Пример #11
0
        /// <summary>
        /// Takes an item specification, evaluates it and expands it into a list of items
        /// </summary>
        /// <param name="originalItem">The original item data</param>
        /// <param name="expander">The expander to use.</param>
        /// <param name="keepMetadata">An <see cref="ISet{String}"/> of metadata names to keep.</param>
        /// <param name="removeMetadata">An <see cref="ISet{String}"/> of metadata names to remove.</param>
        /// <remarks>
        /// This code is very close to that which exists in the Evaluator.EvaluateItemXml method.  However, because
        /// it invokes type constructors, and those constructors take arguments of fundamentally different types, it has not
        /// been refactored.
        /// </remarks>
        /// <returns>A list of items.</returns>
        private IList <ProjectItemInstance> ExpandItemIntoItems
        (
            ProjectItemGroupTaskItemInstance originalItem,
            Expander <ProjectPropertyInstance, ProjectItemInstance> expander,
            ISet <string> keepMetadata,
            ISet <string> removeMetadata
        )
        {
            ProjectErrorUtilities.VerifyThrowInvalidProject(!(keepMetadata != null && removeMetadata != null), originalItem.KeepMetadataLocation, "KeepAndRemoveMetadataMutuallyExclusive");
            IList <ProjectItemInstance> items = new List <ProjectItemInstance>();

            // UNDONE: (Refactor)  This code also exists in largely the same form in Evaluator.CreateItemsFromInclude.
            // STEP 1: Expand properties and metadata in Include
            string evaluatedInclude = expander.ExpandIntoStringLeaveEscaped(originalItem.Include, ExpanderOptions.ExpandPropertiesAndMetadata, originalItem.IncludeLocation);

            // STEP 2: Split Include on any semicolons, and take each split in turn
            if (evaluatedInclude.Length > 0)
            {
                IList <string>             includeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedInclude);
                ProjectItemInstanceFactory itemFactory   = new ProjectItemInstanceFactory(this.Project, originalItem.ItemType);

                foreach (string includeSplit in includeSplits)
                {
                    // STEP 3: If expression is "@(x)" copy specified list with its metadata, otherwise just treat as string
                    bool throwaway;

                    IList <ProjectItemInstance> itemsFromSplit = expander.ExpandSingleItemVectorExpressionIntoItems(includeSplit, itemFactory, ExpanderOptions.ExpandItems, false /* do not include null expansion results */, out throwaway, originalItem.IncludeLocation);

                    if (itemsFromSplit != null)
                    {
                        // Expression is in form "@(X)", so add these items directly.
                        foreach (ProjectItemInstance item in itemsFromSplit)
                        {
                            items.Add(item);
                        }
                    }
                    else
                    {
                        // The expression is not of the form "@(X)". Treat as string
                        string[] includeSplitFiles = EngineFileUtilities.GetFileListEscaped(Project.Directory, includeSplit);

                        foreach (string includeSplitFile in includeSplitFiles)
                        {
                            items.Add(new ProjectItemInstance(Project, originalItem.ItemType, includeSplitFile, includeSplit /* before wildcard expansion */, null, null, originalItem.Location.File));
                        }
                    }
                }

                // STEP 4: Evaluate, split, expand and subtract any Exclude
                if (originalItem.Exclude.Length > 0)
                {
                    string evaluatedExclude = expander.ExpandIntoStringLeaveEscaped(originalItem.Exclude, ExpanderOptions.ExpandAll, originalItem.ExcludeLocation);

                    if (evaluatedExclude.Length > 0)
                    {
                        IList <string>   excludeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedExclude);
                        HashSet <string> excludesUnescapedForComparison = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                        foreach (string excludeSplit in excludeSplits)
                        {
                            string[] excludeSplitFiles = EngineFileUtilities.GetFileListUnescaped(Project.Directory, excludeSplit);

                            foreach (string excludeSplitFile in excludeSplitFiles)
                            {
                                excludesUnescapedForComparison.Add(excludeSplitFile);
                            }
                        }

                        List <ProjectItemInstance> remainingItems = new List <ProjectItemInstance>();

                        for (int i = 0; i < items.Count; i++)
                        {
                            if (!excludesUnescapedForComparison.Contains(((IItem)items[i]).EvaluatedInclude))
                            {
                                remainingItems.Add(items[i]);
                            }
                        }

                        items = remainingItems;
                    }
                }
            }

            // Filter the metadata as appropriate
            if (keepMetadata != null)
            {
                foreach (var item in items)
                {
                    var metadataToRemove = item.MetadataNames.Where(name => !keepMetadata.Contains(name));
                    foreach (var metadataName in metadataToRemove)
                    {
                        item.RemoveMetadata(metadataName);
                    }
                }
            }
            else if (removeMetadata != null)
            {
                foreach (var item in items)
                {
                    var metadataToRemove = item.MetadataNames.Where(name => removeMetadata.Contains(name));
                    foreach (var metadataName in metadataToRemove)
                    {
                        item.RemoveMetadata(metadataName);
                    }
                }
            }

            return(items);
        }