Beispiel #1
0
        /// <summary>
        /// Changes the item type of this item.
        /// Until reevaluation puts it in the correct place, it will be placed at
        /// the end of the list of items of its new type.
        /// </summary>
        /// <remarks>
        /// This is a little involved, as it requires replacing
        /// the XmlElement, and updating the project's datastructures.
        /// </remarks>
        internal void ChangeItemType(string newItemType)
        {
            ErrorUtilities.VerifyThrowArgumentLength(newItemType, "ItemType");
            Project.VerifyThrowInvalidOperationNotImported(_xml.ContainingProject);
            ErrorUtilities.VerifyThrowInvalidOperation(_xml.Parent != null && _xml.Parent.Parent != null, "OM_ObjectIsNoLongerActive");

            if (String.Equals(ItemType, newItemType, StringComparison.Ordinal))
            {
                return;
            }

            _project.SplitItemElementIfNecessary(_xml);

            _project.RemoveItemBeforeItemTypeChange(this);

            // xml.ChangeItemType will throw if new item type is invalid. Make sure we re-add the item anyway
            try
            {
                _xml.ChangeItemType(newItemType);
            }
            finally
            {
                _project.ReAddExistingItemAfterItemTypeChange(this);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Renames the item.
        /// Equivalent to setting the <see cref="UnevaluatedInclude"/> value.
        /// Generally, no expansion occurs. This is because it would potentially result in several items,
        /// which is not meaningful semantics when renaming a single item.
        /// However if the item does not need to be split (which would invalidate its ProjectItemElement),
        /// and the new value expands to exactly one item, then its evaluated include is updated
        /// with the expanded value, rather than the unexpanded value.
        /// </summary>
        /// <remarks>
        /// Even if the new value expands to zero items, we do not expand it.
        /// The common case we are interested in for expansion here is setting something
        /// like "$(sourcesroot)\foo.cs" and expanding that to a single item.
        /// If say "@(foo)" is set as the new name, and it expands to blank, that might
        /// be surprising to the host and maybe even unhandled, if on full reevaluation
        /// it wouldn’t expand to blank. That’s why we're being cautious and supporting
        /// the most common scenario only.
        /// Many hosts will do a ReevaluateIfNecessary before reading anyway.
        /// </remarks>
        public void Rename(string name)
        {
            Project.VerifyThrowInvalidOperationNotImported(_xml.ContainingProject);
            ErrorUtilities.VerifyThrowInvalidOperation(_xml.Parent != null && _xml.Parent.Parent != null, "OM_ObjectIsNoLongerActive");

            if (String.Equals(UnevaluatedInclude, name, StringComparison.Ordinal))
            {
                return;
            }

            _fullPath = null; // Clear cached value

            if (_xml.Count == 0 /* no metadata */ && _project.IsSuitableExistingItemXml(_xml, name, null /* no metadata */) && !FileMatcher.HasWildcardsSemicolonItemOrPropertyReferences(name))
            {
                _evaluatedIncludeEscaped = name;

                // Fast item lookup tables are invalid now.
                // Make sure that when the caller invokes ReevaluateIfNecessary() that they'll be refreshed.
                Project.MarkDirty();
                return;
            }

            bool splitOccurred = _project.SplitItemElementIfNecessary(_xml);

            _xml.Include = name;

            if (splitOccurred)
            {
                _evaluatedIncludeEscaped = name;
            }
            else
            {
                _evaluatedIncludeEscaped = _project.ExpandItemIncludeBestEffortLeaveEscaped(_xml);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Removes any metadata with the specified name.
        /// Returns true if the evaluated metadata existed, otherwise false.
        /// If the metadata name is one of the built-in metadata, like "FullPath", throws InvalidArgumentException.
        /// If the metadata originates in an item definition, and was not overridden, throws InvalidOperationException.
        /// </summary>
        public bool RemoveMetadata(string name)
        {
            ErrorUtilities.VerifyThrowArgumentLength(name, "name");
            ErrorUtilities.VerifyThrowArgument(!FileUtilities.ItemSpecModifiers.IsItemSpecModifier(name), "ItemSpecModifierCannotBeCustomMetadata", name);
            Project.VerifyThrowInvalidOperationNotImported(_xml.ContainingProject);
            ErrorUtilities.VerifyThrowInvalidOperation(_xml.Parent != null && _xml.Parent.Parent != null, "OM_ObjectIsNoLongerActive");

            ProjectMetadata metadatum = (_directMetadata == null) ? null : _directMetadata[name];

            if (metadatum == null)
            {
                ProjectMetadata itemDefinitionMetadata = GetItemDefinitionMetadata(name);
                ErrorUtilities.VerifyThrowInvalidOperation(itemDefinitionMetadata == null, "OM_CannotRemoveMetadataOriginatingFromItemDefinition", name);
                return(false);
            }

            _project.SplitItemElementIfNecessary(_xml);

            // New metadata objects may have been created
            metadatum = _directMetadata[name];

            _xml.RemoveChild(metadatum.Xml);
            _directMetadata.Remove(name);

            return(true);
        }
Beispiel #4
0
        private ProjectMetadata SetMetadataOperation(string name, string unevaluatedValue, bool propagateMetadataToSiblingItems)
        {
            Project.VerifyThrowInvalidOperationNotImported(_xml.ContainingProject);

            XmlUtilities.VerifyThrowArgumentValidElementName(name);
            ErrorUtilities.VerifyThrowArgument(!FileUtilities.ItemSpecModifiers.IsItemSpecModifier(name), "ItemSpecModifierCannotBeCustomMetadata", name);
            ErrorUtilities.VerifyThrowInvalidOperation(!XMakeElements.ReservedItemNames.Contains(name), "CannotModifyReservedItemMetadata", name);
            ErrorUtilities.VerifyThrowInvalidOperation(_xml.Parent != null && _xml.Parent.Parent != null, "OM_ObjectIsNoLongerActive");

            if (!propagateMetadataToSiblingItems)
            {
                _project.SplitItemElementIfNecessary(_xml);
            }

            ProjectMetadata metadatum;

            if (_directMetadata != null && _directMetadata.Contains(name))
            {
                metadatum = _directMetadata[name];
                metadatum.UnevaluatedValue = unevaluatedValue;
            }
            else
            {
                ProjectMetadataElement metadatumXml = _xml.AddMetadata(name, unevaluatedValue);

                string evaluatedValueEscaped = _project.ExpandMetadataValueBestEffortLeaveEscaped(this, unevaluatedValue, metadatumXml.Location);

                metadatum = new ProjectMetadata(this, metadatumXml, evaluatedValueEscaped, null /* predecessor unknown */);
            }

            if (!propagateMetadataToSiblingItems)
            {
                _directMetadata = _directMetadata ?? new PropertyDictionary <ProjectMetadata>();
                _directMetadata.Set(metadatum);
            }
            else
            {
                var siblingItems = _project.Items.Where(i => i._xml == _xml);

                foreach (var siblingItem in siblingItems)
                {
                    siblingItem._directMetadata = siblingItem._directMetadata ?? new PropertyDictionary <ProjectMetadata>();
                    siblingItem._directMetadata.Set(metadatum.DeepClone());
                }
            }

            return(metadatum);
        }
Beispiel #5
0
        /// <summary>
        /// Sets a new metadata value on the ItemDefinition.
        /// </summary>
        /// <remarks>Unevaluated value is assumed to be escaped as necessary</remarks>
        public ProjectMetadata SetMetadataValue(string name, string unevaluatedValue)
        {
            if (Link != null)
            {
                return(Link.SetMetadataValue(name, unevaluatedValue));
            }

            XmlUtilities.VerifyThrowArgumentValidElementName(name);
            ErrorUtilities.VerifyThrowArgument(!FileUtilities.ItemSpecModifiers.IsItemSpecModifier(name), "ItemSpecModifierCannotBeCustomMetadata", name);
            ErrorUtilities.VerifyThrowInvalidOperation(!XMakeElements.ReservedItemNames.Contains(name), "CannotModifyReservedItemMetadata", name);

            ProjectMetadata metadatum;

            if (_metadata != null)
            {
                metadatum = _metadata[name];

                if (metadatum != null)
                {
                    Project.VerifyThrowInvalidOperationNotImported(metadatum.Xml.ContainingProject);
                    metadatum.UnevaluatedValue = unevaluatedValue;
                    return(metadatum);
                }
            }

            // We can't use the item definition that this object came from as a root, as it doesn't map directly
            // to a single XML element. Instead, add a new one to the project. Best we can do.
            ProjectItemDefinitionElement itemDefinition = _project.Xml.AddItemDefinition(_itemType);

            ProjectMetadataElement metadatumXml = itemDefinition.AddMetadata(name, unevaluatedValue);

            _metadata = _metadata ?? new PropertyDictionary <ProjectMetadata>();

            string evaluatedValueEscaped = _project.ExpandMetadataValueBestEffortLeaveEscaped(this, unevaluatedValue, metadatumXml.Location);

            metadatum = new ProjectMetadata(this, metadatumXml, evaluatedValueEscaped, null /* predecessor unknown */);

            _metadata.Set(metadatum);

            return(metadatum);
        }
Beispiel #6
0
        /// <summary>
        /// Adds metadata with the specified name and value to the item.
        /// Updates an existing metadata if one already exists with the same name on the item directly, as opposed to inherited from an item definition.
        /// Updates the evaluated project, but does not affect anything else in the project until reevaluation. For example,
        /// if a piece of metadata named "m" is added on item of type "i", it does not affect "j" which is evaluated from "@(j->'%(m)')" until reevaluation.
        /// Also if the unevaluated value of "m" is set to something that is modified by evaluation, such as "$(p)", the evaluated value will be set to literally "$(p)" until reevaluation.
        /// This is a convenience that it is understood does not necessarily leave the project in a perfectly self consistent state.
        /// Returns the new or existing metadatum.
        /// </summary>
        /// <remarks>Unevaluated value is assumed to be escaped as necessary</remarks>
        public ProjectMetadata SetMetadataValue(string name, string unevaluatedValue)
        {
            Project.VerifyThrowInvalidOperationNotImported(_xml.ContainingProject);

            XmlUtilities.VerifyThrowArgumentValidElementName(name);
            ErrorUtilities.VerifyThrowArgument(!FileUtilities.ItemSpecModifiers.IsItemSpecModifier(name), "ItemSpecModifierCannotBeCustomMetadata", name);
            ErrorUtilities.VerifyThrowInvalidOperation(XMakeElements.IllegalItemPropertyNames[name] == null, "CannotModifyReservedItemMetadata", name);
            ErrorUtilities.VerifyThrowInvalidOperation(_xml.Parent != null && _xml.Parent.Parent != null, "OM_ObjectIsNoLongerActive");

            _project.SplitItemElementIfNecessary(_xml);

            ProjectMetadata metadatum;

            if (_directMetadata != null)
            {
                metadatum = _directMetadata[name];

                if (metadatum != null)
                {
                    metadatum.UnevaluatedValue = unevaluatedValue;
                    return(metadatum);
                }
            }

            ProjectMetadataElement metadatumXml = _xml.AddMetadata(name, unevaluatedValue);

            _directMetadata = _directMetadata ?? new PropertyDictionary <ProjectMetadata>();

            string evaluatedValueEscaped = _project.ExpandMetadataValueBestEffortLeaveEscaped(this, unevaluatedValue, metadatumXml.Location);

            metadatum = new ProjectMetadata(this, metadatumXml, evaluatedValueEscaped, null /* predecessor unknown */);

            _directMetadata.Set(metadatum);

            return(metadatum);
        }