File: BackEnd\BuildManager\BuildRequestData.cs
Web Access
Project: ..\..\..\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.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using Microsoft.Build.Collections;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Experimental.BuildCheck;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
 
namespace Microsoft.Build.Execution
{
    /// <summary>
    /// BuildRequestData encapsulates all the data needed to submit a build request.
    /// </summary>
    public class BuildRequestData : BuildRequestData<BuildRequestData, BuildResult>
    {
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project instances.
        /// </summary>
        /// <param name="projectInstance">The instance to build.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        public BuildRequestData(ProjectInstance projectInstance, string[] targetsToBuild)
            : this(projectInstance, targetsToBuild, null, BuildRequestDataFlags.None)
        {
        }
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project instances.
        /// </summary>
        /// <param name="projectInstance">The instance to build.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use, if any.  May be null.</param>
        public BuildRequestData(ProjectInstance projectInstance, string[] targetsToBuild, HostServices hostServices)
            : this(projectInstance, targetsToBuild, hostServices, BuildRequestDataFlags.None)
        {
        }
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project instances.
        /// </summary>
        /// <param name="projectInstance">The instance to build.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use, if any.  May be null.</param>
        /// <param name="flags">Flags controlling this build request.</param>
        public BuildRequestData(ProjectInstance projectInstance, string[] targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags)
            : this(projectInstance, targetsToBuild, hostServices, flags, null)
        {
        }
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project instances.
        /// </summary>
        /// <param name="projectInstance">The instance to build.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use, if any.  May be null.</param>
        /// <param name="flags">Flags controlling this build request.</param>
        /// <param name="propertiesToTransfer">The list of properties whose values should be transferred from the project to any out-of-proc node.</param>
        public BuildRequestData(ProjectInstance projectInstance, string[] targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags, IEnumerable<string>? propertiesToTransfer)
            : this(targetsToBuild, hostServices, flags, projectInstance.FullPath)
        {
            ErrorUtilities.VerifyThrowArgumentNull(projectInstance);
 
            foreach (string targetName in targetsToBuild)
            {
                ErrorUtilities.VerifyThrowArgumentNull(targetName, "target");
            }
 
            ProjectInstance = projectInstance;
 
            GlobalPropertiesDictionary = projectInstance.GlobalPropertiesDictionary;
            ExplicitlySpecifiedToolsVersion = projectInstance.ExplicitToolsVersion;
            if (propertiesToTransfer != null)
            {
                PropertiesToTransfer = new List<string>(propertiesToTransfer);
            }
        }
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project instances.
        /// </summary>
        /// <param name="projectInstance">The instance to build.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use, if any.  May be null.</param>
        /// <param name="flags">Flags controlling this build request.</param>
        /// <param name="propertiesToTransfer">The list of properties whose values should be transferred from the project to any out-of-proc node.</param>
        /// <param name="requestedProjectState">A <see cref="Execution.RequestedProjectState"/> describing properties, items, and metadata that should be returned. Requires setting <see cref="BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild"/>.</param>
        public BuildRequestData(ProjectInstance projectInstance, string[] targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags, IEnumerable<string>? propertiesToTransfer, RequestedProjectState requestedProjectState)
            : this(projectInstance, targetsToBuild, hostServices, flags, propertiesToTransfer)
        {
            ErrorUtilities.VerifyThrowArgumentNull(requestedProjectState);
 
            RequestedProjectState = requestedProjectState;
        }
 
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project files.
        /// </summary>
        /// <param name="projectFullPath">The full path to the project file.</param>
        /// <param name="globalProperties">The global properties which should be used during evaluation of the project.  Cannot be null.</param>
        /// <param name="toolsVersion">The tools version to use for the build.  May be null.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use.  May be null.</param>
        public BuildRequestData(string projectFullPath, IDictionary<string, string?> globalProperties, string? toolsVersion, string[] targetsToBuild, HostServices? hostServices)
            : this(projectFullPath, globalProperties, toolsVersion, targetsToBuild, hostServices, BuildRequestDataFlags.None)
        {
        }
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project files.
        /// </summary>
        /// <param name="projectFullPath">The full path to the project file.</param>
        /// <param name="globalProperties">The global properties which should be used during evaluation of the project.  Cannot be null.</param>
        /// <param name="toolsVersion">The tools version to use for the build.  May be null.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use.  May be null.</param>
        /// <param name="flags">The <see cref="BuildRequestDataFlags"/> to use.</param>
        /// <param name="requestedProjectState">A <see cref="Execution.RequestedProjectState"/> describing properties, items, and metadata that should be returned. Requires setting <see cref="BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild"/>.</param>
        public BuildRequestData(string projectFullPath, IDictionary<string, string?> globalProperties,
            string? toolsVersion, string[] targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags,
            RequestedProjectState requestedProjectState)
            : this(projectFullPath, globalProperties, toolsVersion, targetsToBuild, hostServices, flags)
        {
            ErrorUtilities.VerifyThrowArgumentNull(requestedProjectState);
 
            RequestedProjectState = requestedProjectState;
        }
 
