| File: Construction\ProjectImportElement.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.Framework; using Microsoft.Build.ObjectModelRemoting; using Microsoft.Build.Shared; #nullable disable namespace Microsoft.Build.Construction { /// <summary> /// Initializes a ProjectImportElement instance. /// </summary> [DebuggerDisplay("Project={Project} Condition={Condition}")] public class ProjectImportElement : ProjectElement { internal ProjectImportElementLink ImportLink => (ProjectImportElementLink)Link; private ImplicitImportLocation _implicitImportLocation; private ProjectElement _originalElement; /// <summary> /// External projects support /// </summary> internal ProjectImportElement(ProjectImportElementLink link) : base(link) { } /// <summary> /// Initialize a parented ProjectImportElement /// </summary> internal ProjectImportElement(XmlElementWithLocation xmlElement, ProjectElementContainer parent, ProjectRootElement containingProject, SdkReference sdkReference = null) : base(xmlElement, parent, containingProject) { ArgumentNullException.ThrowIfNull(parent); SdkReference = sdkReference; } /// <summary> /// Initialize an unparented ProjectImportElement /// </summary> internal ProjectImportElement(XmlElementWithLocation xmlElement, ProjectRootElement containingProject) : base(xmlElement, null, containingProject) { } /// <summary> /// Gets or sets the Project value. /// </summary> public string Project { get => FileUtilities.FixFilePath(GetAttributeValue(XMakeAttributes.project)); set { ArgumentException.ThrowIfNullOrEmpty(value, XMakeAttributes.project); SetOrRemoveAttribute(XMakeAttributes.project, value, "Set Import Project {0}", value); } } /// <summary> /// Location of the project attribute /// </summary> public ElementLocation ProjectLocation => GetAttributeLocation(XMakeAttributes.project); /// <summary> /// Gets or sets the SDK that contains the import. /// </summary> public string Sdk { get => FileUtilities.FixFilePath(GetAttributeValue(XMakeAttributes.sdk)); set { ArgumentException.ThrowIfNullOrEmpty(value, XMakeAttributes.sdk); if (UpdateSdkReference(name: value, SdkReference?.Version, SdkReference?.MinimumVersion)) { SetOrRemoveAttribute(XMakeAttributes.sdk, value, "Set Import Sdk {0}", value); } } } /// <summary> /// Gets or sets the version associated with this SDK import /// </summary> public string Version { get => GetAttributeValue(XMakeAttributes.sdkVersion); set { if (UpdateSdkReference(SdkReference?.Name, version: value, SdkReference?.MinimumVersion)) { SetOrRemoveAttribute(XMakeAttributes.sdkVersion, value, "Set Import Version {0}", value); } } } /// <summary> /// Gets or sets the minimum SDK version required by this import. /// </summary> public string MinimumVersion { get => GetAttributeValue(XMakeAttributes.sdkMinimumVersion); set { if (UpdateSdkReference(SdkReference?.Name, SdkReference?.Version, minimumVersion: value)) { SetOrRemoveAttribute(XMakeAttributes.sdkMinimumVersion, value, "Set Import Minimum Version {0}", value); } } } /// <summary> /// Location of the Sdk attribute /// </summary> public ElementLocation SdkLocation => GetAttributeLocation(XMakeAttributes.sdk); /// <summary> /// Gets the <see cref="ImplicitImportLocation"/> of the import. This indicates if the import was implicitly /// added because of the <see cref="ProjectRootElement.Sdk"/> attribute and the location where the project was /// imported. /// </summary> public ImplicitImportLocation ImplicitImportLocation { get => Link != null ? ImportLink.ImplicitImportLocation : _implicitImportLocation; internal set => _implicitImportLocation = value; } /// <summary> /// If the import is an implicit one (<see cref="ImplicitImportLocation"/> != None) then this element points /// to the original element which generated this implicit import. /// </summary> public ProjectElement OriginalElement { get => Link != null ? ImportLink.OriginalElement : _originalElement; internal set => _originalElement = value; } /// <summary> /// <see cref="Framework.SdkReference"/> if applicable to this import element. /// </summary> internal SdkReference SdkReference { get; set; } /// <summary> /// Creates an unparented ProjectImportElement, wrapping an unparented XmlElement. /// Validates the project value. /// Caller should then ensure the element is added to a parent /// </summary> internal static ProjectImportElement CreateDisconnected(string project, ProjectRootElement containingProject) { XmlElementWithLocation element = containingProject.CreateElement(XMakeElements.import); return new ProjectImportElement(element, containingProject) { Project = project }; } /// <summary> /// Creates an implicit ProjectImportElement as if it was in the project. /// </summary> /// <returns></returns> internal static ProjectImportElement CreateImplicit( string project, ProjectRootElement containingProject, ImplicitImportLocation implicitImportLocation, SdkReference sdkReference, ProjectElement originalElement) { XmlElementWithLocation element = containingProject.CreateElement(XMakeElements.import); return new ProjectImportElement(element, containingProject) { Project = project, Sdk = sdkReference.ToString(), ImplicitImportLocation = implicitImportLocation, SdkReference = sdkReference, OriginalElement = originalElement }; } /// <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 ProjectRootElement || parent is ProjectImportGroupElement, "OM_CannotAcceptParent"); } /// <inheritdoc /> protected override ProjectElement CreateNewInstance(ProjectRootElement owner) { return owner.CreateImportElement(Project); } /// <summary> /// Helper method to update the <see cref="SdkReference" /> property if necessary (update only when changed). /// </summary> /// <returns>True if the <see cref="SdkReference" /> property was updated, otherwise false (no update necessary).</returns> private bool UpdateSdkReference(string name, string version, string minimumVersion) { SdkReference sdk = new SdkReference(name, version, minimumVersion); if (sdk.Equals(SdkReference)) { return false; } SdkReference = sdk; return true; } } }