Esempio n. 1
0
        /// <summary>
        /// Initialize the factory from the task registry
        /// </summary>
        internal LoadedType InitializeFactory
        (
            AssemblyLoadInfo loadInfo,
            string taskName,
            IDictionary <string, TaskPropertyInfo> taskParameters,
            string taskElementContents,
            IDictionary <string, string> taskFactoryIdentityParameters,
            bool taskHostFactoryExplicitlyRequested,
            TargetLoggingContext targetLoggingContext,
            ElementLocation elementLocation,
            string taskProjectFile
        )
        {
            ErrorUtilities.VerifyThrowArgumentNull(loadInfo, "loadInfo");
            VerifyThrowIdentityParametersValid(taskFactoryIdentityParameters, elementLocation, taskName, "Runtime", "Architecture");

            if (taskFactoryIdentityParameters != null)
            {
                _factoryIdentityParameters = new Dictionary <string, string>(taskFactoryIdentityParameters, StringComparer.OrdinalIgnoreCase);
            }

            _taskHostFactoryExplicitlyRequested = taskHostFactoryExplicitlyRequested;

            try
            {
                ErrorUtilities.VerifyThrowArgumentLength(taskName, "taskName");
                _taskName   = taskName;
                _loadedType = _typeLoader.Load(taskName, loadInfo);
                ProjectErrorUtilities.VerifyThrowInvalidProject(_loadedType != null, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, String.Empty);
            }
            catch (TargetInvocationException e)
            {
                // Exception thrown by the called code itself
                // Log the stack, so the task vendor can fix their code
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, Environment.NewLine + e.InnerException.ToString());
            }
            catch (ReflectionTypeLoadException e)
            {
                // ReflectionTypeLoadException.LoaderExceptions may contain nulls
                foreach (Exception exception in e.LoaderExceptions)
                {
                    if (exception != null)
                    {
                        targetLoggingContext.LogError(new BuildEventFileInfo(taskProjectFile), "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, exception.Message);
                    }
                }

                ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message);
            }
            catch (ArgumentNullException e)
            {
                // taskName may be null
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message);
            }
            catch (Exception e) // Catching Exception, but rethrowing unless it's a well-known exception.
            {
                if (ExceptionHandling.NotExpectedReflectionException(e))
                {
                    throw;
                }

                ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "TaskLoadFailure", taskName, loadInfo.AssemblyLocation, e.Message);
            }

            return(_loadedType);
        }
Esempio n. 2
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 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/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);
        }
Esempio n. 3
0
        /// <summary>
        /// Determines how many times the batchable object needs to be executed (each execution is termed a "batch"), and prepares
        /// buckets of items to pass to the object in each batch.
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="batchableObjectParameters"></param>
        /// <param name="lookup"></param>
        /// <param name="implicitBatchableItemType">Any item type that can be considered an implicit input to this batchable object.
        /// This is useful for items inside targets, where the item name is plainly an item type that's an "input" to the object.</param>
        /// <returns>ArrayList containing ItemBucket objects, each one representing an execution batch.</returns>
        internal static ArrayList PrepareBatchingBuckets
        (
            XmlNode parentNode,
            List <string> batchableObjectParameters,
            Lookup lookup,
            string implicitBatchableItemType
        )
        {
            ErrorUtilities.VerifyThrow(parentNode != null, "Need the XML node that represents the batchable object.");
            ErrorUtilities.VerifyThrow(batchableObjectParameters != null, "Need the parameters of the batchable object to determine if it can be batched.");
            ErrorUtilities.VerifyThrow(lookup != null, "Need to specify the lookup.");

            ItemsAndMetadataPair pair = ExpressionShredder.GetReferencedItemNamesAndMetadata(batchableObjectParameters);

            // All the @(itemname) item list references in the tag, including transforms, etc.
            // The keys in the hashtable are the item names, and the values are all String.Empty (not used).
            Hashtable consumedItemReferences = pair.Items;

            // All the %(itemname.metadataname) references in the tag (not counting those embedded
            // inside item transforms), and note that the itemname portion is optional.
            // The keys in the returned hash table are the qualified metadata names (e.g. "EmbeddedResource.Culture"
            // or just "Culture").  The values are MetadataReference structs, which simply split out the item
            // name (possibly null) and the actual metadata name.
            Dictionary <string, MetadataReference> consumedMetadataReferences = pair.Metadata;

            ArrayList buckets = null;

            if (consumedMetadataReferences != null && consumedMetadataReferences.Count > 0)
            {
                // Add any item types that we were explicitly told to assume.
                if (implicitBatchableItemType != null)
                {
                    consumedItemReferences = Utilities.CreateTableIfNecessary(consumedItemReferences);
                    consumedItemReferences[implicitBatchableItemType] = String.Empty;
                }

                // This method goes through all the item list references and figures out which ones
                // will be participating in batching, and which ones won't.  We get back a hashtable
                // where the key is the item name that will be participating in batching.  The values
                // are all String.Empty (not used).  This method may return additional item names
                // that weren't represented in "consumedItemReferences"... this would happen if there
                // were qualified metadata references in the consumedMetadataReferences table, such as
                // %(EmbeddedResource.Culture).
                Hashtable itemListsToBeBatched = GetItemListsToBeBatched(parentNode, consumedMetadataReferences, consumedItemReferences, lookup);

                // At this point, if there were any metadata references in the tag, but no item
                // references to batch on, we've got a problem because we can't figure out which
                // item lists the user wants us to batch.
                if (itemListsToBeBatched.Count == 0)
                {
                    foreach (string unqualifiedMetadataName in consumedMetadataReferences.Keys)
                    {
                        // Of course, since this throws an exception, there's no way we're ever going
                        // to really loop here... it's just that the foreach is the only way I can
                        // figure out how to get data out of the hashtable without knowing any of the
                        // keys!
                        ProjectErrorUtilities.VerifyThrowInvalidProject(false,
                                                                        parentNode, "CannotReferenceItemMetadataWithoutItemName", unqualifiedMetadataName);
                    }
                }
                else
                {
                    // If the batchable object consumes item metadata as well as items to be batched,
                    // we need to partition the items consumed by the object.
                    buckets = BucketConsumedItems(parentNode, lookup, itemListsToBeBatched, consumedMetadataReferences);
                }
            }

            // if the batchable object does not consume any item metadata or items, or if the item lists it consumes are all
            // empty, then the object does not need to be batched
            if ((buckets == null) || (buckets.Count == 0))
            {
                // create a default bucket that references the project items and properties -- this way we always have a bucket
                buckets = new ArrayList(1);
                buckets.Add(new ItemBucket(null, null, lookup, buckets.Count));
            }

            return(buckets);
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a new UsingTask object
        /// </summary>
        /// <param name="usingTaskNode"></param>
        /// <param name="isImported"></param>
        /// <owner>LukaszG</owner>
        internal UsingTask(XmlElement usingTaskNode, bool isImported)
        {
            this.importedFromAnotherProject = isImported;

            // make sure this really is a <UsingTask> tag
            ErrorUtilities.VerifyThrow(usingTaskNode.Name == XMakeElements.usingTask,
                                       "Expected <{0}> element; received <{1}> element.", XMakeElements.usingTask, usingTaskNode.Name);

            bool       illegalChildElementFound = false;
            XmlElement illegalChildElement      = null;

            foreach (XmlElement childElement in usingTaskNode.ChildNodes)
            {
                switch (childElement.Name)
                {
                case XMakeElements.usingTaskBody:
                    // ignore
                    break;

                case XMakeElements.usingTaskParameter:
                    // ignore
                    break;

                case XMakeElements.usingTaskParameterGroup:
                    // ignore
                    break;

                default:
                    illegalChildElementFound = true;
                    illegalChildElement      = childElement;
                    break;
                }

                if (illegalChildElementFound)
                {
                    break;
                }
            }

            // UsingTask has no valid child elements in 3.5 syntax, but in 4.0 syntax it does.
            // So ignore any valid 4.0 child elements and try to load the project as usual, but
            // still error out if something we don't expect is found.
            if (illegalChildElementFound)
            {
                ProjectXmlUtilities.ThrowProjectInvalidChildElement(illegalChildElement);
            }

            foreach (XmlAttribute usingTaskAttribute in usingTaskNode.Attributes)
            {
                switch (usingTaskAttribute.Name)
                {
                // get the task name
                case XMakeAttributes.taskName:
                    taskNameAttribute = usingTaskAttribute;
                    break;

                // get the assembly name or the assembly file/path, whichever is specified...
                case XMakeAttributes.assemblyName:
                    assemblyNameAttribute = usingTaskAttribute;
                    break;

                case XMakeAttributes.assemblyFile:
                    assemblyFileAttribute = usingTaskAttribute;
                    break;

                // ignore any RequiredRuntime XML attribute
                // (we'll make this actually do something when we run on a CLR other than v2.0)
                case XMakeAttributes.requiredRuntime:
                    // Do nothing
                    break;

                // get the condition, if any
                case XMakeAttributes.condition:
                    conditionAttribute = usingTaskAttribute;
                    break;

                // This is only recognized by the new OM:
                // Just ignore it
                case XMakeAttributes.requiredPlatform:
                    // Do nothing
                    break;

                // This is only recognized by the new OM:
                // Just ignore it
                case XMakeAttributes.taskFactory:
                    // Do nothing
                    break;

                // This is only recognized by the new OM:
                // Just ignore it
                case XMakeAttributes.runtime:
                    // Do nothing
                    break;

                // This is only recognized by the new OM:
                // Just ignore it
                case XMakeAttributes.architecture:
                    // Do nothing
                    break;

                default:
                    ProjectXmlUtilities.ThrowProjectInvalidAttribute(usingTaskAttribute);
                    break;
                }
            }

            ProjectErrorUtilities.VerifyThrowInvalidProject(taskNameAttribute != null,
                                                            usingTaskNode, "MissingRequiredAttribute", XMakeAttributes.taskName, XMakeElements.usingTask);
            ProjectErrorUtilities.VerifyThrowInvalidProject(taskNameAttribute.Value.Length > 0,
                                                            taskNameAttribute, "InvalidAttributeValue", taskNameAttribute.Value, XMakeAttributes.taskName, XMakeElements.usingTask);

            ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyNameAttribute != null) || (assemblyFileAttribute != null),
                                                            usingTaskNode, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, XMakeAttributes.assemblyFile);
            ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyNameAttribute == null) || (assemblyFileAttribute == null),
                                                            usingTaskNode, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, XMakeAttributes.assemblyFile);

            ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyNameAttribute == null) || (assemblyNameAttribute.Value.Length > 0),
                                                            assemblyNameAttribute, "InvalidAttributeValue", String.Empty, XMakeAttributes.assemblyName, XMakeElements.usingTask);
            ProjectErrorUtilities.VerifyThrowInvalidProject((assemblyFileAttribute == null) || (assemblyFileAttribute.Value.Length > 0),
                                                            assemblyFileAttribute, "InvalidAttributeValue", String.Empty, XMakeAttributes.assemblyFile, XMakeElements.usingTask);
        }