        /// <summary>
        /// Constructs a BuildRequestData for build requests based on project files.
        /// </summary>
        /// <param name="projectFullPath">The full path to the project file.</param>
        /// <param name="globalProperties">The global properties which should be used during evaluation of the project.  Cannot be null.</param>
        /// <param name="toolsVersion">The tools version to use for the build.  May be null.</param>
        /// <param name="targetsToBuild">The targets to build.</param>
        /// <param name="hostServices">The host services to use.  May be null.</param>
        /// <param name="flags">The <see cref="BuildRequestDataFlags"/> to use.</param>
        public BuildRequestData(string projectFullPath, IDictionary<string, string?> globalProperties, string? toolsVersion, string[] targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags)
            : this(targetsToBuild, hostServices, flags, FileUtilities.NormalizePath(projectFullPath)!)
        {
            ErrorUtilities.VerifyThrowArgumentLength(projectFullPath);
            ErrorUtilities.VerifyThrowArgumentNull(globalProperties);
 
            GlobalPropertiesDictionary = new PropertyDictionary<ProjectPropertyInstance>(globalProperties.Count);
            foreach (KeyValuePair<string, string?> propertyPair in globalProperties)
            {
                GlobalPropertiesDictionary.Set(ProjectPropertyInstance.Create(propertyPair.Key, propertyPair.Value));
            }
 
            ExplicitlySpecifiedToolsVersion = toolsVersion;
        }
 
        /// <summary>
        /// Common constructor.
        /// </summary>
        private BuildRequestData(string[] targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags, string projectFullPath)
            : base(targetsToBuild, flags, hostServices)
        {
            ProjectFullPath = projectFullPath;
        }
 
        /// <summary>
        /// The actual project, in the case where the project doesn't come from disk.
        /// May be null.
        /// </summary>
        /// <value>The project instance.</value>
        public ProjectInstance? ProjectInstance
        {
            get;
        }
 
        /// <summary>The project file.</summary>
        /// <value>The project file to be built.</value>
        public string ProjectFullPath { get; internal set; }
 
        internal override BuildSubmissionBase<BuildRequestData, BuildResult> CreateSubmission(BuildManager buildManager,
            int submissionId, BuildRequestData requestData,
            bool legacyThreadingSemantics) =>
            new BuildSubmission(buildManager, submissionId, requestData, legacyThreadingSemantics);
 
        public override IEnumerable<string> EntryProjectsFullPath => ProjectFullPath.AsSingleItemEnumerable();
 
        /// <summary>
        /// The global properties to use.
        /// </summary>
        /// <value>The set of global properties to be used to build this request.</value>
        public ICollection<ProjectPropertyInstance> GlobalProperties => (GlobalPropertiesDictionary == null) ?
            (ICollection<ProjectPropertyInstance>)ReadOnlyEmptyCollection<ProjectPropertyInstance>.Instance :
            new ReadOnlyCollection<ProjectPropertyInstance>(GlobalPropertiesDictionary);
 
        public override bool IsGraphRequest => false;
 
        /// <summary>
        /// The explicitly requested tools version to use.
        /// </summary>
        public string? ExplicitlySpecifiedToolsVersion { get; }
 
        /// <summary>
        /// Returns a list of properties to transfer out of proc for the build.
        /// </summary>
        public IEnumerable<string>? PropertiesToTransfer { get; }
 
        /// <summary>
        /// Returns the properties, items, and metadata that will be returned
        /// by this build.
        /// </summary>
        public RequestedProjectState? RequestedProjectState { get; }
 
        /// <summary>
        /// Whether the tools version used originated from an explicit specification,
        /// for example from an MSBuild task or /tv switch.
        /// </summary>
        internal bool ExplicitToolsVersionSpecified => ExplicitlySpecifiedToolsVersion != null;
 
        /// <summary>
        /// Returns the global properties as a dictionary.
        /// </summary>
        internal PropertyDictionary<ProjectPropertyInstance>? GlobalPropertiesDictionary { get; }
 
        private IReadOnlyDictionary<string, string?>? _globalPropertiesLookup;
 
        /// <inheritdoc cref="BuildRequestDataBase"/>
        public override IReadOnlyDictionary<string, string?> GlobalPropertiesLookup => _globalPropertiesLookup ??=
            Execution.GlobalPropertiesLookup.ToGlobalPropertiesLookup(GlobalPropertiesDictionary);
 
        // WARNING!: Do not remove the below proxy properties.
        //  They are required to make the OM forward compatible
        //  (code built against this OM should run against binaries with previous version of OM).
 
        /// <inheritdoc cref="BuildRequestDataBase.TargetNames"/>
        public new ICollection<string> TargetNames => base.TargetNames;
 
        /// <inheritdoc cref="BuildRequestDataBase.Flags"/>
        public new BuildRequestDataFlags Flags => base.Flags;
 
        /// <inheritdoc cref="BuildRequestDataBase.HostServices"/>
        public new HostServices? HostServices => base.HostServices;
    }
}