-
-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
52 changed files
with
3,703 additions
and
3,766 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,41 @@ | ||
<Project> | ||
|
||
<PropertyGroup> | ||
<Version Condition="'$(BuildalyzerVersion)' == ''">1.0.0</Version> | ||
<Version Condition="'$(BuildalyzerVersion)' != ''">$(BuildalyzerVersion)</Version> | ||
<AssemblyVersion>$(Version.Split('-')[0])</AssemblyVersion> | ||
<FileVersion>$(Version.Split('-')[0])</FileVersion> | ||
<Authors>Dave Glick and contributors</Authors> | ||
<Company>Dave Glick and contributors</Company> | ||
<Authors>Dave Glick, Pablo Monteiro, and contributors</Authors> | ||
<Company>Dave Glick, Pablo Monteiro, and contributors</Company> | ||
<PackageIcon>icon.png</PackageIcon> | ||
<PackageReadmeFile>README.md</PackageReadmeFile> | ||
<PackageProjectUrl>https://github.com/daveaglick/Buildalyzer</PackageProjectUrl> | ||
<RepositoryUrl>https://github.com/daveaglick/Buildalyzer.git</RepositoryUrl> | ||
<PackageProjectUrl>https://github.com/phmonte/Buildalyzer</PackageProjectUrl> | ||
<RepositoryUrl>https://github.com/phmonte/Buildalyzer.git</RepositoryUrl> | ||
<RepositoryType>git</RepositoryType> | ||
<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance> | ||
<PublishRepositoryUrl>true</PublishRepositoryUrl> | ||
<IncludeSymbols>true</IncludeSymbols> | ||
<SymbolPackageFormat>snupkg</SymbolPackageFormat> | ||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors> | ||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
<EmbedUntrackedSources>true</EmbedUntrackedSources> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<None Include="$(MSBuildThisFileDirectory)\LICENSE.md" Pack="true" PackagePath=""/> | ||
<None Include="$(MSBuildThisFileDirectory)\icon.png" Pack="true" PackagePath="\"/> | ||
<None Include="$(MSBuildThisFileDirectory)\README.md" Pack="true" PackagePath="\"/> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/> | ||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All"/> | ||
<PackageReference Include="Roslynator.Analyzers" Version="4.0.2" PrivateAssets="All"/> | ||
<!-- It appears as though there might be a performance issue in versions of Microsoft.VisualStudio.Threading.Analyzers past this at least through 17.0.64 --> | ||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.9.60" PrivateAssets="All"/> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/> | ||
</ItemGroup> | ||
|
||
<ItemGroup Label="Analyzers"> | ||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="*" PrivateAssets="All"/> | ||
<PackageReference Include="Roslynator.Analyzers" Version="*" PrivateAssets="All"/> | ||
<PackageReference Include="StyleCop.Analyzers" Version="*-*" PrivateAssets="All"/> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,96 +1,93 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using Microsoft.Build.Framework; | ||
using MsBuildPipeLogger; | ||
|
||
namespace Buildalyzer.Logger | ||
namespace Buildalyzer.Logger; | ||
|
||
public class BuildalyzerLogger : PipeLogger | ||
{ | ||
public class BuildalyzerLogger : PipeLogger | ||
{ | ||
private string _pipeHandleAsString; | ||
private bool _logEverything; | ||
private string _pipeHandleAsString; | ||
private bool _logEverything; | ||
|
||
public override void Initialize(IEventSource eventSource) | ||
public override void Initialize(IEventSource eventSource) | ||
{ | ||
// Parse the parameters | ||
string[] parameters = Parameters.Split(';').Select(x => x.Trim()).ToArray(); | ||
if (parameters.Length != 2) | ||
{ | ||
// Parse the parameters | ||
string[] parameters = Parameters.Split(';').Select(x => x.Trim()).ToArray(); | ||
if (parameters.Length != 2) | ||
{ | ||
throw new LoggerException("Unexpected number of parameters"); | ||
} | ||
_pipeHandleAsString = parameters[0]; | ||
if (!bool.TryParse(parameters[1], out _logEverything)) | ||
{ | ||
throw new LoggerException("Second parameter (log everything) should be a bool"); | ||
} | ||
|
||
base.Initialize(eventSource); | ||
throw new LoggerException("Unexpected number of parameters"); | ||
} | ||
|
||
protected override void InitializeEnvironmentVariables() | ||
_pipeHandleAsString = parameters[0]; | ||
if (!bool.TryParse(parameters[1], out _logEverything)) | ||
{ | ||
// Only register the extra logging environment variables if logging everything | ||
if (_logEverything) | ||
{ | ||
base.InitializeEnvironmentVariables(); | ||
} | ||
throw new LoggerException("Second parameter (log everything) should be a bool"); | ||
} | ||
|
||
protected override IPipeWriter InitializePipeWriter() => new AnonymousPipeWriter(_pipeHandleAsString); | ||
base.Initialize(eventSource); | ||
} | ||
|
||
protected override void InitializeEvents(IEventSource eventSource) | ||
protected override void InitializeEnvironmentVariables() | ||
{ | ||
// Only register the extra logging environment variables if logging everything | ||
if (_logEverything) | ||
{ | ||
if (eventSource is null) | ||
{ | ||
throw new ArgumentNullException(nameof(eventSource)); | ||
} | ||
base.InitializeEnvironmentVariables(); | ||
} | ||
} | ||
|
||
if (_logEverything) | ||
{ | ||
base.InitializeEvents(eventSource); | ||
return; | ||
} | ||
protected override IPipeWriter InitializePipeWriter() => new AnonymousPipeWriter(_pipeHandleAsString); | ||
|
||
// Only log what we need for Buildalyzer | ||
eventSource.ProjectStarted += (_, e) => Pipe.Write(e); | ||
eventSource.ProjectFinished += (_, e) => Pipe.Write(e); | ||
eventSource.BuildFinished += (_, e) => Pipe.Write(e); | ||
eventSource.ErrorRaised += (_, e) => Pipe.Write(e); | ||
eventSource.TargetStarted += TargetStarted; | ||
eventSource.TargetFinished += TargetFinished; | ||
eventSource.MessageRaised += MessageRaised; | ||
protected override void InitializeEvents(IEventSource eventSource) | ||
{ | ||
if (eventSource is null) | ||
{ | ||
throw new ArgumentNullException(nameof(eventSource)); | ||
} | ||
|
||
private void TargetStarted(object sender, TargetStartedEventArgs e) | ||
if (_logEverything) | ||
{ | ||
// Only send the CoreCompile target | ||
if (e.TargetName == "CoreCompile") | ||
{ | ||
Pipe.Write(e); | ||
} | ||
base.InitializeEvents(eventSource); | ||
return; | ||
} | ||
|
||
private void TargetFinished(object sender, TargetFinishedEventArgs e) | ||
// Only log what we need for Buildalyzer | ||
eventSource.ProjectStarted += (_, e) => Pipe.Write(e); | ||
eventSource.ProjectFinished += (_, e) => Pipe.Write(e); | ||
eventSource.BuildFinished += (_, e) => Pipe.Write(e); | ||
eventSource.ErrorRaised += (_, e) => Pipe.Write(e); | ||
eventSource.TargetStarted += TargetStarted; | ||
eventSource.TargetFinished += TargetFinished; | ||
eventSource.MessageRaised += MessageRaised; | ||
} | ||
|
||
private void TargetStarted(object sender, TargetStartedEventArgs e) | ||
{ | ||
// Only send the CoreCompile target | ||
if (e.TargetName == "CoreCompile") | ||
{ | ||
Pipe.Write(e); | ||
} | ||
} | ||
|
||
private void TargetFinished(object sender, TargetFinishedEventArgs e) | ||
{ | ||
// Only send the CoreCompile target | ||
if (e.TargetName == "CoreCompile") | ||
{ | ||
// Only send the CoreCompile target | ||
if (e.TargetName == "CoreCompile") | ||
{ | ||
Pipe.Write(e); | ||
} | ||
Pipe.Write(e); | ||
} | ||
} | ||
|
||
private void MessageRaised(object sender, BuildMessageEventArgs e) | ||
private void MessageRaised(object sender, BuildMessageEventArgs e) | ||
{ | ||
// Only send if in the Csc Vbc, or the Fsc task | ||
if ((e is TaskCommandLineEventArgs cmd && | ||
string.Equals(cmd.TaskName, "Csc", StringComparison.OrdinalIgnoreCase)) || | ||
string.Equals(e.SenderName, "Fsc", StringComparison.OrdinalIgnoreCase) || | ||
string.Equals(e.SenderName, "Vbc", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
// Only send if in the Csc Vbc, or the Fsc task | ||
if ((e is TaskCommandLineEventArgs cmd && | ||
string.Equals(cmd.TaskName, "Csc", StringComparison.OrdinalIgnoreCase)) || | ||
string.Equals(e.SenderName, "Fsc", StringComparison.OrdinalIgnoreCase) || | ||
string.Equals(e.SenderName, "Vbc", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
Pipe.Write(e); | ||
} | ||
Pipe.Write(e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,63 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.Build.Construction; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Buildalyzer.Workspaces | ||
namespace Buildalyzer.Workspaces; | ||
|
||
public static class AnalyzerManagerExtensions | ||
{ | ||
public static class AnalyzerManagerExtensions | ||
/// <summary> | ||
/// Instantiates an empty AdhocWorkspace with logging event handlers. | ||
/// </summary> | ||
internal static AdhocWorkspace CreateWorkspace(this IAnalyzerManager manager) | ||
{ | ||
ILogger logger = manager.LoggerFactory?.CreateLogger<AdhocWorkspace>(); | ||
AdhocWorkspace workspace = new AdhocWorkspace(); | ||
workspace.WorkspaceChanged += (sender, args) => logger?.LogDebug($"Workspace changed: {args.Kind.ToString()}{System.Environment.NewLine}"); | ||
workspace.WorkspaceFailed += (sender, args) => logger?.LogError($"Workspace failed: {args.Diagnostic}{System.Environment.NewLine}"); | ||
return workspace; | ||
} | ||
|
||
public static AdhocWorkspace GetWorkspace(this IAnalyzerManager manager) | ||
{ | ||
/// <summary> | ||
/// Instantiates an empty AdhocWorkspace with logging event handlers. | ||
/// </summary> | ||
internal static AdhocWorkspace CreateWorkspace(this IAnalyzerManager manager) | ||
if (manager is null) | ||
{ | ||
ILogger logger = manager.LoggerFactory?.CreateLogger<AdhocWorkspace>(); | ||
AdhocWorkspace workspace = new AdhocWorkspace(); | ||
workspace.WorkspaceChanged += (sender, args) => logger?.LogDebug($"Workspace changed: {args.Kind.ToString()}{System.Environment.NewLine}"); | ||
workspace.WorkspaceFailed += (sender, args) => logger?.LogError($"Workspace failed: {args.Diagnostic}{System.Environment.NewLine}"); | ||
return workspace; | ||
throw new ArgumentNullException(nameof(manager)); | ||
} | ||
|
||
public static AdhocWorkspace GetWorkspace(this IAnalyzerManager manager) | ||
// Run builds in parallel | ||
List<IAnalyzerResult> results = manager.Projects.Values | ||
.AsParallel() | ||
.Select(p => p.Build().FirstOrDefault()) | ||
.Where(x => x != null) | ||
.ToList(); | ||
|
||
// Create a new workspace and add the solution (if there was one) | ||
AdhocWorkspace workspace = manager.CreateWorkspace(); | ||
if (!string.IsNullOrEmpty(manager.SolutionFilePath)) | ||
{ | ||
if (manager is null) | ||
{ | ||
throw new ArgumentNullException(nameof(manager)); | ||
} | ||
SolutionInfo solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, manager.SolutionFilePath); | ||
workspace.AddSolution(solutionInfo); | ||
|
||
// Run builds in parallel | ||
List<IAnalyzerResult> results = manager.Projects.Values | ||
.AsParallel() | ||
.Select(p => p.Build().FirstOrDefault()) | ||
.Where(x => x != null) | ||
// Sort the projects so the order that they're added to the workspace in the same order as the solution file | ||
List<ProjectInSolution> projectsInOrder = manager.SolutionFile.ProjectsInOrder.ToList(); | ||
results = results | ||
.OrderBy(p => projectsInOrder.FindIndex(g => g.AbsolutePath == p.ProjectFilePath)) | ||
.ToList(); | ||
} | ||
|
||
// Create a new workspace and add the solution (if there was one) | ||
AdhocWorkspace workspace = manager.CreateWorkspace(); | ||
if (!string.IsNullOrEmpty(manager.SolutionFilePath)) | ||
{ | ||
SolutionInfo solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, manager.SolutionFilePath); | ||
workspace.AddSolution(solutionInfo); | ||
|
||
// Sort the projects so the order that they're added to the workspace in the same order as the solution file | ||
List<ProjectInSolution> projectsInOrder = manager.SolutionFile.ProjectsInOrder.ToList(); | ||
results = results | ||
.OrderBy(p => projectsInOrder.FindIndex(g => g.AbsolutePath == p.ProjectFilePath)) | ||
.ToList(); | ||
} | ||
|
||
// Add each result to the new workspace (sorted in solution order above, if we have a solution) | ||
foreach (IAnalyzerResult result in results) | ||
// Add each result to the new workspace (sorted in solution order above, if we have a solution) | ||
foreach (IAnalyzerResult result in results) | ||
{ | ||
// Check for duplicate project files and don't add them | ||
if (workspace.CurrentSolution.Projects.All(p => p.FilePath != result.ProjectFilePath)) | ||
{ | ||
// Check for duplicate project files and don't add them | ||
if (workspace.CurrentSolution.Projects.All(p => p.FilePath != result.ProjectFilePath)) | ||
{ | ||
result.AddToWorkspace(workspace, true); | ||
} | ||
result.AddToWorkspace(workspace, true); | ||
} | ||
return workspace; | ||
} | ||
return workspace; | ||
} | ||
} |
Oops, something went wrong.