|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
#nullable disable
namespace Microsoft.Build.Construction
{
/// <summary>
/// ProjectItemDefinitionElement class represents the Item Definition element in the MSBuild project.
/// </summary>
[DebuggerDisplay("{ItemType} #Metadata={Count} Condition={Condition}")]
public class ProjectItemDefinitionElement : ProjectElementContainer
{
/// <summary>
/// External projects support
/// </summary>
internal ProjectItemDefinitionElement(ProjectItemDefinitionElementLink link)
: base(link)
{
}
/// <summary>
/// Initialize a ProjectItemDefinitionElement instance from a node read from a project file
/// </summary>
internal ProjectItemDefinitionElement(XmlElement xmlElement, ProjectItemDefinitionGroupElement parent, ProjectRootElement containingProject)
: base(xmlElement, parent, containingProject)
{
ErrorUtilities.VerifyThrowArgumentNull(parent);
}
/// <summary>
/// Initialize a ProjectItemDefinitionElement instance from a node read from a project file
/// </summary>
private ProjectItemDefinitionElement(XmlElement xmlElement, ProjectRootElement containingProject)
: base(xmlElement, null, containingProject)
{
}
/// <summary>
/// Gets the definition's type.
/// </summary>
public string ItemType => ElementName;
/// <summary>
/// Get any child metadata definitions.
/// </summary>
public ICollection<ProjectMetadataElement> Metadata => GetChildrenOfType<ProjectMetadataElement>();
/// <summary>
/// Convenience method to add a piece of metadata to this item definition.
/// Adds after any existing metadata. Does not modify any existing metadata.
/// </summary>
public ProjectMetadataElement AddMetadata(string name, string unevaluatedValue)
{
return AddMetadata(name, unevaluatedValue, false);
}
/// <summary>
/// Convenience method to add a piece of metadata to this item definition.
/// Adds after any existing metadata. Does not modify any existing metadata.
/// </summary>
/// <param name="name">The name of the metadata to add</param>
/// <param name="unevaluatedValue">The value of the metadata to add</param>
/// <param name="expressAsAttribute">If true, then the metadata will be expressed as an attribute instead of a child element, for example
/// <Content CopyToOutputDirectory="PreserveNewest" />
/// </param>
public ProjectMetadataElement AddMetadata(string name, string unevaluatedValue, bool expressAsAttribute)
{
ErrorUtilities.VerifyThrowArgumentLength(name);
ErrorUtilities.VerifyThrowArgumentNull(unevaluatedValue);
if (expressAsAttribute)
{
ProjectMetadataElement.ValidateValidMetadataAsAttributeName(name, ElementName, Location);
}
ProjectMetadataElement metadata = ContainingProject.CreateMetadataElement(name);
metadata.Value = unevaluatedValue;
metadata.ExpressedAsAttribute = expressAsAttribute;
AppendChild(metadata);
return metadata;
}
/// <summary>
/// Creates an unparented ProjectItemDefinitionElement, wrapping an unparented XmlElement.
/// Caller should then ensure the element is added to a parent.
/// </summary>
internal static ProjectItemDefinitionElement CreateDisconnected(string itemType, ProjectRootElement containingProject)
{
XmlUtilities.VerifyThrowArgumentValidElementName(itemType);
// Orcas inadvertently did not check for reserved item types (like "Choose") in item definitions,
// as we do for item types in item groups. So we do not have a check here.
// Although we could perhaps add one, as such item definitions couldn't be used
// since no items can have the reserved itemType.
XmlElementWithLocation element = containingProject.CreateElement(itemType);
return new ProjectItemDefinitionElement(element, containingProject);
}
/// <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 ProjectItemDefinitionGroupElement, "OM_CannotAcceptParent");
}
/// <inheritdoc />
protected override ProjectElement CreateNewInstance(ProjectRootElement owner)
{
return owner.CreateItemDefinitionElement(ItemType);
}
/// <summary>
/// Do not clone attributes which can be metadata. The corresponding expressed as attribute project elements are responsible for adding their attribute
/// </summary>
protected override bool ShouldCloneXmlAttribute(XmlAttribute attribute) => !ProjectMetadataElement.AttributeNameIsValidMetadataName(attribute.LocalName);
internal override bool ShouldCloneXmlAttribute(XmlAttributeLink attributeLink) => !ProjectMetadataElement.AttributeNameIsValidMetadataName(attributeLink.LocalName);
}
}
|