Esempio n. 5
0
        /// <summary>
        /// Parse a ProjectItemElement
        /// </summary>
        private ProjectItemElement ParseProjectItemElement(XmlElementWithLocation element, ProjectItemGroupElement parent)
        {
            bool belowTarget = parent.Parent is ProjectTargetElement;

            string itemType = element.Name;
            string include  = element.GetAttribute(XMakeAttributes.include);
            string exclude  = element.GetAttribute(XMakeAttributes.exclude);
            string remove   = element.GetAttribute(XMakeAttributes.remove);
            string update   = element.GetAttribute(XMakeAttributes.update);

            var exclusiveItemOperation  = "";
            int exclusiveAttributeCount = 0;

            if (element.HasAttribute(XMakeAttributes.include))
            {
                exclusiveAttributeCount++;
                exclusiveItemOperation = XMakeAttributes.include;
            }
            if (element.HasAttribute(XMakeAttributes.remove))
            {
                exclusiveAttributeCount++;
                exclusiveItemOperation = XMakeAttributes.remove;
            }
            if (element.HasAttribute(XMakeAttributes.update))
            {
                exclusiveAttributeCount++;
                exclusiveItemOperation = XMakeAttributes.update;
            }

            //  At most one of the include, remove, or update attributes may be specified
            if (exclusiveAttributeCount > 1)
            {
                XmlAttributeWithLocation errorAttribute = remove.Length > 0 ? (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.remove] : (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.update];
                ProjectErrorUtilities.ThrowInvalidProject(errorAttribute.Location, "InvalidAttributeExclusive");
            }

            // Include, remove, or update must be present unless inside a target
            ProjectErrorUtilities.VerifyThrowInvalidProject(exclusiveAttributeCount == 1 || belowTarget, element.Location, "IncludeRemoveOrUpdate", exclusiveItemOperation, itemType);

            // Exclude must be missing, unless Include exists
            ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(exclude.Length == 0 || include.Length > 0, (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.exclude]);

            // If we have an Include attribute at all, it must have non-zero length
            ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType);

            // If we have a Remove attribute at all, it must have non-zero length
            ProjectErrorUtilities.VerifyThrowInvalidProject(remove.Length > 0 || element.Attributes[XMakeAttributes.remove] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.remove, itemType);

            // If we have an Update attribute at all, it must have non-zero length
            ProjectErrorUtilities.VerifyThrowInvalidProject(update.Length > 0 || element.Attributes[XMakeAttributes.update] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.update, itemType);

            XmlUtilities.VerifyThrowProjectValidElementName(element);
            ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(itemType), element.Location, "CannotModifyReservedItem", itemType);

            ProjectItemElement item = new ProjectItemElement(element, parent, _project);

            foreach (XmlAttributeWithLocation attribute in element.Attributes)
            {
                bool isKnownAttribute;
                bool isValidMetadataNameInAttribute;

                CheckMetadataAsAttributeName(attribute.Name, out isKnownAttribute, out isValidMetadataNameInAttribute);

                if (!isKnownAttribute && !isValidMetadataNameInAttribute)
                {
                    ProjectXmlUtilities.ThrowProjectInvalidAttribute(attribute);
                }
                else if (isValidMetadataNameInAttribute)
                {
                    ProjectMetadataElement metadatum = _project.CreateMetadataElement(attribute.Name, attribute.Value);
                    metadatum.ExpressedAsAttribute = true;
                    metadatum.Parent = item;

                    item.AppendParentedChildNoChecks(metadatum);
                }
            }

            foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element))
            {
                ProjectMetadataElement metadatum = ParseProjectMetadataElement(childElement, item);

                item.AppendParentedChildNoChecks(metadatum);
            }

            return(item);
        }
Esempio n. 6
0
 /// <summary>
 /// Verify that the element has the specified required attribute on it and
 /// it has a value other than empty string
 /// </summary>
 internal static void VerifyThrowProjectRequiredAttribute(XmlElementWithLocation element, string attributeName)
 {
     ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(attributeName).Length > 0, element.Location, "MissingRequiredAttribute", attributeName, element.Name);
 }
        /// <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)
            {
                var 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)
                    {
                        var 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);
        }
