Пример #1
0
        void ProcessItemSpec(OperationBuilder operationBuilder, string itemSpec, ElementLocation itemSpecLocation)
        {
            //  Code corresponds to Evaluator.CreateItemsFromInclude

            // STEP 1: Expand properties in Include
            string evaluatedIncludeEscaped = _outerExpander.ExpandIntoStringLeaveEscaped(itemSpec, ExpanderOptions.ExpandProperties, itemSpecLocation);

            // STEP 2: Split Include on any semicolons, and take each split in turn
            if (evaluatedIncludeEscaped.Length > 0)
            {
                IList <string> includeSplitsEscaped = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedIncludeEscaped);

                foreach (string includeSplitEscaped in includeSplitsEscaped)
                {
                    // STEP 3: If expression is "@(x)" copy specified list with its metadata, otherwise just treat as string
                    bool isItemListExpression;
                    ProcessSingleItemVectorExpressionForInclude(includeSplitEscaped, operationBuilder, itemSpecLocation, out isItemListExpression);

                    if (!isItemListExpression)
                    {
                        // The expression is not of the form "@(X)". Treat as string

                        //  Code corresponds to EngineFileUtilities.GetFileList
                        bool containsEscapedWildcards = EscapingUtilities.ContainsEscapedWildcards(includeSplitEscaped);
                        bool containsRealWildcards    = FileMatcher.HasWildcards(includeSplitEscaped);

                        if (containsEscapedWildcards && containsRealWildcards)
                        {
                            // Umm, this makes no sense.  The item's Include has both escaped wildcards and
                            // real wildcards.  What does he want us to do?  Go to the file system and find
                            // files that literally have '*' in their filename?  Well, that's not going to
                            // happen because '*' is an illegal character to have in a filename.

                            // Just return the original string.
                            operationBuilder.Operations.Add(Tuple.Create(ItemOperationType.Value, (object)includeSplitEscaped));
                        }
                        else if (!containsEscapedWildcards && containsRealWildcards)
                        {
                            // Unescape before handing it to the filesystem.
                            string filespecUnescaped = EscapingUtilities.UnescapeAll(includeSplitEscaped);
                            operationBuilder.Operations.Add(Tuple.Create(ItemOperationType.Glob, (object)filespecUnescaped));
                        }
                        else
                        {
                            // No real wildcards means we just return the original string.  Don't even bother
                            // escaping ... it should already be escaped appropriately since it came directly
                            // from the project file
                            operationBuilder.Operations.Add(Tuple.Create(ItemOperationType.Value, (object)includeSplitEscaped));
                        }
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Expands the given unexpanded property expression using the properties in the
        /// given expander.
        /// </summary>
        private string ExpandPropertyLeaveEscaped(ToolsetPropertyDefinition property, Expander <ProjectPropertyInstance, ProjectItemInstance> expander)
        {
            try
            {
                return(expander.ExpandIntoStringLeaveEscaped(property.Value, ExpanderOptions.ExpandProperties, property.Source));
            }
            catch (InvalidProjectFileException ex)
            {
                InvalidToolsetDefinitionException.Throw(ex, "ErrorEvaluatingToolsetPropertyExpression", property.Value, property.Source.LocationString, ex.BaseMessage);
            }

            return(string.Empty);
        }
Пример #3
0
        private static IEnumerable <string> GetExpandedMetadataValuesAndConditions(ICollection <ProjectMetadataElement> metadata, Expander <P, I> expander)
        {
            // Since we're just attempting to expand properties in order to find referenced items and not expanding metadata,
            // unexpected errors may occur when evaluating property functions on unexpanded metadata. Just ignore them if that happens.
            // See: https://github.com/dotnet/msbuild/issues/3460
            const ExpanderOptions expanderOptions = ExpanderOptions.ExpandProperties | ExpanderOptions.LeavePropertiesUnexpandedOnError;

            // Expand properties here, because a property may have a value which is an item reference (ie "@(Bar)"), and
            // if so we need to add the right item reference.
            foreach (var metadatumElement in metadata)
            {
                yield return(expander.ExpandIntoStringLeaveEscaped(
                                 metadatumElement.Value,
                                 expanderOptions,
                                 metadatumElement.Location));

                yield return(expander.ExpandIntoStringLeaveEscaped(
                                 metadatumElement.Condition,
                                 expanderOptions,
                                 metadatumElement.ConditionLocation));
            }
        }
Пример #4
0
        private IncludeOperation BuildIncludeOperation(string rootDirectory, ProjectItemElement itemElement, bool conditionResult)
        {
            IncludeOperationBuilder operationBuilder = new IncludeOperationBuilder(itemElement, conditionResult);

            operationBuilder.ElementOrder    = _nextElementOrder++;
            operationBuilder.RootDirectory   = rootDirectory;
            operationBuilder.ConditionResult = conditionResult;

            // Process include
            ProcessItemSpec(itemElement.Include, itemElement.IncludeLocation, operationBuilder);

            //  Code corresponds to Evaluator.EvaluateItemElement

            // Process exclude (STEP 4: Evaluate, split, expand and subtract any Exclude)
            if (itemElement.Exclude.Length > 0)
            {
                //  Expand properties here, because a property may have a value which is an item reference (ie "@(Bar)"), and
                //  if so we need to add the right item reference
                string evaluatedExclude = _expander.ExpandIntoStringLeaveEscaped(itemElement.Exclude, ExpanderOptions.ExpandProperties, itemElement.ExcludeLocation);

                if (evaluatedExclude.Length > 0)
                {
                    IList <string> excludeSplits = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedExclude);

                    operationBuilder.Excludes.AddRange(excludeSplits);

                    foreach (var excludeSplit in excludeSplits)
                    {
                        AddItemReferences(excludeSplit, operationBuilder, itemElement.ExcludeLocation);
                    }
                }
            }

            // Process Metadata (STEP 5: Evaluate each metadata XML and apply them to each item we have so far)
            ProcessMetadataElements(itemElement, operationBuilder);

            return(new IncludeOperation(operationBuilder, this));
        }
Пример #5
0
        /// <summary>
        /// See <see cref="GetMetadataValue(string)">GetMetadataValue</see> for a more detailed explanation.
        /// Returns the escaped value of the metadatum requested.
        /// </summary>
        string IItem.GetMetadataValueEscaped(string name)
        {
            ErrorUtilities.VerifyThrowArgumentLength(name, "name");

            string value = null;

            if (_directMetadata != null)
            {
                ProjectMetadata metadatum = _directMetadata[name];
                if (metadatum != null)
                {
                    value = metadatum.EvaluatedValueEscaped;
                }
            }

            if (value == null)
            {
                value = GetBuiltInMetadataEscaped(name);
            }

            if (value == null)
            {
                ProjectMetadata metadatum = GetItemDefinitionMetadata(name);

                if (null != metadatum && Expander <ProjectProperty, ProjectItem> .ExpressionMayContainExpandableExpressions(metadatum.EvaluatedValueEscaped))
                {
                    Expander <ProjectProperty, ProjectItem> expander = new Expander <ProjectProperty, ProjectItem>(null, null, new BuiltInMetadataTable(this), FileSystems.Default);

                    value = expander.ExpandIntoStringLeaveEscaped(metadatum.EvaluatedValueEscaped, ExpanderOptions.ExpandBuiltInMetadata, metadatum.Location);
                }
                else if (null != metadatum)
                {
                    return(metadatum.EvaluatedValueEscaped);
                }
            }

            return(value ?? String.Empty);
        }
Пример #6
0
        public void PropertyFunctionDoesTaskHostExist_Error()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

                string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::DoesTaskHostExist('ASDF', 'CurrentArchitecture'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                // We should have failed before now
                Assert.True(false);
            }
           );
        }
