| File: Construction\ProjectPropertyElement.cs | Web Access |
| Project: src\msbuild\src\Build\Microsoft.Build.csproj (Microsoft.Build) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using Microsoft.Build.Execution; using Microsoft.Build.Internal; using Microsoft.Build.ObjectModelRemoting; using Microsoft.Build.Shared; #nullable disable namespace Microsoft.Build.Construction { /// <summary> /// ProjectPropertyElement class represents the Property element in the MSBuild project. /// </summary> /// <remarks> /// We do not need to use or set the PropertyType enumeration in the CM. /// The CM does not know about Environment or Global properties, and does not create Output properties. /// We can just verify that we haven't read a PropertyType.Reserved property ourselves. /// So the CM only represents Normal properties. /// </remarks> [DebuggerDisplay("{Name} Value={Value} Condition={Condition}")] public class ProjectPropertyElement : ProjectElement, IPropertyElementWithLocation { internal ProjectPropertyElementLink PropertyLink => (ProjectPropertyElementLink)Link; /// <summary> /// External projects support /// </summary> internal ProjectPropertyElement(ProjectPropertyElementLink link) : base(link) { } /// <summary> /// Initialize a parented ProjectPropertyElement /// </summary> internal ProjectPropertyElement(XmlElementWithLocation xmlElement, ProjectPropertyGroupElement parent, ProjectRootElement containingProject) : base(xmlElement, parent, containingProject) { ArgumentNullException.ThrowIfNull(parent); } /// <summary> /// Initialize an unparented ProjectPropertyElement /// </summary> private ProjectPropertyElement(XmlElementWithLocation xmlElement, ProjectRootElement containingProject) : base(xmlElement, null, containingProject) { } /// <summary> /// Gets or sets the property name. /// </summary> public string Name { get => ElementName; set => ChangeName(value); } /// <summary> /// Gets or sets the unevaluated value. /// Returns empty string if it is not present. /// </summary> public string Value { get => Link != null ? PropertyLink.Value : Internal.Utilities.GetXmlNodeInnerContents(XmlElement); set { ArgumentNullException.ThrowIfNull(value); if (Link != null) { PropertyLink.Value = value; return; } // Visual Studio has a tendency to set properties to their existing value. if (Value != value) { Internal.Utilities.SetXmlNodeInnerContents(XmlElement, value); MarkDirty("Set property Value {0}", value); } } } /// <summary> /// Creates an unparented ProjectPropertyElement, wrapping an unparented XmlElement. /// Validates name. /// Caller should then ensure the element is added to the XmlDocument in the appropriate location. /// </summary> internal static ProjectPropertyElement CreateDisconnected(string name, ProjectRootElement containingProject) { XmlUtilities.VerifyThrowArgumentValidElementName(name); ErrorUtilities.VerifyThrowInvalidOperation(!XMakeElements.ReservedItemNames.Contains(name) && !ReservedPropertyNames.IsReservedProperty(name), "OM_CannotCreateReservedProperty", name); XmlElementWithLocation element = containingProject.CreateElement(name); return new ProjectPropertyElement(element, containingProject); } /// <summary> /// Changes the name. /// </summary> /// <remarks> /// The implementation has to actually replace the element to do this. /// </remarks> internal void ChangeName(string newName) { ArgumentException.ThrowIfNullOrEmpty(newName); XmlUtilities.VerifyThrowArgumentValidElementName(newName); ErrorUtilities.VerifyThrowArgument(!XMakeElements.ReservedItemNames.Contains(newName), "CannotModifyReservedProperty", newName); if (Link != null) { PropertyLink.ChangeName(newName); return; } // Because the element was created from our special XmlDocument, we know it's // an XmlElementWithLocation. XmlElementWithLocation newElement = XmlUtilities.RenameXmlElement(XmlElement, newName, XmlElement.NamespaceURI); ReplaceElement(newElement); } /// <summary> /// Overridden to verify that the potential parent and siblings /// are acceptable. Throws InvalidOperationException if they are not. /// </summary> internal override void VerifyThrowInvalidOperationAcceptableLocation(ProjectElementContainer parent, ProjectElement previousSibling, ProjectElement nextSibling) { ErrorUtilities.VerifyThrowInvalidOperation(parent is ProjectPropertyGroupElement, "OM_CannotAcceptParent"); } /// <inheritdoc /> protected override ProjectElement CreateNewInstance(ProjectRootElement owner) { return owner.CreatePropertyElement(Name); } } }