Esempio n. 8
0
        /// <summary>
        /// Builds this target if it has not already been built as part of its parent project. Before we actually execute the
        /// tasks for this target, though, we first call on all the dependent targets to build themselves.
        /// This function may throw InvalidProjectFileException
        /// </summary>
        internal void Build
        (
            ProjectBuildState buildContext
        )
        {
            // Depending on the build state, we may do different things.
            switch (buildState)
            {
            case BuildState.InProgress:
                // In single proc mode if the build state was already "in progress"
                // and somebody just told us to build ourselves, it means that there is
                // a loop (circular dependency) in the target dependency graph. In multi
                // proc mode we need to analyze the dependency graph before we can
                // tell if there a circular dependency or if two independent chains
                // of targets happen to need the result of this target.
                if (parentEngine.Router.SingleThreadedMode || buildContext.ContainsCycle(this.Name))
                {
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, TargetElement, "CircularDependency", targetName);
                }
                else
                {
                    buildContext.CurrentBuildContextState = ProjectBuildState.BuildContextState.WaitingForTarget;
                    this.executionState.AddWaitingBuildContext(buildContext);
                }
                break;

            case BuildState.CompletedSuccessfully:
            case BuildState.CompletedUnsuccessfully:
                // If this target has already been built as part of this project,
                // we're not going to build it again.  Just return the result
                // from when it was built previously.  Note:  This condition
                // could really only ever hold true if the user specifically
                // requested us to build multiple targets and there existed
                // a direct or indirect dependency relationship between two or
                // more of those top-level targets.
                // Note: we aren't really entering the target in question here, so don't use the target
                // event context. Using the target ID for skipped messages would force us to
                // cache the individual target IDs for unloaded projects and it's not really worth the trouble.
                // Just use the parent event context.
                parentEngine.LoggingServices.LogComment(buildContext.ProjectBuildEventContext,
                                                        (buildState == BuildState.CompletedSuccessfully) ? "TargetAlreadyCompleteSuccess" : "TargetAlreadyCompleteFailure",
                                                        this.targetName);

                // Only contexts which are generated from an MSBuild task could need
                // the outputs of this target, such contexts have a non-null evaluation
                // request
                if ((buildState == BuildState.CompletedSuccessfully) &&
                    (buildContext.BuildRequest.OutputsByTarget != null &&
                     buildContext.NameOfBlockingTarget == null))
                {
                    error.VerifyThrow(
                        String.Equals(EscapingUtilities.UnescapeAll(buildContext.NameOfTargetInProgress), this.Name, StringComparison.OrdinalIgnoreCase),
                        "The name of the target in progress is inconsistent with the target being built");

                    error.VerifyThrow(targetOutputItems != null,
                                      "If the target built successfully, we must have its outputs.");

                    buildContext.BuildRequest.OutputsByTarget[Name] = targetOutputItems.ToArray();
                }

                if (buildContext.NameOfBlockingTarget == null)
                {
                    buildContext.BuildRequest.ResultByTarget[Name] = buildState;
                }
                break;

            case BuildState.NotStarted:
            case BuildState.Skipped:
            {
                // Always have to create a new context in build as other projects or targets may try and build this target
                BuildEventContext targetBuildEventContext = new BuildEventContext
                                                            (
                    buildContext.ProjectBuildEventContext.NodeId,
                    this.id,
                    buildContext.ProjectBuildEventContext.ProjectContextId,
                    buildContext.ProjectBuildEventContext.TaskId
                                                            );

                Expander expander = new Expander(this.parentProject.evaluatedProperties, this.parentProject.evaluatedItemsByName);

                // We first make sure no batching was attempted with the target's condition.
                if (!conditionCheckedForInvalidMetadataReferences)
                {
                    if (ExpressionShredder.ContainsMetadataExpressionOutsideTransform(this.Condition))
                    {
                        ProjectErrorUtilities.ThrowInvalidProject(this.conditionAttribute, "TargetConditionHasInvalidMetadataReference", targetName, this.Condition);
                    }
                    conditionCheckedForInvalidMetadataReferences = true;
                }

                // If condition is false (based on propertyBag), set this target's state to
                // "Skipped" since we won't actually build it.
                if (!Utilities.EvaluateCondition(this.Condition, this.conditionAttribute,
                                                 expander, null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists,
                                                 parentEngine.LoggingServices, targetBuildEventContext))
                {
                    buildState = BuildState.Skipped;

                    if (buildContext.NameOfBlockingTarget == null)
                    {
                        buildContext.BuildRequest.ResultByTarget[Name] = buildState;
                    }

                    if (!parentEngine.LoggingServices.OnlyLogCriticalEvents)
                    {
                        // Expand the expression for the Log.
                        string expanded = expander.ExpandAllIntoString(this.Condition, this.conditionAttribute);
                        // By design: Not building dependencies. This is what NAnt does too.
                        parentEngine.LoggingServices.LogComment(targetBuildEventContext, "TargetSkippedFalseCondition",
                                                                this.targetName, this.Condition, expanded);
                    }
                }
                else
                {
                    // This target has not been built yet.  So build it!
                    // Change our state to "in progress". TargetParameters will need to be re-calculated if Inputs and Outputs attribute has changed.
                    buildState = BuildState.InProgress;
                    List <string> batchableTargetParameters = GetBatchableTargetParameters();
                    executionState = new TargetExecutionWrapper(this, taskElementList, batchableTargetParameters, targetElement, expander, targetBuildEventContext);
                    ContinueBuild(buildContext, null);
                }
            }
            break;

            default:
                error.VerifyThrow(false, "Build state {0} not handled in Target.Build method", buildState);
                break;
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Reads the given &lt;UsingTask&gt; tag and saves the task information specified in it.
        /// </summary>
        /// <param name="usingTask"></param>
        /// <param name="expander"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        public void RegisterTask(UsingTask usingTask, Expander expander, EngineLoggingServices loggingServices, BuildEventContext buildEventContext)
        {
            if (
                // if the <UsingTask> tag doesn't have a condition on it
                (usingTask.Condition == null)
                ||
                // or if the condition holds
                Utilities.EvaluateCondition(usingTask.Condition, usingTask.ConditionAttribute, expander,
                                            null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists, loggingServices, buildEventContext)
                )
            {
                // Lazily allocate the hashtables if they are needed
                if (registeredTasks == null)
                {
                    cachedTaskClassesWithExactMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    cachedTaskClassesWithFuzzyMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    registeredTasks = new Hashtable(StringComparer.OrdinalIgnoreCase);
                }

                string assemblyName = null;
                string assemblyFile = null;

                if (usingTask.AssemblyName != null)
                {
                    // expand out all embedded properties and items in the assembly name
                    assemblyName = expander.ExpandAllIntoString(usingTask.AssemblyName, usingTask.AssemblyNameAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyName.Length > 0,
                                                                    usingTask.AssemblyNameAttribute, "InvalidEvaluatedAttributeValue", assemblyName, usingTask.AssemblyName, XMakeAttributes.assemblyName, XMakeElements.usingTask);
                }
                else
                {
                    // expand out all embedded properties and items in the assembly file/path
                    assemblyFile = expander.ExpandAllIntoString(usingTask.AssemblyFile, usingTask.AssemblyFileAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyFile.Length > 0,
                                                                    usingTask.AssemblyFileAttribute, "InvalidEvaluatedAttributeValue", assemblyFile, usingTask.AssemblyFile, XMakeAttributes.assemblyFile, XMakeElements.usingTask);

                    // figure out the directory of the project in which this <UsingTask> node was defined
                    string projectFile = XmlUtilities.GetXmlNodeFile(usingTask.TaskNameAttribute.OwnerElement, String.Empty);
                    string projectDir  = (projectFile.Length > 0)
                        ? Path.GetDirectoryName(projectFile)
                        : String.Empty;

                    // ensure the assembly file/path is relative to the project in which this <UsingTask> node was defined -- we
                    // don't want paths from imported projects being interpreted relative to the main project file
                    try
                    {
                        assemblyFile = Path.Combine(projectDir, assemblyFile);
                    }
                    catch (ArgumentException ex)
                    {
                        // Invalid chars in AssemblyFile path
                        ProjectErrorUtilities.VerifyThrowInvalidProject(false, usingTask.AssemblyFileAttribute,
                                                                        "InvalidAttributeValueWithException", assemblyFile,
                                                                        XMakeAttributes.assemblyFile, XMakeElements.usingTask, ex.Message);
                    }
                }

                AssemblyLoadInfo taskAssembly = new AssemblyLoadInfo(assemblyName, assemblyFile);

                // expand out all embedded properties and items
                string taskName = expander.ExpandAllIntoString(usingTask.TaskName, usingTask.TaskNameAttribute);

                ProjectErrorUtilities.VerifyThrowInvalidProject(taskName.Length > 0,
                                                                usingTask.TaskNameAttribute, "InvalidEvaluatedAttributeValue", taskName, usingTask.TaskName, XMakeAttributes.taskName, XMakeElements.usingTask);

                // since more than one task can have the same name, we want to keep track of all assemblies that are declared to
                // contain tasks with a given name...
                ArrayList taskAssemblies = (ArrayList)registeredTasks[taskName];

                if (taskAssemblies == null)
                {
                    taskAssemblies            = new ArrayList();
                    registeredTasks[taskName] = taskAssemblies;
                }

                taskAssemblies.Add(taskAssembly);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Adds a ProjectElement to the Xml tree
        /// </summary>
        /// <param name="child">A child to add to the Xml tree, which has already been added to the ProjectElement tree</param>
        /// <remarks>
        /// The MSBuild construction APIs keep a tree of ProjectElements and a parallel Xml tree which consists of
        /// objects from System.Xml.  This is a helper method which adds an XmlElement or Xml attribute to the Xml
        /// tree after the corresponding ProjectElement has been added to the construction API tree, and fixes up
        /// whitespace as necessary.
        /// </remarks>
        internal void AddToXml(ProjectElement child)
        {
            if (child.ExpressedAsAttribute)
            {
                // todo children represented as attributes need to be placed in order too
                //  Assume that the name of the child has already been validated to conform with rules in XmlUtilities.VerifyThrowArgumentValidElementName

                //  Make sure we're not trying to add multiple attributes with the same name
                ProjectErrorUtilities.VerifyThrowInvalidProject(!XmlElement.HasAttribute(child.XmlElement.Name),
                                                                XmlElement.Location, "InvalidChildElementDueToDuplication", child.XmlElement.Name, ElementName);

                SetElementAsAttributeValue(child);
            }
            else
            {
                //  We want to add the XmlElement to the same position in the child list as the corresponding ProjectElement.
                //  Depending on whether the child ProjectElement has a PreviousSibling or a NextSibling, we may need to
                //  use the InsertAfter, InsertBefore, or AppendChild methods to add it in the right place.
                //
                //  Also, if PreserveWhitespace is true, then the elements we add won't automatically get indented, so
                //  we try to match the surrounding formatting.

                // Siblings, in either direction in the linked list, may be represented either as attributes or as elements.
                // Therefore, we need to traverse both directions to find the first sibling of the same type as the one being added.
                // If none is found, then the node being added is inserted as the only node of its kind

                ProjectElement             referenceSibling;
                Predicate <ProjectElement> siblingIsSameAsChild = _ => _.ExpressedAsAttribute == false;

                if (TrySearchLeftSiblings(child.PreviousSibling, siblingIsSameAsChild, out referenceSibling))
                {
                    //  Add after previous sibling
                    XmlElement.InsertAfter(child.XmlElement, referenceSibling.XmlElement);
                    if (XmlDocument.PreserveWhitespace)
                    {
                        //  Try to match the surrounding formatting by checking the whitespace that precedes the node we inserted
                        //  after, and inserting the same whitespace between the previous node and the one we added
                        if (referenceSibling.XmlElement.PreviousSibling != null &&
                            referenceSibling.XmlElement.PreviousSibling.NodeType == XmlNodeType.Whitespace)
                        {
                            var newWhitespaceNode = XmlDocument.CreateWhitespace(referenceSibling.XmlElement.PreviousSibling.Value);
                            XmlElement.InsertAfter(newWhitespaceNode, referenceSibling.XmlElement);
                        }
                    }
                }
                else if (TrySearchRightSiblings(child.NextSibling, siblingIsSameAsChild, out referenceSibling))
                {
                    //  Add as first child
                    XmlElement.InsertBefore(child.XmlElement, referenceSibling.XmlElement);

                    if (XmlDocument.PreserveWhitespace)
                    {
                        //  Try to match the surrounding formatting by checking the whitespace that precedes where we inserted
                        //  the new node, and inserting the same whitespace between the node we added and the one after it.
                        if (child.XmlElement.PreviousSibling != null &&
                            child.XmlElement.PreviousSibling.NodeType == XmlNodeType.Whitespace)
                        {
                            var newWhitespaceNode = XmlDocument.CreateWhitespace(child.XmlElement.PreviousSibling.Value);
                            XmlElement.InsertBefore(newWhitespaceNode, referenceSibling.XmlElement);
                        }
                    }
                }
                else
                {
                    //  Add as only child
                    XmlElement.AppendChild(child.XmlElement);

                    if (XmlDocument.PreserveWhitespace)
                    {
                        //  Try to match the surrounding formatting and add one indentation level
                        if (XmlElement.FirstChild.NodeType == XmlNodeType.Whitespace)
                        {
                            //  This container had a whitespace node, which should generally be a newline and the indent
                            //  before the closing tag.  So we add the default indentation to it so the child will now be indented
                            //  further, and then create a new whitespace node after the child so the closing tag will be on
                            //  a new line with the same indentation.
                            //  If the whitespace we end up copying isn't actually (newline + indentation) like we expect, then it
                            //  should still be OK to copy it, as we'll still be trying to match the surrounding formatting.
                            string whitespace = XmlElement.FirstChild.Value;
                            XmlElement.FirstChild.Value = whitespace + DEFAULT_INDENT;
                            var newWhitespaceNode = XmlDocument.CreateWhitespace(whitespace);
                            XmlElement.InsertAfter(newWhitespaceNode, child.XmlElement);
                        }
                        else if (XmlElement.PreviousSibling != null &&
                                 XmlElement.PreviousSibling.NodeType == XmlNodeType.Whitespace)
                        {
                            //  This container didn't have any whitespace in it.  This probably means it didn't have separate open
                            //  and close tags.  So add a whitespace node before the new child with additional indentation over the
                            //  container's indentation, and add a whitespace node with the same level of indentation as the container
                            //  after the new child so the closing tag will be indented properly.
                            string parentWhitespace       = XmlElement.PreviousSibling.Value;
                            var    indentedWhitespaceNode = XmlDocument.CreateWhitespace(parentWhitespace + DEFAULT_INDENT);
                            XmlElement.InsertBefore(indentedWhitespaceNode, child.XmlElement);
                            var unindentedWhitespaceNode = XmlDocument.CreateWhitespace(parentWhitespace);
                            XmlElement.InsertAfter(unindentedWhitespaceNode, child.XmlElement);
                        }
                    }
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Internal constructor
        /// </summary>
        /// <param name="importElement"></param>
        /// <param name="isImported"></param>
        /// <owner>LukaszG</owner>
        internal Import(XmlElement importElement, Project parentProject, bool isImported)
        {
            this.importedFromAnotherProject = isImported;

            // Make sure the <Import> node has been given to us.
            ErrorUtilities.VerifyThrow(importElement != null,
                                       "Need an XML node representing the <Import> element.");

            this.importElement = importElement;

            // Make sure we have a valid parent Project
            ErrorUtilities.VerifyThrow(parentProject != null,
                                       "Need a parent Project object to instantiate an Import.");

            this.parentProject = parentProject;

            // Make sure this really is the <Import> node.
            ProjectXmlUtilities.VerifyThrowElementName(importElement, XMakeElements.import);

            // Loop through the list of attributes on the <Import> element.
            foreach (XmlAttribute importAttribute in importElement.Attributes)
            {
                switch (importAttribute.Name)
                {
                // The "project" attribute points us at the project file to import.
                case XMakeAttributes.project:
                    // Just store the attribute value at this point. We want to make sure that we evaluate any
                    // Condition attribute before looking at the Project attribute - if the Condition is going to be false,
                    // it's legitimate for the value of the Project attribute to be completely invalid.
                    // For example, <Import Project="$(A)" Condition="$(A)!=''"/> should not cause an error
                    // that the Project attribute is empty.
                    this.projectPathAttribute = importAttribute;
                    break;

                // If the "condition" attribute is present, then it must evaluate to "true".
                case XMakeAttributes.condition:
                    this.conditionAttribute = importAttribute;
                    break;

                // We've come across an attribute in the <Import> element that we
                // don't recognize.  Fail due to invalid project file.
                default:
                    ProjectXmlUtilities.ThrowProjectInvalidAttribute(importAttribute);
                    break;
                }
            }

            ProjectErrorUtilities.VerifyThrowInvalidProject((this.projectPathAttribute != null) && (this.projectPathAttribute.Value.Length != 0),
                                                            importElement, "MissingRequiredAttribute",
                                                            XMakeAttributes.project, XMakeElements.import);

            // Make sure this node has no children.  Our schema doesn't support having
            // children beneath the <Import> element.
            if (importElement.HasChildNodes)
            {
                // Don't put the "if" condition inside the first parameter to
                // VerifyThrow..., because we'll get null reference exceptions,
                // since the parameter importElement.FirstChild.Name is being
                // passed in regardless of whether the condition holds true or not.
                ProjectXmlUtilities.ThrowProjectInvalidChildElement(importElement.FirstChild);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Evaluate node as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluationState state)
        {
            if (String.Compare(functionName, "exists", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("exists", (GenericExpressionNode)arguments[0], state);

                if (Project.PerThreadProjectDirectory != null && !String.IsNullOrEmpty(expandedValue))
                {
                    try
                    {
                        expandedValue = Path.GetFullPath(Path.Combine(Project.PerThreadProjectDirectory, expandedValue));
                    }
                    catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception.
                    {
                        if (ExceptionHandling.NotExpectedException(e))
                        {
                            throw;
                        }

                        // Ignore invalid characters or path related exceptions

                        // We will ignore the PathTooLong exception caused by GetFullPath becasue in single proc this code
                        // is not executed and the condition is just evaluated to false as File.Exists and Directory.Exists does not throw in this situation.
                        // To be consistant with that we will return a false in this case also.
                        // DevDiv Bugs: 46035

                        return(false);
                    }
                }

                // Both Exists functions return false if the value is null or empty
                return(File.Exists(expandedValue) || Directory.Exists(expandedValue));
            }
            else if (String.Compare(functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("HasTrailingSlash", (GenericExpressionNode)arguments[0], state);

                // Is the last character a backslash?
                if (expandedValue.Length != 0)
                {
                    char lastCharacter = expandedValue[expandedValue.Length - 1];
                    // Either back or forward slashes satisfy the function: this is useful for URL's
                    return(lastCharacter == Path.DirectorySeparatorChar || lastCharacter == Path.AltDirectorySeparatorChar);
                }
                else
                {
                    return(false);
                }
            }
            // We haven't implemented any other "functions"
            else
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(
                    false,
                    state.conditionAttribute,
                    "UndefinedFunctionCall",
                    state.parsedCondition,
                    this.functionName);

                return(false);
            }
        }
Esempio n. 13
0
        internal BuildItemGroupChildXml(XmlElement element, ChildType childTypeExpected)
        {
            ErrorUtilities.VerifyThrow(element != null, "Need an XML node.");
            ErrorUtilities.VerifyThrowNoAssert(childTypeExpected != ChildType.Invalid, "Can't expect invalid childtype");
            ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(element);

            this.element = element;

            // Loop through each of the attributes on the item element.
            foreach (XmlAttribute attribute in element.Attributes)
            {
                switch (attribute.Name)
                {
                case XMakeAttributes.include:
                    this.includeAttribute = attribute;
                    break;

                case XMakeAttributes.exclude:
                    this.excludeAttribute = attribute;
                    break;

                case XMakeAttributes.condition:
                    this.conditionAttribute = attribute;
                    break;

                case XMakeAttributes.xmlns:
                    // We already verified that the namespace is correct
                    break;

                case XMakeAttributes.remove:
                    this.removeAttribute = attribute;
                    break;

                case XMakeAttributes.keepMetadata:
                case XMakeAttributes.removeMetadata:
                case XMakeAttributes.keepDuplicates:
                    // Ignore these - they are part of the new OM.
                    break;

                default:
                    ProjectXmlUtilities.ThrowProjectInvalidAttribute(attribute);
                    break;
                }
            }

            this.childType = ChildType.Invalid;

            // Default to modify, if that's one of the child types we are told to expect.
            if ((childTypeExpected & ChildType.BuildItemModify) == ChildType.BuildItemModify)
            {
                this.childType = ChildType.BuildItemModify;
            }

            if (this.includeAttribute != null)
            {
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd, includeAttribute);
                ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name);
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(removeAttribute == null, removeAttribute);
                this.childType = ChildType.BuildItemAdd;
            }

            if (this.excludeAttribute != null)
            {
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd, excludeAttribute);
                ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name);
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(removeAttribute == null, removeAttribute);
                this.childType = ChildType.BuildItemAdd;
            }

            if (this.removeAttribute != null)
            {
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute((childTypeExpected & ChildType.BuildItemRemove) == ChildType.BuildItemRemove, removeAttribute);
                ProjectErrorUtilities.VerifyThrowInvalidProject(Remove.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.remove, element.Name);
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(includeAttribute == null, includeAttribute);
                ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(excludeAttribute == null, excludeAttribute);
                this.childType = ChildType.BuildItemRemove;
            }

            if (this.childType == ChildType.Invalid)
            {
                // So the xml wasn't consistent with any of the child types that we were told to expect.
                // Figure out the most reasonable message to produce.
                if ((childTypeExpected & ChildType.BuildItemAdd) == ChildType.BuildItemAdd)
                {
                    ProjectErrorUtilities.VerifyThrowInvalidProject(Include.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.include, element.Name);
                }
                else if ((childTypeExpected & ChildType.BuildItemRemove) == ChildType.BuildItemRemove)
                {
                    ProjectErrorUtilities.VerifyThrowInvalidProject(Remove.Length > 0, element, "MissingRequiredAttribute", XMakeAttributes.remove, element.Name);
                }
                else
                {
                    ErrorUtilities.ThrowInternalError("Unexpected child type");
                }
            }

            // Validate each of the child nodes beneath the item.
            List <XmlElement> children = ProjectXmlUtilities.GetValidChildElements(element);

            if (this.childType == ChildType.BuildItemRemove && children.Count != 0)
            {
                ProjectErrorUtilities.ThrowInvalidProject(element, "ChildElementsBelowRemoveNotAllowed", children[0].Name);
            }

            foreach (XmlElement child in children)
            {
                ProjectXmlUtilities.VerifyThrowProjectValidNameAndNamespace(child);

                ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.IsItemSpecModifier(child.Name), child, "ItemSpecModifierCannotBeCustomMetadata", child.Name);
                ProjectErrorUtilities.VerifyThrowInvalidProject(XMakeElements.IllegalItemPropertyNames[child.Name] == null, child, "CannotModifyReservedItemMetadata", child.Name);
            }
        }
        /// <summary>
        /// Processes the target stack until its empty or we hit a recursive break (due to CallTarget etc.)
        /// </summary>
        private async Task ProcessTargetStack(ITaskBuilder taskBuilder)
        {
            // Keep building while we have targets to build and haven't been cancelled.
            bool stopProcessingStack = false;

            while
            (
                !_cancellationToken.IsCancellationRequested &&
                !stopProcessingStack &&
                !_targetsToBuild.IsEmpty
            )
            {
                TargetEntry currentTargetEntry = _targetsToBuild.Peek();
                switch (currentTargetEntry.State)
                {
                case TargetEntryState.Dependencies:
                    // Ensure we are dealing with a target which actually exists.
                    ProjectErrorUtilities.VerifyThrowInvalidProject
                    (
                        _requestEntry.RequestConfiguration.Project.Targets.ContainsKey(currentTargetEntry.Name),
                        currentTargetEntry.ReferenceLocation,
                        "TargetDoesNotExist",
                        currentTargetEntry.Name
                    );

                    // If we already have results for this target which were not skipped, we can ignore it.  In
                    // addition, we can also ignore its before and after targets -- if this target has already run,
                    // then so have they.
                    if (!CheckSkipTarget(ref stopProcessingStack, currentTargetEntry))
                    {
                        // Temporarily remove this entry so we can push our after targets
                        _targetsToBuild.Pop();

                        // Push our after targets, if any.  Our parent is the parent of the target after which we are running.
                        IList <TargetSpecification> afterTargets = _requestEntry.RequestConfiguration.Project.GetTargetsWhichRunAfter(currentTargetEntry.Name);
                        bool didPushTargets = await PushTargets(afterTargets, currentTargetEntry.ParentEntry, currentTargetEntry.Lookup, currentTargetEntry.ErrorTarget, currentTargetEntry.StopProcessingOnCompletion, TargetPushType.AfterTargets);

                        // If we have after targets, the last one to run will inherit the stopProcessing flag and we will reset ours.  If we didn't push any targets, then we shouldn't clear the
                        // flag because it means we are still on the bottom of this CallTarget stack.
                        if ((afterTargets.Count != 0) && didPushTargets)
                        {
                            currentTargetEntry.StopProcessingOnCompletion = false;
                        }

                        // Put us back on the stack
                        _targetsToBuild.Push(currentTargetEntry);

                        // Determine which targets are dependencies.  This will also test to see if the target should be skipped due to condition.
                        // If it is determined the target should skip, the dependency list returned will be empty.
                        IList <TargetSpecification> dependencies = currentTargetEntry.GetDependencies(_projectLoggingContext);

                        // Push our before targets now, unconditionally.  If we have marked that we should stop processing the stack here, which can only
                        // happen if our current target was supposed to stop processing AND we had no after targets, then our last before target should
                        // inherit the stop processing flag and we will reset it.
                        // Our parent is the target before which we run, just like a depends-on target.
                        IList <TargetSpecification> beforeTargets = _requestEntry.RequestConfiguration.Project.GetTargetsWhichRunBefore(currentTargetEntry.Name);
                        bool pushedTargets = await PushTargets(beforeTargets, currentTargetEntry, currentTargetEntry.Lookup, currentTargetEntry.ErrorTarget, stopProcessingStack, TargetPushType.BeforeTargets);

                        if (beforeTargets.Count != 0 && pushedTargets)
                        {
                            stopProcessingStack = false;
                        }

                        // And if we have dependencies to run, push them now.
                        if (null != dependencies)
                        {
                            await PushTargets(dependencies, currentTargetEntry, currentTargetEntry.Lookup, false, false, TargetPushType.Normal);
                        }
                    }

                    break;

                case TargetEntryState.Execution:

                    // It's possible that our target got pushed onto the stack for one build and had its dependencies process, then a re-entrant build came in and
                    // actually built this target while we were waiting, so that by the time we get here, it's already been finished.  In this case, just blow it away.
                    if (!CheckSkipTarget(ref stopProcessingStack, currentTargetEntry))
                    {
                        // This target is now actively building.
                        _requestEntry.RequestConfiguration.ActivelyBuildingTargets.Add(currentTargetEntry.Name, _requestEntry.Request.GlobalRequestId);

                        // Execute all of the tasks on this target.
                        await currentTargetEntry.ExecuteTarget(taskBuilder, _requestEntry, _projectLoggingContext, _cancellationToken);
                    }

                    break;

                case TargetEntryState.ErrorExecution:
                    if (!CheckSkipTarget(ref stopProcessingStack, currentTargetEntry))
                    {
                        // Push the error targets onto the stack.  This target will now be marked as completed.
                        // When that state is processed, it will mark its parent for error execution
                        var errorTargets = currentTargetEntry.GetErrorTargets(_projectLoggingContext);
                        try
                        {
                            await PushTargets(errorTargets, currentTargetEntry, currentTargetEntry.Lookup, true,
                                              false, TargetPushType.Normal);
                        }
                        catch
                        {
                            if (_requestEntry.RequestConfiguration.ActivelyBuildingTargets.ContainsKey(
                                    currentTargetEntry.Name))
                            {
                                _requestEntry.RequestConfiguration.ActivelyBuildingTargets.Remove(currentTargetEntry
                                                                                                  .Name);
                            }

                            throw;
                        }
                    }

                    break;

                case TargetEntryState.Completed:
                    // The target is complete, we can gather up the results and remove this target
                    // from the stack.
                    TargetResult targetResult = currentTargetEntry.GatherResults();

                    // If this result failed but we are under the influence of the legacy ContinueOnError behavior for a
                    // CallTarget, make sure we don't contribute this failure to the overall success of the build.
                    targetResult.TargetFailureDoesntCauseBuildFailure = _legacyCallTargetContinueOnError;

                    // This target is no longer actively building.
                    _requestEntry.RequestConfiguration.ActivelyBuildingTargets.Remove(currentTargetEntry.Name);

                    _buildResult.AddResultsForTarget(currentTargetEntry.Name, targetResult);

                    TargetEntry topEntry = _targetsToBuild.Pop();
                    if (topEntry.StopProcessingOnCompletion)
                    {
                        stopProcessingStack = true;
                    }

                    PopDependencyTargetsOnTargetFailure(topEntry, targetResult, ref stopProcessingStack);

                    break;

                default:
                    ErrorUtilities.ThrowInternalError("Unexpected target state {0}", currentTargetEntry.State);
                    break;
                }
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Adds a ProjectElement to the Xml tree
        /// </summary>
        /// <param name="child">A child to add to the Xml tree, which has already been added to the ProjectElement tree</param>
        /// <remarks>
        /// The MSBuild construction APIs keep a tree of ProjectElements and a parallel Xml tree which consists of
        /// objects from System.Xml.  This is a helper method which adds an XmlElement or Xml attribute to the Xml
        /// tree after the corresponding ProjectElement has been added to the construction API tree, and fixes up
        /// whitespace as necessary.
        /// </remarks>
        internal void AddToXml(ProjectElement child)
        {
            if (child.ExpressedAsAttribute)
            {
                // todo children represented as attributes need to be placed in order too
                //  Assume that the name of the child has already been validated to conform with rules in XmlUtilities.VerifyThrowArgumentValidElementName

                //  Make sure we're not trying to add multiple attributes with the same name
                ProjectErrorUtilities.VerifyThrowInvalidProject(!XmlElement.HasAttribute(child.XmlElement.Name),
                                                                XmlElement.Location, "InvalidChildElementDueToDuplication", child.XmlElement.Name, ElementName);

                SetElementAsAttributeValue(child);
            }
            else
            {
                //  We want to add the XmlElement to the same position in the child list as the corresponding ProjectElement.
                //  Depending on whether the child ProjectElement has a PreviousSibling or a NextSibling, we may need to
                //  use the InsertAfter, InsertBefore, or AppendChild methods to add it in the right place.
                //
                //  Also, if PreserveWhitespace is true, then the elements we add won't automatically get indented, so
                //  we try to match the surrounding formatting.

                // Siblings, in either direction in the linked list, may be represented either as attributes or as elements.
                // Therefore, we need to traverse both directions to find the first sibling of the same type as the one being added.
                // If none is found, then the node being added is inserted as the only node of its kind

                ProjectElement             referenceSibling;
                Predicate <ProjectElement> siblingIsExplicitElement = _ => _.ExpressedAsAttribute == false;

                if (TrySearchLeftSiblings(child.PreviousSibling, siblingIsExplicitElement, out referenceSibling))
                {
                    //  Add after previous sibling
                    XmlElement.InsertAfter(child.XmlElement, referenceSibling.XmlElement);
                    if (XmlDocument.PreserveWhitespace)
                    {
                        //  Try to match the surrounding formatting by checking the whitespace that precedes the node we inserted
                        //  after, and inserting the same whitespace between the previous node and the one we added
                        if (referenceSibling.XmlElement.PreviousSibling != null &&
                            referenceSibling.XmlElement.PreviousSibling.NodeType == XmlNodeType.Whitespace)
                        {
                            var newWhitespaceNode = XmlDocument.CreateWhitespace(referenceSibling.XmlElement.PreviousSibling.Value);
                            XmlElement.InsertAfter(newWhitespaceNode, referenceSibling.XmlElement);
                        }
                    }
                }
                else if (TrySearchRightSiblings(child.NextSibling, siblingIsExplicitElement, out referenceSibling))
                {
                    //  Add as first child
                    XmlElement.InsertBefore(child.XmlElement, referenceSibling.XmlElement);

                    if (XmlDocument.PreserveWhitespace)
                    {
                        //  Try to match the surrounding formatting by checking the whitespace that precedes where we inserted
                        //  the new node, and inserting the same whitespace between the node we added and the one after it.
                        if (child.XmlElement.PreviousSibling != null &&
                            child.XmlElement.PreviousSibling.NodeType == XmlNodeType.Whitespace)
                        {
                            var newWhitespaceNode = XmlDocument.CreateWhitespace(child.XmlElement.PreviousSibling.Value);
                            XmlElement.InsertBefore(newWhitespaceNode, referenceSibling.XmlElement);
                        }
                    }
                }
                else
                {
                    //  Add as only child
                    XmlElement.AppendChild(child.XmlElement);

                    if (XmlDocument.PreserveWhitespace)
                    {
                        //  If the empty parent has whitespace in it, delete it
                        if (XmlElement.FirstChild.NodeType == XmlNodeType.Whitespace)
                        {
                            XmlElement.RemoveChild(XmlElement.FirstChild);
                        }

                        var parentIndentation = GetElementIndentation(XmlElement);

                        var leadingWhitespaceNode  = XmlDocument.CreateWhitespace(Environment.NewLine + parentIndentation + DEFAULT_INDENT);
                        var trailingWhiteSpaceNode = XmlDocument.CreateWhitespace(Environment.NewLine + parentIndentation);

                        XmlElement.InsertBefore(leadingWhitespaceNode, child.XmlElement);
                        XmlElement.InsertAfter(trailingWhiteSpaceNode, child.XmlElement);
                    }
                }
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Initializes a persisted target from an existing &lt;Target&gt; element which exists either in the main parent project
        /// file or one of the imported files.
        /// </summary>
        /// <param name="targetElement"></param>
        /// <param name="project"></param>
        /// <param name="importedFromAnotherProject"></param>
        internal Target
        (
            XmlElement targetElement,
            Project project,
            bool importedFromAnotherProject
        )
        {
            // Make sure a valid node has been given to us.
            error.VerifyThrow(targetElement != null, "Need a valid XML node.");

            // Make sure this really is the <target> node.
            ProjectXmlUtilities.VerifyThrowElementName(targetElement, XMakeElements.target);

            this.targetElement              = targetElement;
            this.parentProject              = project;
            this.parentEngine               = project.ParentEngine;
            this.conditionAttribute         = null;
            this.taskElementList            = null;
            this.importedFromAnotherProject = importedFromAnotherProject;
            this.buildState = BuildState.NotStarted;
            this.id         = project.ParentEngine.GetNextTargetId();

            // The target name and target dependendencies (dependencies on other
            // targets) are specified as attributes of the <target> element.

            XmlAttribute returnsAttribute = null;

            // Loop through all the attributes on the <target> element.
            foreach (XmlAttribute targetAttribute in targetElement.Attributes)
            {
                switch (targetAttribute.Name)
                {
                // Process the "condition" attribute.
                case XMakeAttributes.condition:
                    this.conditionAttribute = targetAttribute;
                    break;

                // Process the "name" attribute.
                case XMakeAttributes.name:
                    this.targetName = EscapingUtilities.UnescapeAll(targetAttribute.Value);

                    // Target names cannot contain MSBuild special characters, embedded properties,
                    // or item lists.
                    int indexOfSpecialCharacter = this.targetName.IndexOfAny(XMakeElements.illegalTargetNameCharacters);
                    if (indexOfSpecialCharacter >= 0)
                    {
                        ProjectErrorUtilities.VerifyThrowInvalidProject(false,
                                                                        targetAttribute, "NameInvalid", targetName, targetName[indexOfSpecialCharacter]);
                    }

                    break;

                // Process the "dependsOnTargets" attribute.
                case XMakeAttributes.dependsOnTargets:
                    this.dependsOnTargetsAttribute = targetAttribute;
                    break;

                case XMakeAttributes.inputs:
                    this.inputsAttribute           = targetAttribute;
                    recalculateBatchableParameters = true;
                    break;

                case XMakeAttributes.outputs:
                    this.outputsAttribute          = targetAttribute;
                    recalculateBatchableParameters = true;
                    break;

                // This is only recognized by the new OM:
                // so that the compat tests keep passing,
                // ignore it.
                case XMakeAttributes.keepDuplicateOutputs:
                    break;

                // This is only recognized by the new OM:
                // so that the compat tests keep passing,
                // ignore it.
                case XMakeAttributes.returns:
                    returnsAttribute = targetAttribute;
                    break;

                // These are only recognized by the new OM:
                // while the solution wrapper generator is using
                // the old OM to parse projects for dependencies,
                // we must make sure to not fail for these
                case XMakeAttributes.beforeTargets:
                case XMakeAttributes.afterTargets:
                    break;

                default:
                    ProjectXmlUtilities.ThrowProjectInvalidAttribute(targetAttribute);
                    break;
                }
            }

            // Hack to help the 3.5 engine at least pretend to still be able to build on top of
            // the 4.0 targets.  In cases where there is no Outputs attribute, just a Returns attribute,
            // we can approximate the correct behaviour by making the Returns attribute our "outputs" attribute.
            if (this.outputsAttribute == null && returnsAttribute != null)
            {
                this.outputsAttribute          = returnsAttribute;
                recalculateBatchableParameters = true;
            }

            // It's considered an error if a target does not have a name.
            ProjectErrorUtilities.VerifyThrowInvalidProject(!string.IsNullOrEmpty(targetName),
                                                            targetElement, "MissingRequiredAttribute", XMakeAttributes.name, XMakeElements.target);

            this.taskElementList = new ArrayList();

            // Process each of the child nodes beneath the <Target>.
            XmlElement        anyOnErrorElement = null;
            List <XmlElement> childElements     = ProjectXmlUtilities.GetValidChildElements(targetElement);

            foreach (XmlElement childElement in childElements)
            {
                bool onErrorOutOfOrder = false;
                switch (childElement.Name)
                {
                case XMakeElements.onError:
                    anyOnErrorElement = childElement;
                    break;

                default:
                    onErrorOutOfOrder = (anyOnErrorElement != null);
                    this.taskElementList.Add(new BuildTask(childElement,
                                                           this, this.importedFromAnotherProject));
                    break;
                }

                // Check for out-of-order OnError
                ProjectErrorUtilities.VerifyThrowInvalidProject(!onErrorOutOfOrder,
                                                                anyOnErrorElement, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name);
            }
        }
        /// <summary>
        /// Execute a PropertyGroup element, including each child property
        /// </summary>
        /// <param name="lookup">The lookup use for evaluation and as a destination for these properties.</param>
        internal override void ExecuteTask(Lookup lookup)
        {
            foreach (ProjectPropertyGroupTaskPropertyInstance property in _taskInstance.Properties)
            {
                List <ItemBucket> buckets = null;

                try
                {
                    // Find all the metadata references in order to create buckets
                    List <string> parameterValues = new List <string>();
                    GetBatchableValuesFromProperty(parameterValues, property);
                    buckets = BatchingEngine.PrepareBatchingBuckets(parameterValues, lookup, property.Location);

                    // "Execute" each bucket
                    foreach (ItemBucket bucket in buckets)
                    {
                        bool condition = ConditionEvaluator.EvaluateCondition
                                         (
                            property.Condition,
                            ParserOptions.AllowAll,
                            bucket.Expander,
                            ExpanderOptions.ExpandAll,
                            Project.Directory,
                            property.ConditionLocation,
                            LoggingContext.LoggingService,
                            LoggingContext.BuildEventContext
                                         );

                        if (condition)
                        {
                            // Check for a reserved name now, so it fails right here instead of later when the property eventually reaches
                            // the outer scope.
                            ProjectErrorUtilities.VerifyThrowInvalidProject
                            (
                                !ReservedPropertyNames.IsReservedProperty(property.Name),
                                property.Location,
                                "CannotModifyReservedProperty",
                                property.Name
                            );

                            string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(property.Value, ExpanderOptions.ExpandAll, property.Location);

                            if (LogTaskInputs && !LoggingContext.LoggingService.OnlyLogCriticalEvents)
                            {
                                LoggingContext.LogComment(MessageImportance.Low, "PropertyGroupLogMessage", property.Name, evaluatedValue);
                            }

                            bucket.Lookup.SetProperty(ProjectPropertyInstance.Create(property.Name, evaluatedValue, property.Location, Project.IsImmutable));
                        }
                    }
                }
                finally
                {
                    if (buckets != null)
                    {
                        // Propagate the property changes to the bucket above
                        foreach (ItemBucket bucket in buckets)
                        {
                            bucket.LeaveScope();
                        }
                    }
                }
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Evaluate node as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state)
        {
            if (String.Compare(_functionName, "exists", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("exists", (GenericExpressionNode)_arguments[0], state);

                if (String.IsNullOrEmpty(expandedValue))
                {
                    return(false);
                }

                try
                {
                    if (state.EvaluationDirectory != null && !Path.IsPathRooted(expandedValue))
                    {
                        expandedValue = Path.GetFullPath(Path.Combine(state.EvaluationDirectory, expandedValue));
                    }
                }
                catch (Exception e) when(ExceptionHandling.IsIoRelatedException(e))
                {
                    // Ignore invalid characters or path related exceptions

                    // We will ignore the PathTooLong exception caused by GetFullPath because in single proc this code
                    // is not executed and the condition is just evaluated to false as File.Exists and Directory.Exists does not throw in this situation.
                    // To be consistant with that we will return a false in this case also.
                    // DevDiv Bugs: 46035

                    return(false);
                }

                if (state.LoadedProjectsCache != null && state.LoadedProjectsCache.TryGet(expandedValue) != null)
                {
                    return(true);
                }

                bool exists = FileUtilities.FileOrDirectoryExistsNoThrow(expandedValue);

                return(exists);
            }
            else if (String.Compare(_functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("HasTrailingSlash", (GenericExpressionNode)_arguments[0], state);

                // Is the last character a backslash?
                if (expandedValue.Length != 0)
                {
                    char lastCharacter = expandedValue[expandedValue.Length - 1];
                    // Either back or forward slashes satisfy the function: this is useful for URL's
                    return(lastCharacter == Path.DirectorySeparatorChar || lastCharacter == Path.AltDirectorySeparatorChar);
                }
                else
                {
                    return(false);
                }
            }
            // We haven't implemented any other "functions"
            else
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(
                    false,
                    state.ElementLocation,
                    "UndefinedFunctionCall",
                    state.Condition,
                    _functionName);

                return(false);
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Constructor for the Choose object.  Parses the contents of the Choose
        /// and sets up list of When blocks
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <owner>DavidLe</owner>
        /// <param name="parentProject"></param>
        /// <param name="parentGroupingCollection"></param>
        /// <param name="chooseElement"></param>
        /// <param name="importedFromAnotherProject"></param>
        /// <param name="nestingDepth">stack overflow guard</param>
        internal Choose
        (
            Project parentProject,
            GroupingCollection parentGroupingCollection,
            XmlElement chooseElement,
            bool importedFromAnotherProject,
            int nestingDepth
        )
        {
            whenClauseList = new ArrayList();

            error.VerifyThrow(chooseElement != null, "Need valid <Choose> element.");

            // Make sure this really is the <Choose> node.
            ProjectXmlUtilities.VerifyThrowElementName(chooseElement, XMakeElements.choose);

            // Stack overflow guard. The only way in the MSBuild file format that MSBuild elements can be
            // legitimately nested without limit is the <Choose> construct. So, enforce a nesting limit
            // to avoid blowing our stack.
            nestingDepth++;
            ProjectErrorUtilities.VerifyThrowInvalidProject(nestingDepth <= maximumChooseNesting, chooseElement, "ChooseOverflow", maximumChooseNesting);

            this.importedFromAnotherProject = importedFromAnotherProject;

            // This <Choose> is coming from an existing XML element, so
            // walk through all the attributes and child elements, creating the
            // necessary When objects.

            // No attributes on the <Choose> element, so don't allow any.
            ProjectXmlUtilities.VerifyThrowProjectNoAttributes(chooseElement);

            bool foundOtherwise = false;

            // Loop through the child nodes of the <Choose> element.
            foreach (XmlNode chooseChildNode in chooseElement)
            {
                switch (chooseChildNode.NodeType)
                {
                // Handle XML comments under the <PropertyGroup> node (just ignore them).
                case XmlNodeType.Comment:
                // fall through
                case XmlNodeType.Whitespace:
                    // ignore whitespace
                    break;

                case XmlNodeType.Element:
                    // The only two types of child nodes that a <Choose> element can contain
                    // is are <When> elements and zero or one <Otherwise> elements.

                    ProjectXmlUtilities.VerifyThrowProjectValidNamespace((XmlElement)chooseChildNode);

                    if (chooseChildNode.Name == XMakeElements.when)
                    {
                        // don't allow <When> to follow <Otherwise>
                        ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise,
                                                                        chooseChildNode, "WhenNotAllowedAfterOtherwise");
                        When newWhen = new When(parentProject,
                                                parentGroupingCollection,
                                                (XmlElement)chooseChildNode,
                                                importedFromAnotherProject,
                                                When.Options.ProcessWhen,
                                                nestingDepth);
                        this.whenClauseList.Add(newWhen);
                    }
                    else if (chooseChildNode.Name == XMakeElements.otherwise)
                    {
                        ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise,
                                                                        chooseChildNode, "MultipleOtherwise");
                        When newWhen = new When(parentProject,
                                                parentGroupingCollection,
                                                (XmlElement)chooseChildNode,
                                                importedFromAnotherProject,
                                                When.Options.ProcessOtherwise,
                                                nestingDepth);
                        otherwiseClause = newWhen;
                        foundOtherwise  = true;
                    }
                    else
                    {
                        ProjectXmlUtilities.ThrowProjectInvalidChildElement(chooseChildNode);
                    }
                    break;

                default:
                    // Unrecognized child element.
                    ProjectXmlUtilities.ThrowProjectInvalidChildElement(chooseChildNode);
                    break;
                }
            }
            ProjectErrorUtilities.VerifyThrowInvalidProject(this.whenClauseList.Count != 0,
                                                            chooseElement, "ChooseMustContainWhen");
        }
Esempio n. 20
0
        /// <summary>
        /// Parse a ProjectUsingTaskElement
        /// </summary>
        private ProjectUsingTaskElement ParseProjectUsingTaskElement(XmlElementWithLocation element)
        {
            ProjectXmlUtilities.VerifyThrowProjectAttributes(element, ValidAttributesOnUsingTask);
            ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(XMakeAttributes.taskName).Length > 0, element.Location, "ProjectTaskNameEmpty");

            string assemblyName = element.GetAttribute(XMakeAttributes.assemblyName);
            string assemblyFile = element.GetAttribute(XMakeAttributes.assemblyFile);

            ProjectErrorUtilities.VerifyThrowInvalidProject
            (
                (assemblyName.Length > 0) ^ (assemblyFile.Length > 0),
                element.Location,
                "UsingTaskAssemblySpecification",
                XMakeElements.usingTask,
                XMakeAttributes.assemblyName,
                XMakeAttributes.assemblyFile
            );

            ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.assemblyName);
            ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, XMakeAttributes.assemblyFile);

            ProjectUsingTaskElement usingTask = new ProjectUsingTaskElement(element, _project, _project);

            bool foundTaskElement    = false;
            bool foundParameterGroup = false;

            foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element))
            {
                ProjectElement child            = null;
                string         childElementName = childElement.Name;
                switch (childElementName)
                {
                case XMakeElements.usingTaskParameterGroup:
                    if (foundParameterGroup)
                    {
                        ProjectXmlUtilities.ThrowProjectInvalidChildElementDueToDuplicate(childElement);
                    }

                    child = ParseUsingTaskParameterGroupElement(childElement, usingTask);
                    foundParameterGroup = true;
                    break;

                case XMakeElements.usingTaskBody:
                    if (foundTaskElement)
                    {
                        ProjectXmlUtilities.ThrowProjectInvalidChildElementDueToDuplicate(childElement);
                    }

                    ProjectXmlUtilities.VerifyThrowProjectAttributes(childElement, ValidAttributesOnUsingTaskBody);

                    child            = new ProjectUsingTaskBodyElement(childElement, usingTask, _project);
                    foundTaskElement = true;
                    break;

                default:
                    ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element.Location);
                    break;
                }

                usingTask.AppendParentedChildNoChecks(child);
            }

            return(usingTask);
        }
Esempio n. 21
0
        private GenericExpressionNode Factor(string expression)
        {
            // Checks for TokenTypes String, Numeric, Property, ItemMetadata, and ItemList.
            GenericExpressionNode arg = this.Arg(expression);

            // If it's one of those, return it.
            if (arg != null)
            {
                return(arg);
            }

            // If it's not one of those, check for other TokenTypes.
            Token current = lexer.CurrentToken;

            if (Same(expression, Token.TokenType.Function))
            {
                if (!Same(expression, Token.TokenType.LeftParenthesis))
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", lexer.IsNextString(), errorPosition);
                    return(null);
                }
                ArrayList arglist = new ArrayList();
                Arglist(expression, arglist);
                if (!Same(expression, Token.TokenType.RightParenthesis))
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                    return(null);
                }
                return(new FunctionCallExpressionNode(current.String, arglist));
            }
            else if (Same(expression, Token.TokenType.LeftParenthesis))
            {
                GenericExpressionNode child = Expr(expression);
                if (Same(expression, Token.TokenType.RightParenthesis))
                {
                    return(child);
                }
                else
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }
            }
            else if (Same(expression, Token.TokenType.Not))
            {
                OperatorExpressionNode notNode = new NotExpressionNode();
                GenericExpressionNode  expr    = Factor(expression);
                if (expr == null)
                {
                    errorPosition = lexer.GetErrorPosition();
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
                }
                notNode.LeftChild = expr;
                return(notNode);
            }
            else
            {
                errorPosition = lexer.GetErrorPosition();
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, this.conditionAttribute, "UnexpectedTokenInCondition", expression, lexer.IsNextString(), errorPosition);
            }
            return(null);
        }