Пример #7
0
        public void PropertyFunctionValueOrDefault()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::ValueOrDefault('', '42'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("42", result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::ValueOrDefault('42', '43'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("42", result);
        }
Пример #8
0
        public void PropertyFunctionStaticMethodGetCultureInfo()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.Globalization.CultureInfo]::GetCultureInfo(`en-US`).ToString())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(System.Globalization.CultureInfo.GetCultureInfo("en-US").ToString(), result);
        }
Пример #9
0
        public void PropertyFunctionStaticMethodEnumArgument()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.Environment]::GetFolderPath(SpecialFolder.System))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(System.Environment.GetFolderPath(Environment.SpecialFolder.System), result);
        }
Пример #10
0
        public void PropertyFunctionStaticMethodRegex1()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("File", @"foo\file.txt"));

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

            // Support enum combines as Enum.Parse expects them
            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.Text.RegularExpressions.Regex]::IsMatch(`-42`, `^-?\d+(\.\d{2})?$`, `RegexOptions.IgnoreCase,RegexOptions.Singleline`))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(@"True", result);

            // We support the C# style enum combining syntax too
            result = expander.ExpandIntoStringLeaveEscaped(@"$([System.Text.RegularExpressions.Regex]::IsMatch(`-42`, `^-?\d+(\.\d{2})?$`, System.Text.RegularExpressions.RegexOptions.IgnoreCase|RegexOptions.Singleline))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(@"True", result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([System.Text.RegularExpressions.Regex]::IsMatch(`100 GBP`, `^-?\d+(\.\d{2})?$`))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(@"False", result);
        }
Пример #11
0
        public void PropertyFunctionGetRegistryValueFromView2()
        {
            try
            {
                PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
                pg.Set(ProjectPropertyInstance.Create("SomeProperty", "Value"));

                Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg);
                RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\MSBuild_test");

                key.SetValue(String.Empty, "%TEMP%", RegistryValueKind.ExpandString);
                string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::GetRegistryValueFromView('HKEY_CURRENT_USER\Software\Microsoft\MSBuild_test', null, null, Microsoft.Win32.RegistryView.Default))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                Assert.Equal(Environment.GetEnvironmentVariable("TEMP"), result);
            }
            finally
            {
                Registry.CurrentUser.DeleteSubKey(@"Software\Microsoft\MSBuild_test");
            }
        }        /// <summary>
