Skip to content

Commit

Permalink
Expose collected BuildEvents publically (#296)
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel authored Mar 4, 2025
1 parent 9e95595 commit 7d9ef9c
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 56 deletions.
6 changes: 3 additions & 3 deletions src/Buildalyzer/AnalyzerManagerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ namespace Buildalyzer;

public class AnalyzerManagerOptions
{
public ILoggerFactory LoggerFactory { get; set; }
public ILoggerFactory? LoggerFactory { get; set; }

/// <summary>
/// A filter that indicates whether a give project should be loaded.
/// Return <c>true</c> to load the project, <c>false</c> to filter it out.
/// </summary>
public Func<ProjectInSolution, bool> ProjectFilter { get; set; }
public Func<ProjectInSolution, bool>? ProjectFilter { get; set; }

public TextWriter LogWriter
public TextWriter? LogWriter
{
set
{
Expand Down
4 changes: 4 additions & 0 deletions src/Buildalyzer/AnalyzerResults.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using Microsoft.Build.Framework;

namespace Buildalyzer;

Expand All @@ -19,6 +20,9 @@ internal void Add(IEnumerable<IAnalyzerResult> results, bool overallSuccess)
_overallSuccess = _overallSuccess.HasValue ? _overallSuccess.Value && overallSuccess : overallSuccess;
}

/// <inheritdoc />
public ImmutableArray<BuildEventArgs> BuildEventArguments { get; set; } = [];

public IAnalyzerResult this[string targetFramework] => _results[targetFramework];

public IEnumerable<string> TargetFrameworks => _results.Keys.OrderBy(e => e, TargetFrameworkComparer.Instance);
Expand Down
3 changes: 3 additions & 0 deletions src/Buildalyzer/BuildEventArgsCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public BuildEventArgsCollector(EventArgsDispatcher server)
/// <inheritdoc />
public int Count => Bag.Count;

/// <summary>Indicates that no events has been collected.</summary>
public bool IsEmpty => Count == 0;

/// <inheritdoc />
public IEnumerator<BuildEventArgs> GetEnumerator() => Bag.GetEnumerator();

Expand Down
9 changes: 6 additions & 3 deletions src/Buildalyzer/IAnalyzerResults.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using Microsoft.Build.Framework;

namespace Buildalyzer;

public interface IAnalyzerResults : IEnumerable<IAnalyzerResult>
public interface IAnalyzerResults : IReadOnlyCollection<IAnalyzerResult>
{
IAnalyzerResult this[string targetFramework] { get; }
/// <summary>The collected <see cref="BuildEventArgs"/> during the analysis.</summary>
ImmutableArray<BuildEventArgs> BuildEventArguments { get; }

int Count { get; }
IAnalyzerResult this[string targetFramework] { get; }

bool OverallSuccess { get; }

Expand Down
91 changes: 41 additions & 50 deletions src/Buildalyzer/ProjectAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Buildalyzer.Logger;
using Buildalyzer.Logging;
using Microsoft.Build.Construction;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
using Microsoft.Extensions.Logging;
using MsBuildPipeLogger;
Expand Down Expand Up @@ -148,61 +147,53 @@ public IAnalyzerResults Build(string targetFramework, BuildEnvironment buildEnvi
private IAnalyzerResults BuildTargets(
BuildEnvironment buildEnvironment, string targetFramework, string[] targetsToBuild, AnalyzerResults results)
{
using (CancellationTokenSource cancellation = new CancellationTokenSource())
{
using var pipeLogger = new AnonymousPipeLoggerServer(cancellation.Token);
bool receivedAnyEvent = false;

void OnPipeLoggerOnAnyEventRaised(object o, BuildEventArgs buildEventArgs)
{
receivedAnyEvent = true;
}

pipeLogger.AnyEventRaised += OnPipeLoggerOnAnyEventRaised;
using var cancellation = new CancellationTokenSource();

using var eventProcessor = new EventProcessor(Manager, this, BuildLoggers, pipeLogger, results != null);
using var pipeLogger = new AnonymousPipeLoggerServer(cancellation.Token);
using var eventCollector = new BuildEventArgsCollector(pipeLogger);
using var eventProcessor = new EventProcessor(Manager, this, BuildLoggers, pipeLogger, true);

// Run MSBuild
int exitCode;
string fileName = GetCommand(
buildEnvironment,
targetFramework,
targetsToBuild,
pipeLogger.GetClientHandle(),
out string arguments);

using (ProcessRunner processRunner = new ProcessRunner(
fileName,
arguments,
buildEnvironment.WorkingDirectory ?? Path.GetDirectoryName(ProjectFile.Path),
GetEffectiveEnvironmentVariables(buildEnvironment),
Manager.LoggerFactory))
// Run MSBuild
int exitCode;
string fileName = GetCommand(
buildEnvironment,
targetFramework,
targetsToBuild,
pipeLogger.GetClientHandle(),
out string arguments);

using var processRunner = new ProcessRunner(
fileName,
arguments,
buildEnvironment.WorkingDirectory ?? Path.GetDirectoryName(ProjectFile.Path)!,
GetEffectiveEnvironmentVariables(buildEnvironment)!,
Manager.LoggerFactory);

void OnProcessRunnerExited()
{
if (eventCollector.IsEmpty && processRunner.ExitCode != 0)
{
void OnProcessRunnerExited()
{
if (!receivedAnyEvent && processRunner.ExitCode != 0)
{
pipeLogger.Dispose();
}
}

processRunner.Exited += OnProcessRunnerExited;
processRunner.Start();
try
{
pipeLogger.ReadAll();
}
catch (ObjectDisposedException)
{
// Ignore
}
processRunner.WaitForExit();
exitCode = processRunner.ExitCode;
pipeLogger.Dispose();
}
}

// Collect the results
results?.Add(eventProcessor.Results, exitCode == 0 && eventProcessor.OverallSuccess);
processRunner.Exited += OnProcessRunnerExited;
processRunner.Start();
try
{
pipeLogger.ReadAll();
}
catch (ObjectDisposedException)
{
// Ignore
}
processRunner.WaitForExit();
exitCode = processRunner.ExitCode;
results.BuildEventArguments = [.. eventCollector];

// Collect the results
results.Add(eventProcessor.Results, exitCode == 0 && eventProcessor.OverallSuccess);

return results;
}

Expand Down
10 changes: 10 additions & 0 deletions tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ public void Builds_DesignTime(
results.Should().AllSatisfy(r => r.Succeeded.Should().BeTrue());
}

[Test]
public void Collects_BuildEventArguments()
{
using var ctx = Context.ForProject(@"SdkNet6Project\SdkNet6Project.csproj");

var results = ctx.Analyzer.Build(new EnvironmentOptions());

results.BuildEventArguments.Should().HaveCount(18);
}

[Test]
public void BuildsProject(
[ValueSource(nameof(Preferences))] EnvironmentPreference preference,
Expand Down

0 comments on commit 7d9ef9c

Please sign in to comment.