Esempio n. 22
0
        /// <summary>
        /// Of all the item lists that are referenced in this batchable object, which ones should we
        /// batch on, and which ones should we just pass in wholesale to every invocation of the
        /// target/task?
        ///
        /// Rule #1.  If the user has referenced any *qualified* item metadata such as %(EmbeddedResource.Culture),
        /// then that item list "EmbeddedResource" will definitely get batched.
        ///
        /// Rule #2.  For all the unqualified item metadata such as %(Culture), we make sure that
        /// every single item in every single item list being passed into the task contains a value
        /// for that metadata.  If not, it's an error.  If so, we batch all of those item lists.
        ///
        /// All other item lists will not be batched, and instead will be passed in wholesale to all buckets.
        /// </summary>
        /// <returns>Hashtable containing the item names that should be batched.</returns>
        private static Hashtable GetItemListsToBeBatched
        (
            XmlNode parentNode,
            Dictionary <string, MetadataReference> consumedMetadataReferences, // Key is [string] potentially qualified metadata name
            // Value is [struct MetadataReference]
            Hashtable consumedItemReferenceNames,                              // Key is [string] item name.
            // Value is always String.Empty (unused).
            Lookup lookup
        )
        {
            // The keys in this hashtable are the names of the items that we will batch on.
            // The values are always String.Empty (not used).
            Hashtable itemListsToBeBatched = new Hashtable(StringComparer.OrdinalIgnoreCase);

            // Loop through all the metadata references and find the ones that are qualified
            // with an item name.
            foreach (MetadataReference consumedMetadataReference in consumedMetadataReferences.Values)
            {
                if (consumedMetadataReference.itemName != null)
                {
                    // Rule #1.  Qualified metadata reference.
                    // For metadata references that are qualified with an item name
                    // (e.g., %(EmbeddedResource.Culture) ), we add that item name to the list of
                    // consumed item names, even if the item name wasn't otherwise referenced via
                    // @(...) syntax, and even if every item in the list doesn't necessary contain
                    // a value for this metadata.  This is the special power that you get by qualifying
                    // the metadata reference with an item name.
                    itemListsToBeBatched[consumedMetadataReference.itemName] = String.Empty;

                    // Also add this qualified item to the consumed item references list, because
                    // %(EmbeddedResource.Culture) effectively means that @(EmbeddedResource) is
                    // being consumed, even though we may not see literally "@(EmbeddedResource)"
                    // in the tag anywhere.  Adding it to this list allows us (down below in this
                    // method) to check that every item in this list has a value for each
                    // unqualified metadata reference.
                    consumedItemReferenceNames = Utilities.CreateTableIfNecessary(consumedItemReferenceNames);
                    consumedItemReferenceNames[consumedMetadataReference.itemName] = String.Empty;
                }
            }

            // Loop through all the metadata references and find the ones that are unqualified.
            foreach (MetadataReference consumedMetadataReference in consumedMetadataReferences.Values)
            {
                if (consumedMetadataReference.itemName == null)
                {
                    // Rule #2.  Unqualified metadata reference.
                    // For metadata references that are unqualified, every single consumed item
                    // must contain a value for that metadata.  If any item doesn't, it's an error
                    // to use unqualified metadata.
                    if (consumedItemReferenceNames != null)
                    {
                        foreach (string consumedItemName in consumedItemReferenceNames.Keys)
                        {
                            // Loop through all the items in the item list.
                            BuildItemGroup items = lookup.GetItems(consumedItemName);

                            if (items != null)
                            {
                                // Loop through all the items in the BuildItemGroup.
                                foreach (BuildItem item in items)
                                {
                                    ProjectErrorUtilities.VerifyThrowInvalidProject(
                                        item.HasMetadata(consumedMetadataReference.metadataName),
                                        parentNode, "ItemDoesNotContainValueForUnqualifiedMetadata",
                                        item.Include, consumedItemName, consumedMetadataReference.metadataName);
                                }
                            }

                            // This item list passes the test of having every single item containing
                            // a value for this metadata.  Therefore, add this item list to the batching list.
                            // Also, to save doing lookup.GetItems again, put the items in the table as the value.
                            itemListsToBeBatched[consumedItemName] = items;
                        }
                    }
                }
            }

            return(itemListsToBeBatched);
        }