Пример #12
0
            protected void DecorateItemsWithMetadata(ImmutableList <I> items, ImmutableList <ProjectMetadataElement> metadata)
            {
                if (metadata.Count > 0)
                {
                    ////////////////////////////////////////////////////
                    // UNDONE: Implement batching here.
                    //
                    // We want to allow built-in metadata in metadata values here.
                    // For example, so that an Idl file can specify that its Tlb output should be named %(Filename).tlb.
                    //
                    // In other words, we want batching. However, we won't need to go to the trouble of using the regular batching code!
                    // That's because that code is all about grouping into buckets of similar items. In this context, we're not
                    // invoking a task, and it's fine to process each item individually, which will always give the correct results.
                    //
                    // For the CTP, to make the minimal change, we will not do this quite correctly.
                    //
                    // We will do this:
                    // -- check whether any metadata values or their conditions contain any bare built-in metadata expressions,
                    //    or whether they contain any custom metadata && the Include involved an @(itemlist) expression.
                    // -- if either case is found, we go ahead and evaluate all the metadata separately for each item.
                    // -- otherwise we can do the old thing (evaluating all metadata once then applying to all items)
                    //
                    // This algorithm gives the correct results except when:
                    // -- batchable expressions exist on the include, exclude, or condition on the item element itself
                    //
                    // It means that 99% of cases still go through the old code, which is best for the CTP.
                    // When we ultimately implement this correctly, we should make sure we optimize for the case of very many items
                    // and little metadata, none of which varies between items.

                    // Do not expand properties as they have been already expanded by the lazy evaluator upon item operation construction.
                    // Prior to lazy evaluation ExpanderOptions.ExpandAll was used.
                    const ExpanderOptions metadataExpansionOptions = ExpanderOptions.ExpandAll;

                    List <string> values = new List <string>(metadata.Count * 2);

                    foreach (var metadataElement in metadata)
                    {
                        values.Add(metadataElement.Value);
                        values.Add(metadataElement.Condition);
                    }

                    ItemsAndMetadataPair itemsAndMetadataFound = ExpressionShredder.GetReferencedItemNamesAndMetadata(values);

                    bool needToProcessItemsIndividually = false;

                    if (itemsAndMetadataFound.Metadata != null && itemsAndMetadataFound.Metadata.Values.Count > 0)
                    {
                        // If there is bare metadata of any kind, and the Include involved an item list, we should
                        // run items individually, as even non-built-in metadata might differ between items

                        if (_referencedItemLists.Count >= 0)
                        {
                            needToProcessItemsIndividually = true;
                        }
                        else
                        {
                            // If there is bare built-in metadata, we must always run items individually, as that almost
                            // always differs between items.

                            // UNDONE: When batching is implemented for real, we need to make sure that
                            // item definition metadata is included in all metadata operations during evaluation
                            if (itemsAndMetadataFound.Metadata.Values.Count > 0)
                            {
                                needToProcessItemsIndividually = true;
                            }
                        }
                    }

                    if (needToProcessItemsIndividually)
                    {
                        foreach (I item in items)
                        {
                            _expander.Metadata = item;

                            foreach (var metadataElement in metadata)
                            {
#if FEATURE_MSBUILD_DEBUGGER
                                //if (DebuggerManager.DebuggingEnabled)
                                //{
                                //    DebuggerManager.PulseState(metadataElementElement.Location, _itemPassLocals);
                                //}
#endif

                                if (!EvaluateCondition(metadataElement.Condition, metadataElement, metadataExpansionOptions, ParserOptions.AllowAll, _expander, _lazyEvaluator))
                                {
                                    continue;
                                }

                                string evaluatedValue = _expander.ExpandIntoStringLeaveEscaped(metadataElement.Value, metadataExpansionOptions, metadataElement.Location);

                                item.SetMetadata(metadataElement, FileUtilities.MaybeAdjustFilePath(evaluatedValue, metadataElement.ContainingProject.DirectoryPath));
                            }
                        }

                        // End of legal area for metadata expressions.
                        _expander.Metadata = null;
                    }

                    // End of pseudo batching
                    ////////////////////////////////////////////////////
                    // Start of old code
                    else
                    {
                        // Metadata expressions are allowed here.
                        // Temporarily gather and expand these in a table so they can reference other metadata elements above.
                        EvaluatorMetadataTable metadataTable = new EvaluatorMetadataTable(_itemType);
                        _expander.Metadata = metadataTable;

                        // Also keep a list of everything so we can get the predecessor objects correct.
                        List <Pair <ProjectMetadataElement, string> > metadataList = new List <Pair <ProjectMetadataElement, string> >(metadata.Count);

                        foreach (var metadataElement in metadata)
                        {
                            // Because of the checking above, it should be safe to expand metadata in conditions; the condition
                            // will be true for either all the items or none
                            if (!EvaluateCondition(metadataElement.Condition, metadataElement, metadataExpansionOptions, ParserOptions.AllowAll, _expander, _lazyEvaluator))
                            {
                                continue;
                            }

#if FEATURE_MSBUILD_DEBUGGER
                            //if (DebuggerManager.DebuggingEnabled)
                            //{
                            //    DebuggerManager.PulseState(metadataElementElement.Location, _itemPassLocals);
                            //}
#endif

                            string evaluatedValue = _expander.ExpandIntoStringLeaveEscaped(metadataElement.Value, metadataExpansionOptions, metadataElement.Location);
                            evaluatedValue = FileUtilities.MaybeAdjustFilePath(evaluatedValue, metadataElement.ContainingProject.DirectoryPath);

                            metadataTable.SetValue(metadataElement, evaluatedValue);
                            metadataList.Add(new Pair <ProjectMetadataElement, string>(metadataElement, evaluatedValue));
                        }

                        // Apply those metadata to each item
                        // Note that several items could share the same metadata objects

                        // Set all the items at once to make a potential copy-on-write optimization possible.
                        // This is valuable in the case where one item element evaluates to
                        // many items (either by semicolon or wildcards)
                        // and that item also has the same piece/s of metadata for each item.
                        _itemFactory.SetMetadata(metadataList, items);

                        // End of legal area for metadata expressions.
                        _expander.Metadata = null;
                    }
                }
            }
Пример #13
0
        private List <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");
            List <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/dotnet/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);
        }
