Skip to content

Commit 7d9ef9c

Browse files
authored
Expose collected BuildEvents publically (#296)
1 parent 9e95595 commit 7d9ef9c

File tree

6 files changed

+67
-56
lines changed

6 files changed

+67
-56
lines changed

src/Buildalyzer/AnalyzerManagerOptions.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ namespace Buildalyzer;
77

88
public class AnalyzerManagerOptions
99
{
10-
public ILoggerFactory LoggerFactory { get; set; }
10+
public ILoggerFactory? LoggerFactory { get; set; }
1111

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

18-
public TextWriter LogWriter
18+
public TextWriter? LogWriter
1919
{
2020
set
2121
{

src/Buildalyzer/AnalyzerResults.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Concurrent;
2+
using Microsoft.Build.Framework;
23

34
namespace Buildalyzer;
45

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

23+
/// <inheritdoc />
24+
public ImmutableArray<BuildEventArgs> BuildEventArguments { get; set; } = [];
25+
2226
public IAnalyzerResult this[string targetFramework] => _results[targetFramework];
2327

2428
public IEnumerable<string> TargetFrameworks => _results.Keys.OrderBy(e => e, TargetFrameworkComparer.Instance);

src/Buildalyzer/BuildEventArgsCollector.cs

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ public BuildEventArgsCollector(EventArgsDispatcher server)
1717
/// <inheritdoc />
1818
public int Count => Bag.Count;
1919

20+
/// <summary>Indicates that no events has been collected.</summary>
21+
public bool IsEmpty => Count == 0;
22+
2023
/// <inheritdoc />
2124
public IEnumerator<BuildEventArgs> GetEnumerator() => Bag.GetEnumerator();
2225

src/Buildalyzer/IAnalyzerResults.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
using Microsoft.Build.Framework;
2+
13
namespace Buildalyzer;
24

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

7-
int Count { get; }
10+
IAnalyzerResult this[string targetFramework] { get; }
811

912
bool OverallSuccess { get; }
1013

src/Buildalyzer/ProjectAnalyzer.cs

+41-50
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using Buildalyzer.Logger;
77
using Buildalyzer.Logging;
88
using Microsoft.Build.Construction;
9-
using Microsoft.Build.Framework;
109
using Microsoft.Build.Logging;
1110
using Microsoft.Extensions.Logging;
1211
using MsBuildPipeLogger;
@@ -148,61 +147,53 @@ public IAnalyzerResults Build(string targetFramework, BuildEnvironment buildEnvi
148147
private IAnalyzerResults BuildTargets(
149148
BuildEnvironment buildEnvironment, string targetFramework, string[] targetsToBuild, AnalyzerResults results)
150149
{
151-
using (CancellationTokenSource cancellation = new CancellationTokenSource())
152-
{
153-
using var pipeLogger = new AnonymousPipeLoggerServer(cancellation.Token);
154-
bool receivedAnyEvent = false;
155-
156-
void OnPipeLoggerOnAnyEventRaised(object o, BuildEventArgs buildEventArgs)
157-
{
158-
receivedAnyEvent = true;
159-
}
160-
161-
pipeLogger.AnyEventRaised += OnPipeLoggerOnAnyEventRaised;
150+
using var cancellation = new CancellationTokenSource();
162151

163-
using var eventProcessor = new EventProcessor(Manager, this, BuildLoggers, pipeLogger, results != null);
152+
using var pipeLogger = new AnonymousPipeLoggerServer(cancellation.Token);
153+
using var eventCollector = new BuildEventArgsCollector(pipeLogger);
154+
using var eventProcessor = new EventProcessor(Manager, this, BuildLoggers, pipeLogger, true);
164155

165-
// Run MSBuild
166-
int exitCode;
167-
string fileName = GetCommand(
168-
buildEnvironment,
169-
targetFramework,
170-
targetsToBuild,
171-
pipeLogger.GetClientHandle(),
172-
out string arguments);
173-
174-
using (ProcessRunner processRunner = new ProcessRunner(
175-
fileName,
176-
arguments,
177-
buildEnvironment.WorkingDirectory ?? Path.GetDirectoryName(ProjectFile.Path),
178-
GetEffectiveEnvironmentVariables(buildEnvironment),
179-
Manager.LoggerFactory))
156+
// Run MSBuild
157+
int exitCode;
158+
string fileName = GetCommand(
159+
buildEnvironment,
160+
targetFramework,
161+
targetsToBuild,
162+
pipeLogger.GetClientHandle(),
163+
out string arguments);
164+
165+
using var processRunner = new ProcessRunner(
166+
fileName,
167+
arguments,
168+
buildEnvironment.WorkingDirectory ?? Path.GetDirectoryName(ProjectFile.Path)!,
169+
GetEffectiveEnvironmentVariables(buildEnvironment)!,
170+
Manager.LoggerFactory);
171+
172+
void OnProcessRunnerExited()
173+
{
174+
if (eventCollector.IsEmpty && processRunner.ExitCode != 0)
180175
{
181-
void OnProcessRunnerExited()
182-
{
183-
if (!receivedAnyEvent && processRunner.ExitCode != 0)
184-
{
185-
pipeLogger.Dispose();
186-
}
187-
}
188-
189-
processRunner.Exited += OnProcessRunnerExited;
190-
processRunner.Start();
191-
try
192-
{
193-
pipeLogger.ReadAll();
194-
}
195-
catch (ObjectDisposedException)
196-
{
197-
// Ignore
198-
}
199-
processRunner.WaitForExit();
200-
exitCode = processRunner.ExitCode;
176+
pipeLogger.Dispose();
201177
}
178+
}
202179

203-
// Collect the results
204-
results?.Add(eventProcessor.Results, exitCode == 0 && eventProcessor.OverallSuccess);
180+
processRunner.Exited += OnProcessRunnerExited;
181+
processRunner.Start();
182+
try
183+
{
184+
pipeLogger.ReadAll();
185+
}
186+
catch (ObjectDisposedException)
187+
{
188+
// Ignore
205189
}
190+
processRunner.WaitForExit();
191+
exitCode = processRunner.ExitCode;
192+
results.BuildEventArguments = [.. eventCollector];
193+
194+
// Collect the results
195+
results.Add(eventProcessor.Results, exitCode == 0 && eventProcessor.OverallSuccess);
196+
206197
return results;
207198
}
208199

tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs

+10
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ public void Builds_DesignTime(
8181
results.Should().AllSatisfy(r => r.Succeeded.Should().BeTrue());
8282
}
8383

84+
[Test]
85+
public void Collects_BuildEventArguments()
86+
{
87+
using var ctx = Context.ForProject(@"SdkNet6Project\SdkNet6Project.csproj");
88+
89+
var results = ctx.Analyzer.Build(new EnvironmentOptions());
90+
91+
results.BuildEventArguments.Should().HaveCount(18);
92+
}
93+
8494
[Test]
8595
public void BuildsProject(
8696
[ValueSource(nameof(Preferences))] EnvironmentPreference preference,

0 commit comments

Comments
 (0)