Esempio n. 23
0
        /// <summary>
        /// Evaluate node as boolean
        /// </summary>
        internal override bool BoolEvaluate(ConditionEvaluator.IConditionEvaluationState state)
        {
            if (String.Compare(_functionName, "exists", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                try
                {
                    // Expand the items and use DefaultIfEmpty in case there is nothing returned
                    // Then check if everything is not null (because the list was empty), not
                    // already loaded into the cache, and exists
                    List <string> list = ExpandArgumentAsFileList(_arguments[0], state);
                    if (list == null)
                    {
                        return(false);
                    }

                    foreach (var item in list)
                    {
                        if (item == null || !(state.LoadedProjectsCache?.TryGet(item) != null || FileUtilities.FileOrDirectoryExistsNoThrow(item, state.FileSystem)))
                        {
                            return(false);
                        }
                    }

                    return(true);
                }
                catch (Exception e) when(ExceptionHandling.IsIoRelatedException(e))
                {
                    // Ignore invalid characters or path related exceptions

                    // We will ignore the PathTooLong exception caused by GetFullPath because in single proc this code
                    // is not executed and the condition is just evaluated to false as File.Exists and Directory.Exists does not throw in this situation.
                    // To be consistant with that we will return a false in this case also.
                    // DevDiv Bugs: 46035

                    return(false);
                }
            }
            else if (String.Compare(_functionName, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase) == 0)
            {
                // Check we only have one argument
                VerifyArgumentCount(1, state);

                // Expand properties and items, and verify the result is an appropriate scalar
                string expandedValue = ExpandArgumentForScalarParameter("HasTrailingSlash", _arguments[0], state);

                // Is the last character a backslash?
                if (expandedValue.Length != 0)
                {
                    char lastCharacter = expandedValue[expandedValue.Length - 1];
                    // Either back or forward slashes satisfy the function: this is useful for URL's
                    return(lastCharacter == Path.DirectorySeparatorChar || lastCharacter == Path.AltDirectorySeparatorChar || lastCharacter == '\\');
                }
                else
                {
                    return(false);
                }
            }
            // We haven't implemented any other "functions"
            else
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(
                    false,
                    state.ElementLocation,
                    "UndefinedFunctionCall",
                    state.Condition,
                    _functionName);

                return(false);
            }
        }
        /// <summary>
        /// Parses the project into the ProjectRootElement
        /// </summary>
        private void Parse()
        {
            // XML guarantees exactly one root element
            XmlElementWithLocation element = _document.DocumentElement as XmlElementWithLocation;

            ProjectErrorUtilities.VerifyThrowInvalidProject(element != null, ElementLocation.Create(_document.FullPath), "NoRootProjectElement", XMakeElements.project);
            ProjectErrorUtilities.VerifyThrowInvalidProject(element.Name != XMakeElements.visualStudioProject, element.Location, "ProjectUpgradeNeeded", _project.FullPath);
            ProjectErrorUtilities.VerifyThrowInvalidProject(element.LocalName == XMakeElements.project, element.Location, "UnrecognizedElement", element.Name);

            // If a namespace was specified it must be the default MSBuild namespace.
            if (!ProjectXmlUtilities.VerifyValidProjectNamespace(element))
            {
                ProjectErrorUtilities.ThrowInvalidProject(element.Location, "ProjectMustBeInMSBuildXmlNamespace",
                                                          XMakeAttributes.defaultXmlNamespace);
            }
            else
            {
                _project.XmlNamespace = element.NamespaceURI;
            }

            // Historically, we allow any attribute on the Project element

            // The element wasn't available to the ProjectRootElement constructor so we have to set it now
            _project.SetProjectRootElementFromParser(element, _project);

            foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element))
            {
                switch (childElement.Name)
                {
                case XMakeElements.propertyGroup:
                    _project.AppendParentedChildNoChecks(ParseProjectPropertyGroupElement(childElement, _project));
                    break;

                case XMakeElements.itemGroup:
                    _project.AppendParentedChildNoChecks(ParseProjectItemGroupElement(childElement, _project));
                    break;

                case XMakeElements.importGroup:
                    _project.AppendParentedChildNoChecks(ParseProjectImportGroupElement(childElement, _project));
                    break;

                case XMakeElements.import:
                    _project.AppendParentedChildNoChecks(ParseProjectImportElement(childElement, _project));
                    break;

                case XMakeElements.usingTask:
                    _project.AppendParentedChildNoChecks(ParseProjectUsingTaskElement(childElement));
                    break;

                case XMakeElements.target:
                    _project.AppendParentedChildNoChecks(ParseProjectTargetElement(childElement));
                    break;

                case XMakeElements.itemDefinitionGroup:
                    _project.AppendParentedChildNoChecks(ParseProjectItemDefinitionGroupElement(childElement));
                    break;

                case XMakeElements.choose:
                    _project.AppendParentedChildNoChecks(ParseProjectChooseElement(childElement, _project, 0 /* nesting depth */));
                    break;

                case XMakeElements.projectExtensions:
                    _project.AppendParentedChildNoChecks(ParseProjectExtensionsElement(childElement));
                    break;

                case XMakeElements.sdk:
                    _project.AppendParentedChildNoChecks(ParseProjectSdkElement(childElement));
                    break;

                // Obsolete
                case XMakeElements.error:
                case XMakeElements.warning:
                case XMakeElements.message:
                    ProjectErrorUtilities.ThrowInvalidProject(childElement.Location, "ErrorWarningMessageNotSupported", childElement.Name);
                    break;

                default:
                    ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, childElement.ParentNode.Name, childElement.Location);
                    break;
                }
            }
        }