Пример #14
0
        private List <ItemSpecFragment> BuildItemFragments(IElementLocation itemSpecLocation, string projectDirectory, bool expandProperties)
        {
            // Code corresponds to Evaluator.CreateItemsFromInclude
            var evaluatedItemspecEscaped = ItemSpecString;

            if (string.IsNullOrEmpty(evaluatedItemspecEscaped))
            {
                return(new List <ItemSpecFragment>());
            }

            // STEP 1: Expand properties in Include
            if (expandProperties)
            {
                evaluatedItemspecEscaped = Expander.ExpandIntoStringLeaveEscaped(
                    ItemSpecString,
                    ExpanderOptions.ExpandProperties,
                    itemSpecLocation);
            }

            var semicolonCount = 0;

            foreach (var c in evaluatedItemspecEscaped)
            {
                if (c == ';')
                {
                    semicolonCount++;
                }
            }

            // estimate the number of fragments with the number of semicolons. This is will overestimate in case of transforms with semicolons, but won't underestimate.
            var fragments = new List <ItemSpecFragment>(semicolonCount + 1);

            // STEP 2: Split Include on any semicolons, and take each split in turn
            if (evaluatedItemspecEscaped.Length > 0)
            {
                var splitsEscaped = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedItemspecEscaped);

                foreach (var splitEscaped in splitsEscaped)
                {
                    // STEP 3: If expression is "@(x)" copy specified list with its metadata, otherwise just treat as string
                    var itemReferenceFragment = ProcessItemExpression(
                        splitEscaped,
                        itemSpecLocation,
                        projectDirectory,
                        out var isItemListExpression);

                    if (isItemListExpression)
                    {
                        fragments.Add(itemReferenceFragment);
                    }
                    else
                    {
                        // The expression is not of the form "@(X)". Treat as string

                        // Code corresponds to EngineFileUtilities.GetFileList
                        if (!FileMatcher.HasWildcards(splitEscaped))
                        {
                            // No real wildcards means we just return the original string.  Don't even bother
                            // escaping ... it should already be escaped appropriately since it came directly
                            // from the project file

                            fragments.Add(new ValueFragment(splitEscaped, projectDirectory));
                        }
                        else if (EscapingUtilities.ContainsEscapedWildcards(splitEscaped))
                        {
                            // '*' is an illegal character to have in a filename.
                            // todo: file-system assumption on legal path characters: https://github.com/dotnet/msbuild/issues/781
                            // Just return the original string.
                            fragments.Add(new ValueFragment(splitEscaped, projectDirectory));
                        }
                        else
                        {
                            // Unescape before handing it to the filesystem.
                            var filespecUnescaped = EscapingUtilities.UnescapeAll(splitEscaped);

                            fragments.Add(new GlobFragment(filespecUnescaped, projectDirectory));
                        }
                    }
                }
            }

            return(fragments);
        }
Пример #15
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);
        }
