Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose collected BuildEvents publically #296

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
_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 All @@ -39,7 +43,7 @@
{
public static TargetFrameworkComparer Instance { get; } = new TargetFrameworkComparer();

public int Compare(string x, string y)

Check warning on line 46 in src/Buildalyzer/AnalyzerResults.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullability of reference types in type of parameter 'x' of 'int TargetFrameworkComparer.Compare(string x, string y)' doesn't match implicitly implemented member 'int IComparer<string>.Compare(string? x, string? y)' (possibly because of nullability attributes).

Check warning on line 46 in src/Buildalyzer/AnalyzerResults.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullability of reference types in type of parameter 'y' of 'int TargetFrameworkComparer.Compare(string x, string y)' doesn't match implicitly implemented member 'int IComparer<string>.Compare(string? x, string? y)' (possibly because of nullability attributes).

Check warning on line 46 in src/Buildalyzer/AnalyzerResults.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullability of reference types in type of parameter 'x' of 'int TargetFrameworkComparer.Compare(string x, string y)' doesn't match implicitly implemented member 'int IComparer<string>.Compare(string? x, string? y)' (possibly because of nullability attributes).

Check warning on line 46 in src/Buildalyzer/AnalyzerResults.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullability of reference types in type of parameter 'y' of 'int TargetFrameworkComparer.Compare(string x, string y)' doesn't match implicitly implemented member 'int IComparer<string>.Compare(string? x, string? y)' (possibly because of nullability attributes).

Check warning on line 46 in src/Buildalyzer/AnalyzerResults.cs

View workflow job for this annotation

GitHub Actions / Build (macos-12)

Nullability of reference types in type of parameter 'x' of 'int TargetFrameworkComparer.Compare(string x, string y)' doesn't match implicitly implemented member 'int IComparer<string>.Compare(string? x, string? y)' (possibly because of nullability attributes).

Check warning on line 46 in src/Buildalyzer/AnalyzerResults.cs

View workflow job for this annotation

GitHub Actions / Build (macos-12)

Nullability of reference types in type of parameter 'y' of 'int TargetFrameworkComparer.Compare(string x, string y)' doesn't match implicitly implemented member 'int IComparer<string>.Compare(string? x, string? y)' (possibly because of nullability attributes).
{
return (string.IsNullOrEmpty(x), string.IsNullOrEmpty(y)) switch
{
Expand Down
4 changes: 4 additions & 0 deletions src/Buildalyzer/BuildEventArgsCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ public BuildEventArgsCollector(EventArgsDispatcher server)
/// <inheritdoc />
public int Count => Bag.Count;

/// <summary>Indicates that no events has been collected.</summary>
[Pure]
public bool None() => Count == 0;

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

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

public interface IAnalyzerResults : IEnumerable<IAnalyzerResult>
namespace Buildalyzer;

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
88 changes: 41 additions & 47 deletions src/Buildalyzer/ProjectAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,61 +148,55 @@ 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 (ProcessRunner processRunner = new ProcessRunner(
fileName,
arguments,
buildEnvironment.WorkingDirectory ?? Path.GetDirectoryName(ProjectFile.Path)!,
GetEffectiveEnvironmentVariables(buildEnvironment)!,
Manager.LoggerFactory))
{
void OnProcessRunnerExited()
{
void OnProcessRunnerExited()
{
if (!receivedAnyEvent && processRunner.ExitCode != 0)
{
pipeLogger.Dispose();
}
}

processRunner.Exited += OnProcessRunnerExited;
processRunner.Start();
try
{
pipeLogger.ReadAll();
}
catch (ObjectDisposedException)
if (eventCollector.None() && processRunner.ExitCode != 0)
{
// Ignore
pipeLogger.Dispose();
}
processRunner.WaitForExit();
exitCode = processRunner.ExitCode;
}

// 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
Loading