Esempio n. 25
0
        /// <summary>
        /// Used to load information about default MSBuild tasks i.e. tasks that do not need to be explicitly declared in projects
        /// with the &lt;UsingTask&gt; element. Default task information is read from special files, which are located in the same
        /// directory as the MSBuild binaries.
        /// </summary>
        /// <remarks>
        /// 1) a default tasks file needs the &lt;Project&gt; root tag in order to be well-formed
        /// 2) the XML declaration tag &lt;?xml ...&gt; is ignored
        /// 3) comment tags are always ignored regardless of their placement
        /// 4) the rest of the tags are expected to be &lt;UsingTask&gt; tags
        /// </remarks>
        private void RegisterDefaultTasks(BuildEventContext buildEventContext)
        {
            if (!defaultTasksRegistrationAttempted)
            {
                try
                {
                    this.defaultTaskRegistry = new TaskRegistry();

                    string[] defaultTasksFiles = { };

                    try
                    {
                        defaultTasksFiles = getFiles(toolset.ToolsPath, defaultTasksFilePattern);

                        if (defaultTasksFiles.Length == 0)
                        {
                            loggingServices.LogWarning(buildEventContext, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty),
                                                       "DefaultTasksFileLoadFailureWarning",
                                                       defaultTasksFilePattern, toolset.ToolsPath, String.Empty);
                        }
                    }
                    // handle security problems when finding the default tasks files
                    catch (UnauthorizedAccessException e)
                    {
                        loggingServices.LogWarning(buildEventContext, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty),
                                                   "DefaultTasksFileLoadFailureWarning",
                                                   defaultTasksFilePattern, toolset.ToolsPath, e.Message);
                    }
                    // handle problems when reading the default tasks files
                    catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception.
                    {
                        if (ExceptionHandling.NotExpectedException(e))
                        {
                            throw;
                        }

                        loggingServices.LogWarning(buildEventContext, new BuildEventFileInfo(/* this warning truly does not involve any file */ String.Empty),
                                                   "DefaultTasksFileLoadFailureWarning",
                                                   defaultTasksFilePattern, toolset.ToolsPath, e.Message);
                    }

                    BuildPropertyGroup propertyBag = null;

                    foreach (string defaultTasksFile in defaultTasksFiles)
                    {
                        try
                        {
                            XmlDocument defaultTasks = loadXmlFromPath(defaultTasksFile);

                            // look for the first root tag that is not a comment or an XML declaration -- this should be the <Project> tag
                            // NOTE: the XML parser will guarantee there is only one real root element in the file
                            // but we need to find it amongst the other types of XmlNode at the root.
                            foreach (XmlNode topLevelNode in defaultTasks.ChildNodes)
                            {
                                if (XmlUtilities.IsXmlRootElement(topLevelNode))
                                {
                                    ProjectErrorUtilities.VerifyThrowInvalidProject(topLevelNode.LocalName == XMakeElements.project,
                                                                                    topLevelNode, "UnrecognizedElement", topLevelNode.Name);

                                    ProjectErrorUtilities.VerifyThrowInvalidProject((topLevelNode.Prefix.Length == 0) && (String.Compare(topLevelNode.NamespaceURI, XMakeAttributes.defaultXmlNamespace, StringComparison.OrdinalIgnoreCase) == 0),
                                                                                    topLevelNode, "ProjectMustBeInMSBuildXmlNamespace", XMakeAttributes.defaultXmlNamespace);

                                    // the <Project> tag can only the XML namespace -- no other attributes
                                    foreach (XmlAttribute projectAttribute in topLevelNode.Attributes)
                                    {
                                        ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(projectAttribute.Name == XMakeAttributes.xmlns, projectAttribute);
                                    }

                                    // look at all the child tags of the <Project> root tag we found
                                    foreach (XmlNode usingTaskNode in topLevelNode.ChildNodes)
                                    {
                                        if (usingTaskNode.NodeType != XmlNodeType.Comment)
                                        {
                                            ProjectErrorUtilities.VerifyThrowInvalidProject(usingTaskNode.Name == XMakeElements.usingTask,
                                                                                            usingTaskNode, "UnrecognizedElement", usingTaskNode.Name);

                                            // Initialize the property bag if it hasn't been already.
                                            if (propertyBag == null)
                                            {
                                                // Set the value of the MSBuildBinPath/ToolsPath properties.
                                                BuildPropertyGroup reservedPropertyBag = new BuildPropertyGroup();

                                                reservedPropertyBag.SetProperty(
                                                    new BuildProperty(ReservedPropertyNames.binPath, EscapingUtilities.Escape(toolset.ToolsPath),
                                                                      PropertyType.ReservedProperty));

                                                reservedPropertyBag.SetProperty(
                                                    new BuildProperty(ReservedPropertyNames.toolsPath, EscapingUtilities.Escape(toolset.ToolsPath),
                                                                      PropertyType.ReservedProperty));

                                                // Also set MSBuildAssemblyVersion so that the tasks file can tell between v4 and v12 MSBuild
                                                reservedPropertyBag.SetProperty(
                                                    new BuildProperty(ReservedPropertyNames.assemblyVersion, Constants.AssemblyVersion,
                                                                      PropertyType.ReservedProperty));

                                                propertyBag = new BuildPropertyGroup();
                                                propertyBag.ImportInitialProperties(parentEngine.EnvironmentProperties, reservedPropertyBag, BuildProperties, parentEngine.GlobalProperties);
                                            }

                                            defaultTaskRegistry.RegisterTask(new UsingTask((XmlElement)usingTaskNode, true), new Expander(propertyBag), loggingServices, buildEventContext);
                                        }
                                    }

                                    break;
                                }
                            }
                        }
                        // handle security problems when loading the default tasks file
                        catch (UnauthorizedAccessException e)
                        {
                            loggingServices.LogError(buildEventContext, new BuildEventFileInfo(defaultTasksFile), "DefaultTasksFileFailure", e.Message);
                            break;
                        }
                        // handle problems when loading the default tasks file
                        catch (IOException e)
                        {
                            loggingServices.LogError(buildEventContext, new BuildEventFileInfo(defaultTasksFile), "DefaultTasksFileFailure", e.Message);
                            break;
                        }
                        // handle XML errors in the default tasks file
                        catch (XmlException e)
                        {
                            ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, new BuildEventFileInfo(e),
                                                                                    "DefaultTasksFileFailure", e.Message);
                        }
                    }
                }
                finally
                {
                    defaultTasksRegistrationAttempted = true;
                }
            }
        }