File: BuildCheck\OM\BuildCheckDataContext.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 Microsoft.Build.Experimental.BuildCheck.Infrastructure;
using System.IO;
 
namespace Microsoft.Build.Experimental.BuildCheck;
 
/// <summary>
/// Base for a data passed from infrastructure to build checks.
/// </summary>
/// <param name="projectFilePath">Currently built project.</param>
/// <param name="projectConfigurationId">The unique id of a project with unique global properties set.</param>
public abstract class CheckData(string projectFilePath, int? projectConfigurationId)
{
    private string? _projectFileDirectory;
    // The id is going to be used in future revision
#pragma warning disable CA1823
    private int? _projectConfigurationId = projectConfigurationId;
#pragma warning restore CA1823
 
    /// <summary>
    /// Full path to the project file being built.
    /// </summary>
    public string ProjectFilePath { get; } = projectFilePath;
 
    // TBD: ProjectConfigurationId is not yet populated - as we need to properly anchor project build events
    ///// <summary>
    ///// The unique id of a project with unique global properties set.
    ///// This is helpful to distinguish between different configurations of a single project in case of multitargeting.
    /////
    ///// In cases where the project instance cannot be determined, it will be set to <see cref="BuildEventContext.InvalidProjectInstanceId"/>.
    ///// This is generally case of all evaluation-time data. To relate evaluation-time and build-execution-time data, use (TBD: ProjectStarted event/data)
    ///// </summary>
    ///// <remarks>
    ///// The same project with same global properties (aka configuration), can be executed multiple times to obtain results for multiple targets.
    /////  (this is internally distinguished as 'ProjectContextId' - each context is a different request for different targets results).
    ///// This is not distinguished by the ProjectConfigurationId - as all of those executions share same configuration and results and prevents re-execution of the same targets.
    /////
    ///// InstanceId (ConfigurationId): https://github.com/dotnet/msbuild/blob/2a8b16dbabd25782554ff0fe77619d58eccfe603/src/Build/BackEnd/BuildManager/BuildManager.cs#L2186-L2244
    ///// </remarks>
    ////public int ProjectConfigurationId { get; } = projectConfigurationId ?? BuildEventContext.InvalidProjectInstanceId;
 
    /// <summary>
    /// Directory path of the file being built (the containing directory of <see cref="ProjectFilePath"/>).
    /// </summary>
    public string ProjectFileDirectory =>
        _projectFileDirectory ??= Path.GetDirectoryName(ProjectFilePath)!;
}
 
/// <summary>
/// Data passed from infrastructure to build checks.
/// </summary>
/// <typeparam name="T">The type of the actual data for checking.</typeparam>
public class BuildCheckDataContext<T> where T : CheckData
{
    private readonly CheckWrapper _executionCheckWrapper;
    private readonly ICheckContext _checkContext;
    private readonly CheckConfigurationEffective[] _configPerRule;
    private readonly Action<CheckWrapper, ICheckContext, CheckConfigurationEffective[], BuildCheckResult> _resultHandler;
 
    internal BuildCheckDataContext(
        CheckWrapper checkWrapper,
        ICheckContext loggingContext,
        CheckConfigurationEffective[] configPerRule,
        Action<CheckWrapper, ICheckContext, CheckConfigurationEffective[], BuildCheckResult> resultHandler,
        T data)
    {
        _executionCheckWrapper = checkWrapper;
        _checkContext = loggingContext;
        _configPerRule = configPerRule;
        _resultHandler = resultHandler;
        Data = data;
    }
 
    /// <summary>
    /// Method for reporting the result of the build check rule.
    /// </summary>
    /// <param name="result"></param>
    public void ReportResult(BuildCheckResult result)
        => _resultHandler(_executionCheckWrapper, _checkContext, _configPerRule, result);
 
    /// <summary>
    /// Data to be checked.
    /// </summary>
    public T Data { get; }
}