Пример #16
0
        public void PropertyFunctionDoesTaskHostExist_NonexistentTaskHost()
        {
            string taskHostName = Environment.GetEnvironmentVariable("MSBUILDTASKHOST_EXE_NAME");
            try
            {
                Environment.SetEnvironmentVariable("MSBUILDTASKHOST_EXE_NAME", "asdfghjkl.exe");
                NodeProviderOutOfProcTaskHost.ClearCachedTaskHostPaths();

                PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

                string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::DoesTaskHostExist('CLR2', 'CurrentArchitecture'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                // CLR has been forced to pretend not to exist, whether it actually does or not
                Assert.True(String.Equals("false", result, StringComparison.OrdinalIgnoreCase));
            }
            finally
            {
                Environment.SetEnvironmentVariable("MSBUILDTASKHOST_EXE_NAME", taskHostName);
                NodeProviderOutOfProcTaskHost.ClearCachedTaskHostPaths();
            }
        }
Пример #17
0
        public void PropertyFunctionStaticMethodIntrinsicMaths()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Add(39.9, 2.1))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((39.9 + 2.1).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Add(40, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((40 + 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Subtract(44, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((44 - 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Subtract(42.9, 0.9))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((42.9 - 0.9).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Multiply(21, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((21 * 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Multiply(84.0, 0.5))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((84.0 * 0.5).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Divide(84, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((84 / 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Divide(84.4, 2.0))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((84.4 / 2.0).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Modulo(85, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((85 % 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Modulo(2345.5, 43))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((2345.5 % 43).ToString(), result);

            // test for overflow wrapping
            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Add(9223372036854775807, 20))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            double expectedResult = 9223372036854775807D + 20D;
            Assert.Equal(expectedResult.ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseOr(40, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((40 | 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseAnd(42, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((42 & 2).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseXor(213, 255))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((213 ^ 255).ToString(), result);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseNot(-43))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((~-43).ToString(), result);
        }
Пример #18
0
        public void PropertyFunctionGenericListReturn()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped("$([MSBuild]::__GetListTest())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("A;B;C;D", result);
        }
Пример #19
0
        public void Medley()
        {
            // Make absolutely sure that the static method cache hasn't been polluted by the other tests.  
            AvailableStaticMethods.Reset_ForUnitTestsOnly();

            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("File", @"foo\file.txt"));

            pg.Set(ProjectPropertyInstance.Create("a", "no"));
            pg.Set(ProjectPropertyInstance.Create("b", "true"));
            pg.Set(ProjectPropertyInstance.Create("c", "1"));
            pg.Set(ProjectPropertyInstance.Create("position", "4"));
            pg.Set(ProjectPropertyInstance.Create("d", "xxx"));
            pg.Set(ProjectPropertyInstance.Create("e", "xxx"));
            pg.Set(ProjectPropertyInstance.Create("and", "and"));
            pg.Set(ProjectPropertyInstance.Create("a_semi_b", "a;b"));
            pg.Set(ProjectPropertyInstance.Create("a_apos_b", "a'b"));
            pg.Set(ProjectPropertyInstance.Create("foo_apos_foo", "foo'foo"));
            pg.Set(ProjectPropertyInstance.Create("a_escapedsemi_b", "a%3bb"));
            pg.Set(ProjectPropertyInstance.Create("a_escapedapos_b", "a%27b"));
            pg.Set(ProjectPropertyInstance.Create("has_trailing_slash", @"foo\"));
            pg.Set(ProjectPropertyInstance.Create("emptystring", @""));
            pg.Set(ProjectPropertyInstance.Create("space", @" "));
            pg.Set(ProjectPropertyInstance.Create("listofthings", @"a;b;c;d;e;f;g;h;i;j;k;l"));
            pg.Set(ProjectPropertyInstance.Create("input", @"EXPORT a"));
            pg.Set(ProjectPropertyInstance.Create("propertycontainingnullasastring", @"null"));

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

            string[,] validTests = {
                {"$(input.ToString()[1])", "X"},
                {"$(input[1])", "X"},
                {"$(listofthings.Split(';')[$(position)])","e"},
                {@"$([System.Text.RegularExpressions.Regex]::Match($(Input), `EXPORT\s+(.+)`).Groups[1].Value)","a"},
                {"$([MSBuild]::Add(1,2).CompareTo(3))", "0"},
                {"$([MSBuild]::Add(1,2).CompareTo(3))", "0"},
                {"$([MSBuild]::Add(1,2).CompareTo(3.0))", "0"},
                {"$([MSBuild]::Add(1,2).CompareTo('3'))", "0"},
                {"$([MSBuild]::Add(1,2).CompareTo(3.1))", "-1"},
                {"$([MSBuild]::Add(1,2).CompareTo(2))", "1"},
                {"$([MSBuild]::Add(1,2).Equals(3))", "True"},
                {"$([MSBuild]::Add(1,2).Equals(3.0))", "True"},
                {"$([MSBuild]::Add(1,2).Equals('3'))", "True"},
                {"$([MSBuild]::Add(1,2).Equals(3.1))", "False"},
                {"$(a.Insert(0,'%28'))", "%28no"},
                {"$(a.Insert(0,'\"'))", "\"no"},
                {"$(a.Insert(0,'(('))", "%28%28no"},
                {"$(a.Insert(0,'))'))", "%29%29no"},
                {"A$(Reg:A)A", "AA"},
                {"A$(Reg:AA)", "A"},
                {"$(Reg:AA)", ""},
                {"$(Reg:AAAA)", ""},
                {"$(Reg:AAA)", ""},
                {"$([MSBuild]::Add(2,$([System.Convert]::ToInt64('28', 16))))", "42"},
                {"$([MSBuild]::Add(2,$([System.Convert]::ToInt64('28', $([System.Convert]::ToInt32(16))))))", "42"},
                {"$(e.Length.ToString())", "3"},
                {"$(e.get_Length().ToString())", "3"},
                {"$(emptystring.Length)", "0" },
                {"$(space.Length)", "1" },
                {"$([System.TimeSpan]::Equals(null, null))", "True"}, // constant, unquoted null is a special value
                {"$([MSBuild]::Add(40,null))", "40"},
                {"$([MSBuild]::Add( 40 , null ))", "40"},
                {"$([MSBuild]::Add(null,40))", "40"},
                {"$([MSBuild]::Escape(';'))", "%3b"},
                {"$([MSBuild]::UnEscape('%3b'))", ";"},
                {"$(e.Substring($(e.Length)))", ""},
                {"$([System.Int32]::MaxValue)", System.Int32.MaxValue.ToString()},
                {"x$()", "x"},
                {"A$(Reg:A)A", "AA"},
                {"A$(Reg:AA)", "A"},
                {"$(Reg:AA)", ""},
                {"$(Reg:AAAA)", ""},
                {"$(Reg:AAA)", ""}
                                   };

            string[] errorTests = {
            "$(input[)",
            "$(input.ToString()])",
            "$(input.ToString()[)",
            "$(input.ToString()[12])",
            "$(input[])",
            "$(input[-1])",
            "$(listofthings.Split(';')[)",
            "$(listofthings.Split(';')['goo'])",
            "$(listofthings.Split(';')[])",
            "$(listofthings.Split(';')[-1])",
            "$([]::())",
                                                      @"
 
$(
 
$(
 
[System.IO]::Path.GetDirectory('c:\foo\bar\baz.txt')
 
).Substring(
 
'$([System.IO]::Path.GetPathRoot(
 
'$([System.IO]::Path.GetDirectory('c:\foo\bar\baz.txt'))'
 
).Length)'
 
 
 
)
 
",
                "$([Microsoft.VisualBasic.FileIO.FileSystem]::CurrentDirectory)", // not allowed
                "$(e.Length..ToString())",
                "$(SomeStuff.get_Length(null))",
                "$(SomeStuff.Substring((1)))",
                "$(b.Substring(-10, $(c)))",
                "$(b.Substring(-10, $(emptystring)))",
                "$(b.Substring(-10, $(space)))",
                "$([MSBuild]::Add.Sub(null,40))",
                "$([MSBuild]::Add( ,40))", // empty parameter is empty string
                "$([MSBuild]::Add('',40))", // empty quoted parameter is empty string
                "$([MSBuild]::Add(40,,,))",
                "$([MSBuild]::Add(40, ,,))",
                "$([MSBuild]::Add(40,)",
                "$([MSBuild]::Add(40,X)",
                "$([MSBuild]::Add(40,",
                "$([MSBuild]::Add(40",
                "$([MSBuild]::Add(,))", // gives "Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true."
                "$([System.TimeSpan]::Equals(,))", // empty parameter is interpreted as empty string
                "$([System.TimeSpan]::Equals($(space),$(emptystring)))", // empty parameter is interpreted as empty string
                "$([System.TimeSpan]::Equals($(emptystring),$(emptystring)))", // empty parameter is interpreted as empty string
                "$([MSBuild]::Add($(PropertyContainingNullAsAString),40))", // a property containing the word null is a string "null"
                "$([MSBuild]::Add('null',40))", // the word null is a string "null"
                "$(SomeStuff.Substring(-10))",
                "$(.Length)",
                "$(.Substring(1))",
                "$(.get_Length())",
                "$(e.)",
                "$(e..)",
                "$(e..Length)",
                "$(e$(d).Length)",
                "$($(d).Length)",
                "$(e`.Length)",
                "$([System.IO.Path]Combine::Combine(`a`,`b`))",
                "$([System.IO.Path]::Combine((`a`,`b`))",
                "$([System.IO.Path]::Combine(`|`,`b`))",
                "$([System.IO.Path]Combine(::Combine(`a`,`b`))",
                "$([System.IO.Path]Combine(`::Combine(`a`,`b`)`, `b`)`)",
                "$([System.IO.Path]::`Combine(`a`, `b`)`)",
                "$([System.IO.Path]::(`Combine(`a`, `b`)`))",
                "$([System.DateTime]foofoo::Now)",
                "$([System.DateTime].Now)",
                "$([].Now)",
                "$([ ].Now)",
                "$([ .Now)",
                "$([])",
                "$([ )",
                "$([ ])",
                "$([System.Diagnostics.Process]::Start(`NOTEPAD.EXE`))",
                "$([[]]::Start(`NOTEPAD.EXE`))",
                "$([(::Start(`NOTEPAD.EXE`))",
                "$([Goop]::Start(`NOTEPAD.EXE`))",
                "$([System.Threading.Thread]::CurrentThread)",
                "$",
                "$(",
                "$((",
                "@",
                "@(",
                "@()",
                "%",
                "%(",
                "%()",
                "exists",
                "exists(",
                "exists()",
                "exists( )",
                "exists(,)",
                "@(x->'",
                "@(x->''",
                "@(x-",
                "@(x->'x','",
                "@(x->'x',''",
                "@(x->'x','')",
                "-1>x",
                "\n",
                "\t",
                "+-1",
                "$(SomeStuff.)",
                "$(SomeStuff.!)",
                "$(SomeStuff.`)",
                "$(SomeStuff.GetType)",
                "$(goop.baz`)",
                "$(SomeStuff.Substring(HELLO!))",
                "$(SomeStuff.ToLowerInvariant()_goop)",
                "$(SomeStuff($(System.DateTime.Now)))",
                "$(System.Foo.Bar.Lgg)",
                "$(SomeStuff.Lgg)",
                "$(SomeStuff($(Value)))",
                "$(e.$(e.Length))",
                "$(e.Substring($(e.Substring(,)))",
                "$(e.Substring($(e.Substring(a)))",
                "$(e.Substring($([System.IO.Path]::Combine(`a`, `b`))))",
                "$([]::())",
                "$((((",
                "$(Registry:X)",
                "$($())",
                "$",
                "()"
            };

            string result;
            for (int i = 0; i < validTests.GetLength(0); i++)
            {
                result = expander.ExpandIntoStringLeaveEscaped(validTests[i, 0], ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                if (!String.Equals(result, validTests[i, 1]))
                {
                    string message = "FAILURE: " + validTests[i, 0] + " expanded to '" + result + "' instead of '" + validTests[i, 1] + "'";
                    Console.WriteLine(message);
                    Assert.True(false, message);
                }
                else
                {
                    Console.WriteLine(validTests[i, 0] + " expanded to '" + result + "'");
                }
            }

            for (int i = 0; i < errorTests.GetLength(0); i++)
            {
                // If an expression is invalid,
                //      - Expansion may throw InvalidProjectFileException, or
                //      - return the original unexpanded expression
                bool success = true;
                bool caughtException = false;
                result = String.Empty;
                try
                {
                    result = expander.ExpandIntoStringLeaveEscaped(errorTests[i], ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
                    if (String.Compare(result, errorTests[i]) == 0)
                    {
                        Console.WriteLine(errorTests[i] + " did not expand.");
                        success = false;
                    }
                }
                catch (InvalidProjectFileException ex)
                {
                    Console.WriteLine(errorTests[i] + " caused '" + ex.Message + "'");
                    caughtException = true;
                }
                Assert.True(
                        (success == false || caughtException == true),
                        "FAILURE: Expected '" + errorTests[i] + "' to not parse or not be evaluated but it evaluated to '" + result + "'"
                    );
            }
        }
Пример #20
0
        public void PropertyFunctionDictionaryReturn()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped("$([System.Environment]::GetEnvironmentVariables())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ToUpperInvariant();
            string expected = ("OS=" + Environment.GetEnvironmentVariable("OS")).ToUpperInvariant();


            Assert.True(result.Contains(expected));
        }
Пример #21
0
        public void PropertyFunctionStaticMethodNested()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("File", @"foo\file.txt"));

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.IO.Path]::Combine(`c:\`, $([System.IO.Path]::Combine(`foo`,`file.txt`))))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(@"c:\foo\file.txt", result);
        }
Пример #22
0
        public void PropertyFunctionArrayReturnManualSplitter()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("List", "A-B-C-D"));
            pg.Set(ProjectPropertyInstance.Create("Splitter", "-"));

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

            string result = expander.ExpandIntoStringLeaveEscaped("$(List.Split($(Splitter.ToCharArray())))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("A;B;C;D", result);
        }
Пример #23
0
        public void PropertyFunctionStaticMethodChained()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

            Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg);
            string dateTime = "'" + _dateToParse + "'";
            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.DateTime]::Parse(" + dateTime + ").ToString(`yyyy/MM/dd HH:mm:ss`))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(DateTime.Parse(_dateToParse).ToString("yyyy/MM/dd HH:mm:ss"), result);
        }
Пример #24
0
        public void PropertyFunctionInvalid7()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
                pg.Set(ProjectPropertyInstance.Create("SomeStuff", "This IS SOME STUff"));

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

                string result = expander.ExpandIntoStringLeaveEscaped("[$(SomeStuff.Substring(-10))]", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
            }
           );
        }
Пример #25
0
        public void PropertyFunctionStaticMethodDirectoryNameOfFileAbove()
        {
            string tempPath = Path.GetTempPath();
            string tempFile = Path.GetFileName(FileUtilities.GetTemporaryFile());

            try
            {
                string directoryStart = Path.Combine(tempPath, "one\\two\\three\\four\\five");

                PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
                pg.Set(ProjectPropertyInstance.Create("StartingDirectory", directoryStart));
                pg.Set(ProjectPropertyInstance.Create("FileToFind", tempFile));

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

                string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::GetDirectoryNameOfFileAbove($(StartingDirectory), $(FileToFind)))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                Assert.Equal(Microsoft.Build.Shared.FileUtilities.EnsureTrailingSlash(tempPath), Microsoft.Build.Shared.FileUtilities.EnsureTrailingSlash(result));

                result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::GetDirectoryNameOfFileAbove($(StartingDirectory), Hobbits))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                Assert.Equal(String.Empty, result);
            }
            finally
            {
                File.Delete(tempFile);
            }
        }
Пример #26
0
        public void PropertyFunctionInvalid8()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

                string result = expander.ExpandIntoStringLeaveEscaped("$(([System.DateTime]::Now).ToString(\"MM.dd.yyyy\"))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
            }
           );
        }
Пример #27
0
        public void PropertyFunctionStaticMethodArithmeticAddDouble()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::Add(39.9, 2.1))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal((39.9 + 2.1).ToString(), result);
        }
Пример #28
0
        public void PropertyFunctionInvalidNoMetadataFunctions()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped("[%(LowerLetterList.Identity.ToUpper())]", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("[%(LowerLetterList.Identity.ToUpper())]", result);
        }
Пример #29
0
        public void PropertyFunctionValueOrDefaultFromEnvironment()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

            pg["BonkersTargetsPath"] = ProjectPropertyInstance.Create("BonkersTargetsPath", "Bonkers");

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::ValueOrDefault('$(BonkersTargetsPath)', '42'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("Bonkers", result);

            pg["BonkersTargetsPath"] = ProjectPropertyInstance.Create("BonkersTargetsPath", String.Empty);

            result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::ValueOrDefault('$(BonkersTargetsPath)', '43'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("43", result);
        }
Пример #30
0
        public void PropertyFunctionNoCollisionsOnType()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("System", "The System Namespace"));

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

            string result = expander.ExpandIntoStringLeaveEscaped("$(System)", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal("The System Namespace", result);
        }
Пример #31
0
        public void PropertyFunctionDoesTaskHostExist_Evaluated()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

            pg["Runtime"] = ProjectPropertyInstance.Create("Runtime", "CurrentRuntime");
            pg["Architecture"] = ProjectPropertyInstance.Create("Architecture", "CurrentArchitecture");

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::DoesTaskHostExist('$(Runtime)', '$(Architecture)'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            // This is the current, so it had better be true!
            Assert.True(String.Equals("true", result, StringComparison.OrdinalIgnoreCase));
        }
Пример #32
0
        public void PropertyFunctionStaticMethodMakeRelative()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("ParentPath", @"c:\abc\def"));
            pg.Set(ProjectPropertyInstance.Create("FilePath", @"c:\abc\def\foo.cpp"));

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::MakeRelative($(ParentPath), `$(FilePath)`))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(@"foo.cpp", result);
        }
Пример #33
0
        public void PropertyFunctionStaticMethodFileAttributes()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string tempFile = FileUtilities.GetTemporaryFile();
            try
            {
                File.SetAttributes(tempFile, FileAttributes.ReadOnly | FileAttributes.Archive);

                string result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseAnd(32,$([System.IO.File]::GetAttributes(" + tempFile + "))))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                Assert.Equal("32", result);
            }
            finally
            {
                File.SetAttributes(tempFile, FileAttributes.Normal);
                File.Delete(tempFile);
            }
        }
Пример #34
0
        public void PropertyFunctionConstructor2()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("ver1", @"1.2.3.4"));
            pg.Set(ProjectPropertyInstance.Create("ver2", @"2.2.3.4"));

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.Version]::new($(ver1)).CompareTo($([System.Version]::new($(ver2)))))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(@"-1", result);
        }
Пример #35
0
        public void PropertySimpleSpaced()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            pg.Set(ProjectPropertyInstance.Create("SomeStuff", "This IS SOME STUff"));

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$( SomeStuff )", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(String.Empty, result);
        }
Пример #36
0
        public void PropertyStaticFunctionAllEnabled()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string env = Environment.GetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS");

            try
            {
                Environment.SetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS", "1");

                string result = expander.ExpandIntoStringLeaveEscaped("$([Microsoft.VisualBasic.FileIO.FileSystem]::CurrentDirectory)", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

                Assert.Equal(0, String.Compare(Directory.GetCurrentDirectory(), result, StringComparison.OrdinalIgnoreCase));
            }
            finally
            {
                Environment.SetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS", env);
                AvailableStaticMethods.Reset_ForUnitTestsOnly();
            }
        }
Пример #37
0
        public void PropertyFunctionConsumingItemMetadata()
        {
            ProjectInstance project = ProjectHelpers.CreateEmptyProjectInstance();
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();
            Dictionary<string, string> itemMetadataTable = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            itemMetadataTable["Compile.Identity"] = "fOo.Cs";
            StringMetadataTable itemMetadata = new StringMetadataTable(itemMetadataTable);

            List<ProjectItemInstance> ig = new List<ProjectItemInstance>();
            pg.Set(ProjectPropertyInstance.Create("SomePath", @"c:\some\path"));
            ig.Add(new ProjectItemInstance(project, "Compile", "fOo.Cs", project.FullPath));

            ItemDictionary<ProjectItemInstance> itemsByType = new ItemDictionary<ProjectItemInstance>();
            itemsByType.ImportItems(ig);

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

            string result = expander.ExpandIntoStringLeaveEscaped(@"$([System.IO.Path]::Combine($(SomePath),%(Compile.Identity)))", ExpanderOptions.ExpandAll, MockElementLocation.Instance);

            Assert.Equal(@"c:\some\path\fOo.Cs", result);
        }
Пример #38
0
        public void PropertyStaticFunctionUsingNamespaceNotFound()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string env = Environment.GetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS");

            try
            {
                Environment.SetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS", "1");

                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([Microsoft.FOO.FileIO.FileSystem]::CurrentDirectory)", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([Foo.Baz]::new())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([Foo]::new())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([Foo.]::new())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([.Foo]::new())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([.]::new())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
                Assert.Throws<InvalidProjectFileException>(() => expander.ExpandIntoStringLeaveEscaped("$([]::new())", ExpanderOptions.ExpandProperties, MockElementLocation.Instance));
            }
            finally
            {
                Environment.SetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS", env);
                AvailableStaticMethods.Reset_ForUnitTestsOnly();
            }
        }
Пример #39
0
        private IEnumerable <ItemFragment> BuildItemFragments(IElementLocation itemSpecLocation, bool expandProperties)
        {
            var builder = ImmutableList.CreateBuilder <ItemFragment>();

            //  Code corresponds to Evaluator.CreateItemsFromInclude
            var evaluatedItemspecEscaped = ItemSpecString;

            if (string.IsNullOrEmpty(evaluatedItemspecEscaped))
            {
                return(builder.ToImmutable());
            }

            // STEP 1: Expand properties in Include
            if (expandProperties)
            {
                evaluatedItemspecEscaped = Expander.ExpandIntoStringLeaveEscaped(ItemSpecString, ExpanderOptions.ExpandProperties, itemSpecLocation);
            }

            // STEP 2: Split Include on any semicolons, and take each split in turn
            if (evaluatedItemspecEscaped.Length > 0)
            {
                var splitsEscaped = ExpressionShredder.SplitSemiColonSeparatedList(evaluatedItemspecEscaped);

                foreach (var splitEscaped in splitsEscaped)
                {
                    // STEP 3: If expression is "@(x)" copy specified list with its metadata, otherwise just treat as string
                    bool isItemListExpression;
                    var  itemReferenceFragment = ProcessItemExpression(splitEscaped, itemSpecLocation, out isItemListExpression);

                    if (isItemListExpression)
                    {
                        builder.Add(itemReferenceFragment);
                    }
                    else
                    {
                        // The expression is not of the form "@(X)". Treat as string

                        //  Code corresponds to EngineFileUtilities.GetFileList
                        var containsEscapedWildcards = EscapingUtilities.ContainsEscapedWildcards(splitEscaped);
                        var containsRealWildcards    = FileMatcher.HasWildcards(splitEscaped);

                        // '*' is an illegal character to have in a filename.
                        // todo file-system assumption on legal path characters: https://github.com/Microsoft/msbuild/issues/781
                        if (containsEscapedWildcards && containsRealWildcards)
                        {
                            // Just return the original string.
                            builder.Add(new ValueFragment(splitEscaped, itemSpecLocation.File));
                        }
                        else if (!containsEscapedWildcards && containsRealWildcards)
                        {
                            // Unescape before handing it to the filesystem.
                            var filespecUnescaped = EscapingUtilities.UnescapeAll(splitEscaped);

                            builder.Add(new GlobFragment(filespecUnescaped, itemSpecLocation.File));
                        }
                        else
                        {
                            // No real wildcards means we just return the original string.  Don't even bother
                            // escaping ... it should already be escaped appropriately since it came directly
                            // from the project file

                            builder.Add(new ValueFragment(splitEscaped, itemSpecLocation.File));
                        }
                    }
                }
            }

            return(builder.ToImmutable());
        }
Пример #40
0
        public void PropertyFunctionStaticMethodQuoted4()
        {
            PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

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

            string result = expander.ExpandIntoStringLeaveEscaped("$([System.DateTime]::Now.ToString(\"MM.dd.yyyy\"))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

            Assert.Equal(DateTime.Now.ToString("MM.dd.yyyy"), result);
        }