From cfe8e01140c8a3fc7a8a2032cab775dc16fcdc25 Mon Sep 17 00:00:00 2001 From: Ricardo Escobar Barrios <348416+REscobar@users.noreply.github.com> Date: Sat, 7 Sep 2024 22:20:06 -0600 Subject: [PATCH 1/5] Updates MSBuild references (#282) --- .../Buildalyzer.Workspaces.csproj | 4 +- src/Buildalyzer/Buildalyzer.csproj | 4 +- .../Integration/SimpleProjectsFixture.cs | 1 + .../ProjectAnalyzerExtensionsFixture.cs | 18 ++++ .../SdkNet8CS12FeaturesProject/Class1.cs | 99 +++++++++++++++++++ .../SdkNet8CS12FeaturesProject.csproj | 9 ++ tests/projects/TestProjects.sln | 12 ++- 7 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 tests/projects/SdkNet8CS12FeaturesProject/Class1.cs create mode 100644 tests/projects/SdkNet8CS12FeaturesProject/SdkNet8CS12FeaturesProject.csproj diff --git a/src/Buildalyzer.Workspaces/Buildalyzer.Workspaces.csproj b/src/Buildalyzer.Workspaces/Buildalyzer.Workspaces.csproj index 067722f8..3bf2265f 100644 --- a/src/Buildalyzer.Workspaces/Buildalyzer.Workspaces.csproj +++ b/src/Buildalyzer.Workspaces/Buildalyzer.Workspaces.csproj @@ -19,8 +19,8 @@ ToBeReleased - - + + diff --git a/src/Buildalyzer/Buildalyzer.csproj b/src/Buildalyzer/Buildalyzer.csproj index d1aa8711..ad2674cb 100644 --- a/src/Buildalyzer/Buildalyzer.csproj +++ b/src/Buildalyzer/Buildalyzer.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs index 81cd2cfe..b92649e8 100644 --- a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs +++ b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs @@ -39,6 +39,7 @@ public class SimpleProjectsFixture @"SdkNet6SelfContained\SdkNet6SelfContained.csproj", @"SdkNet6ImplicitUsings\SdkNet6ImplicitUsings.csproj", @"SdkNet7Project\SdkNet7Project.csproj", + @"SdkNet8CS12FeaturesProject\SdkNet8CS12FeaturesProject.csproj", @"SdkNetCore2ProjectImport\SdkNetCore2ProjectImport.csproj", @"SdkNetCore2ProjectWithReference\SdkNetCore2ProjectWithReference.csproj", @"SdkNetCore2ProjectWithImportedProps\SdkNetCore2ProjectWithImportedProps.csproj", diff --git a/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs b/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs index 3f0a0c77..d62f64d7 100644 --- a/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs +++ b/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs @@ -183,6 +183,24 @@ public async Task SupportsNullabilityEnabled() diagnostics.ShouldBeEmpty(); } + [Test(Description = "Test C#12 features https://github.com/phmonte/Buildalyzer/issues/281")] + + public async Task SupportsLangVersion12Features() + { + // Given + StringWriter log = new StringWriter(); + IProjectAnalyzer analyzer = GetProjectAnalyzer(@"projects\SdkNet8CS12FeaturesProject\SdkNet8CS12FeaturesProject.csproj", log); + AdhocWorkspace workspace = analyzer.GetWorkspace(); + Project project = workspace.CurrentSolution.Projects.Single(); + + // When + Compilation compilation = await project.GetCompilationAsync(); + + Diagnostic[] diagnostics = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToArray(); + + diagnostics.ShouldBeEmpty(); + } + #if Is_Windows [Test] public void HandlesWpfCustomControlLibrary() diff --git a/tests/projects/SdkNet8CS12FeaturesProject/Class1.cs b/tests/projects/SdkNet8CS12FeaturesProject/Class1.cs new file mode 100644 index 00000000..739f3f11 --- /dev/null +++ b/tests/projects/SdkNet8CS12FeaturesProject/Class1.cs @@ -0,0 +1,99 @@ +namespace SdkNet8CS12FeaturesProject +{ + // LangVersion12 Features https://github.com/phmonte/Buildalyzer/issues/281 + public class Class1 + { + // https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#collection-expressions + public void CollectionExpression() + { + // Create an array: + int[] a = [1, 2, 3, 4, 5, 6, 7, 8]; + + // Create a list: + List b = ["one", "two", "three"]; + + // Create a span + Span c = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i']; + + // Create a jagged 2D array: + int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + + // Create a jagged 2D array from variables: + int[] row0 = [1, 2, 3]; + int[] row1 = [4, 5, 6]; + int[] row2 = [7, 8, 9]; + int[][] twoDFromVariables = [row0, row1, row2]; + + int[] single = [.. row0, .. row1, .. row2]; + foreach (var element in single) + { + Console.Write($"{element}, "); + } + } + + public readonly struct Distance(double dx, double dy) + { + public readonly double Magnitude { get; } = Math.Sqrt(dx * dx + dy * dy); + public readonly double Direction { get; } = Math.Atan2(dy, dx); + } + + public struct Distance2(double dx, double dy) + { + public readonly double Magnitude => Math.Sqrt(dx * dx + dy * dy); + public readonly double Direction => Math.Atan2(dy, dx); + + public void Translate(double deltaX, double deltaY) + { + dx += deltaX; + dy += deltaY; + } + + public Distance2() : this(0, 0) { } + } + + public class BankAccount(string accountID, string owner) + { + public string AccountID { get; } = ValidAccountNumber(accountID) + ? accountID + : throw new ArgumentException("Invalid account number", nameof(accountID)); + + public string Owner { get; } = string.IsNullOrWhiteSpace(owner) + ? throw new ArgumentException("Owner name cannot be empty", nameof(owner)) + : owner; + + public override string ToString() => $"Account ID: {AccountID}, Owner: {Owner}"; + + public static bool ValidAccountNumber(string accountID) => + accountID?.Length == 10 && accountID.All(c => char.IsDigit(c)); + } + + public class CheckingAccount(string accountID, string owner, decimal overdraftLimit = 0) : BankAccount(accountID, owner) + { + public decimal CurrentBalance { get; private set; } = 0; + + public void Deposit(decimal amount) + { + if (amount < 0) + { + throw new ArgumentOutOfRangeException(nameof(amount), "Deposit amount must be positive"); + } + CurrentBalance += amount; + } + + public void Withdrawal(decimal amount) + { + if (amount < 0) + { + throw new ArgumentOutOfRangeException(nameof(amount), "Withdrawal amount must be positive"); + } + if (CurrentBalance - amount < -overdraftLimit) + { + throw new InvalidOperationException("Insufficient funds for withdrawal"); + } + CurrentBalance -= amount; + } + + public override string ToString() => $"Account ID: {AccountID}, Owner: {Owner}, Balance: {CurrentBalance}"; + } + } +} diff --git a/tests/projects/SdkNet8CS12FeaturesProject/SdkNet8CS12FeaturesProject.csproj b/tests/projects/SdkNet8CS12FeaturesProject/SdkNet8CS12FeaturesProject.csproj new file mode 100644 index 00000000..fa71b7ae --- /dev/null +++ b/tests/projects/SdkNet8CS12FeaturesProject/SdkNet8CS12FeaturesProject.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/tests/projects/TestProjects.sln b/tests/projects/TestProjects.sln index 043eb951..75927d02 100644 --- a/tests/projects/TestProjects.sln +++ b/tests/projects/TestProjects.sln @@ -52,11 +52,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkNet6SelfContained", "Sdk EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "VisualBasicNetConsoleApp", "VisualBasicProject\VisualBasicNetConsoleApp.vbproj", "{592A499F-F101-4ED6-82BE-052A5256B1A2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RazorClassLibraryTest", "RazorClassLibraryTest\RazorClassLibraryTest.csproj", "{96E0901D-99F0-4D28-973E-98F288DF69B7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorClassLibraryTest", "RazorClassLibraryTest\RazorClassLibraryTest.csproj", "{96E0901D-99F0-4D28-973E-98F288DF69B7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResponseFile", "ResponseFile\ResponseFile.csproj", "{B18DD8E6-9D47-4FDD-90EA-8F9C6789BE3A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResponseFile", "ResponseFile\ResponseFile.csproj", "{B18DD8E6-9D47-4FDD-90EA-8F9C6789BE3A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SdkNet7Project", "SdkNet7Project\SdkNet7Project.csproj", "{8862BA17-36B7-470E-B293-D02E18FD5E4D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkNet7Project", "SdkNet7Project\SdkNet7Project.csproj", "{8862BA17-36B7-470E-B293-D02E18FD5E4D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkNet8CS12FeaturesProject", "SdkNet8CS12FeaturesProject\SdkNet8CS12FeaturesProject.csproj", "{6DDD74AB-8821-4267-8DC2-8864A3BB5871}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -172,6 +174,10 @@ Global {8862BA17-36B7-470E-B293-D02E18FD5E4D}.Debug|Any CPU.Build.0 = Debug|Any CPU {8862BA17-36B7-470E-B293-D02E18FD5E4D}.Release|Any CPU.ActiveCfg = Release|Any CPU {8862BA17-36B7-470E-B293-D02E18FD5E4D}.Release|Any CPU.Build.0 = Release|Any CPU + {6DDD74AB-8821-4267-8DC2-8864A3BB5871}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6DDD74AB-8821-4267-8DC2-8864A3BB5871}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DDD74AB-8821-4267-8DC2-8864A3BB5871}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6DDD74AB-8821-4267-8DC2-8864A3BB5871}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From aa33cf52e949fe076bb454d3491cf044c72e6fb1 Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Sun, 8 Sep 2024 06:22:22 +0200 Subject: [PATCH 2/5] Create a test context to take away a lot of the repeating plumbing code (#260) --- Buildalyzer.sln | 1 - .../Integration/SimpleProjectsFixture.cs | 50 ++++------- .../TestTools/BuildalyzerTestContext.cs | 90 +++++++++++++++++++ tests/Buildalyzer.Tests/TestTools/Context.cs | 23 +++++ .../Buildalyzer.Workspaces.Tests.csproj | 3 +- .../ProjectAnalyzerExtensionsFixture.cs | 17 ++-- 6 files changed, 137 insertions(+), 47 deletions(-) create mode 100644 tests/Buildalyzer.Tests/TestTools/BuildalyzerTestContext.cs create mode 100644 tests/Buildalyzer.Tests/TestTools/Context.cs diff --git a/Buildalyzer.sln b/Buildalyzer.sln index e5a3d5dc..ca7a8a1d 100644 --- a/Buildalyzer.sln +++ b/Buildalyzer.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.9.34622.214 diff --git a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs index b92649e8..b5a1aa18 100644 --- a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs +++ b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs @@ -2,6 +2,7 @@ using System.IO; using System.IO.Compression; using Buildalyzer.Environment; +using Buildalyzer.TestTools; using FluentAssertions; using Shouldly; @@ -60,27 +61,23 @@ public class SimpleProjectsFixture }; [Test] - public void DesignTimeBuildsProject( + public void Builds_DesignTime( [ValueSource(nameof(Preferences))] EnvironmentPreference preference, [ValueSource(nameof(ProjectFiles))] string projectFile) { - // Given - StringWriter log = new StringWriter(); - IProjectAnalyzer analyzer = GetProjectAnalyzer(projectFile, log); - EnvironmentOptions options = new EnvironmentOptions + using var ctx = Context.ForProject(projectFile); + + var options = new EnvironmentOptions { - Preference = preference + Preference = preference, + DesignTime = true, }; - // When - DeleteProjectDirectory(projectFile, "obj"); - DeleteProjectDirectory(projectFile, "bin"); - IAnalyzerResults results = analyzer.Build(options); + var results = ctx.Analyzer.Build(options); - // Then - results.Count.ShouldBeGreaterThan(0, log.ToString()); - results.OverallSuccess.ShouldBeTrue(log.ToString()); - results.ShouldAllBe(x => x.Succeeded, log.ToString()); + results.Should().NotBeEmpty(); + results.OverallSuccess.Should().BeTrue(); + results.Should().AllSatisfy(r => r.Succeeded.Should().BeTrue()); } [Test] @@ -139,7 +136,7 @@ public void GetsSourceFiles( [Test] public void GetsReferences( [ValueSource(nameof(Preferences))] EnvironmentPreference preference, - [ValueSource(nameof(ProjectFiles))] [NotNull] string projectFile) + [ValueSource(nameof(ProjectFiles))][NotNull] string projectFile) { // Given StringWriter log = new StringWriter(); @@ -685,7 +682,7 @@ public static void DuplicateProjectReferences() } [Test] - public void GetsAdditionalCscFiles() + public void Resolves_additional_files_for_Razor_project() { // Given StringWriter log = new StringWriter(); @@ -699,7 +696,7 @@ public void GetsAdditionalCscFiles() } [Test] - public void GetsAdditionalFile() + public void Resolves_additional_files() { // Given StringWriter log = new StringWriter(); @@ -710,24 +707,7 @@ public void GetsAdditionalFile() .Should().BeEquivalentTo("message.txt"); } - [Test] - public void HandlesProcessFailure() - { - // Given - StringWriter log = new StringWriter(); - IProjectAnalyzer analyzer = GetProjectAnalyzer(@"SdkNet6Exe\SdkNet6Exe.csproj", log); - - // When - IAnalyzerResults results = analyzer.Build(new EnvironmentOptions - { - Arguments = { "/unknown" } // This argument will cause msbuild to immediately fail - }); - - // Then - results.OverallSuccess.ShouldBeFalse(); - } - - private static IProjectAnalyzer GetProjectAnalyzer(string projectFile, StringWriter log) + private static IProjectAnalyzer GetProjectAnalyzer(string projectFile, System.IO.StringWriter log) { IProjectAnalyzer analyzer = new AnalyzerManager( new AnalyzerManagerOptions diff --git a/tests/Buildalyzer.Tests/TestTools/BuildalyzerTestContext.cs b/tests/Buildalyzer.Tests/TestTools/BuildalyzerTestContext.cs new file mode 100644 index 00000000..99c2d434 --- /dev/null +++ b/tests/Buildalyzer.Tests/TestTools/BuildalyzerTestContext.cs @@ -0,0 +1,90 @@ +using System.Diagnostics; +using System.IO; + +namespace Buildalyzer.TestTools; + +/// Creates a test context for testing s. +/// +/// The context ensures an fresh build (deletes previous artifacts in advance). +/// The context logs to the console in DEBUG mode. +/// +public sealed class BuildalyzerTestContext : IDisposable +{ + public TextWriter Log => IsDisposed ? throw new ObjectDisposedException(GetType().FullName) : log; + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly TextWriter log = new StringWriter(); + + public BuildalyzerTestContext(FileInfo projectFile) + { + ProjectFile = projectFile; + Manager = new AnalyzerManager( + new AnalyzerManagerOptions + { + LogWriter = Log, + }); + + Analyzer = Manager.GetProject(projectFile.FullName); + + DebugMode(ref InDebugMode); + AddBinaryLogger(); + DeleteSubDirectory("bin"); + DeleteSubDirectory("obj"); + } + + public FileInfo ProjectFile { get; } + + public AnalyzerManager Manager { get; } + + public IProjectAnalyzer Analyzer { get; } + + /// + public void Dispose() + { + if (!IsDisposed) + { + if (InDebugMode) + { + Console.WriteLine(Log.ToString()); + } + Log.Dispose(); + + IsDisposed = true; + } + } + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private bool IsDisposed; + + /// Ensures that the analysis is done ignoring previous results. + private void DeleteSubDirectory(string path) + { + var directory = new DirectoryInfo(Path.Combine(ProjectFile.Directory!.FullName, path)); + + if (directory.Exists) + { + try + { + directory.Delete(true); + Log.WriteLine($"Deleted all files at {directory}"); + } + catch (Exception x) + { + Log.WriteLine(x); + } + } + } + + [Conditional("BinaryLog")] + private void AddBinaryLogger() + { + Analyzer.AddBinaryLogger(Path.Combine(@"C:\Temp\", Path.ChangeExtension(ProjectFile.Name, ".core.binlog"))); + } + + /// Sets to true when run in DEBUG mode. + [Conditional("DEBUG")] + private void DebugMode(ref bool inDebugMode) => inDebugMode = true; + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly bool InDebugMode; +} diff --git a/tests/Buildalyzer.Tests/TestTools/Context.cs b/tests/Buildalyzer.Tests/TestTools/Context.cs new file mode 100644 index 00000000..30818e0d --- /dev/null +++ b/tests/Buildalyzer.Tests/TestTools/Context.cs @@ -0,0 +1,23 @@ +using System.Diagnostics.Contracts; +using System.IO; + +namespace Buildalyzer.TestTools; + +public static class Context +{ + [Pure] + public static BuildalyzerTestContext ForProject(string path) => new(GetProjectPath(path)); + + private static FileInfo GetProjectPath(string file) + { + var location = new FileInfo(typeof(Context).Assembly.Location).Directory!; + return new FileInfo(Path.Combine( + location.FullName, + "..", + "..", + "..", + "..", + "projects", + file)); + } +} diff --git a/tests/Buildalyzer.Workspaces.Tests/Buildalyzer.Workspaces.Tests.csproj b/tests/Buildalyzer.Workspaces.Tests/Buildalyzer.Workspaces.Tests.csproj index d0a90108..d7239a1b 100644 --- a/tests/Buildalyzer.Workspaces.Tests/Buildalyzer.Workspaces.Tests.csproj +++ b/tests/Buildalyzer.Workspaces.Tests/Buildalyzer.Workspaces.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -22,6 +22,7 @@ + diff --git a/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs b/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs index d62f64d7..1c2597ff 100644 --- a/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs +++ b/tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs @@ -1,6 +1,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Buildalyzer.TestTools; +using FluentAssertions; using Microsoft.CodeAnalysis; using NUnit.Framework; using Shouldly; @@ -12,19 +14,14 @@ namespace Buildalyzer.Workspaces.Tests; public class ProjectAnalyzerExtensionsFixture { [Test] - public void LoadsWorkspace() + public void Loads_Workspace() { - // Given - SafeStringWriter log = new SafeStringWriter(); - IProjectAnalyzer analyzer = GetProjectAnalyzer(@"projects\SdkNetStandardProject\SdkNetStandardProject.csproj", log); + using var ctx = Context.ForProject(@"SdkNetStandardProject\SdkNetStandardProject.csproj"); - // When - Workspace workspace = analyzer.GetWorkspace(); + var workspace = ctx.Analyzer.GetWorkspace(); - // Then - string logged = log.ToString(); - logged.ShouldNotContain("Workspace failed"); - workspace.CurrentSolution.Projects.First().Documents.ShouldContain(x => x.Name == "Class1.cs", log.ToString()); + ctx.Log.ToString().Should().NotContain("Workspace failed"); + workspace.CurrentSolution.Projects.First().Documents.First().Should().BeEquivalentTo(new { Name = "Class1.cs" }); } [Test] From 91ce0b4c931bfae1947b84fd7b848cf7e152b04c Mon Sep 17 00:00:00 2001 From: Cyrille DUPUYDAUBY Date: Sun, 8 Sep 2024 07:05:29 +0200 Subject: [PATCH 3/5] Add support for azure function (#280) Co-authored-by: Pablo Monteiro --- src/Buildalyzer/Logging/EventProcessor.cs | 47 ++++++++++--------- .../Integration/SimpleProjectsFixture.cs | 23 +++++++++ .../AzureFunctionProject.csproj | 20 ++++++++ .../projects/AzureFunctionProject/Program.cs | 16 +++++++ .../AzureFunctionProject/TestFunction.cs | 22 +++++++++ tests/projects/AzureFunctionProject/host.json | 11 +++++ .../AzureFunctionProject/local.settings.json | 7 +++ 7 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 tests/projects/AzureFunctionProject/AzureFunctionProject.csproj create mode 100644 tests/projects/AzureFunctionProject/Program.cs create mode 100644 tests/projects/AzureFunctionProject/TestFunction.cs create mode 100644 tests/projects/AzureFunctionProject/host.json create mode 100644 tests/projects/AzureFunctionProject/local.settings.json diff --git a/src/Buildalyzer/Logging/EventProcessor.cs b/src/Buildalyzer/Logging/EventProcessor.cs index 9ac7ed26..6ea96b41 100644 --- a/src/Buildalyzer/Logging/EventProcessor.cs +++ b/src/Buildalyzer/Logging/EventProcessor.cs @@ -145,31 +145,36 @@ private void TargetFinished(object sender, TargetFinishedEventArgs e) private void MessageRaised(object sender, BuildMessageEventArgs e) { - AnalyzerResult result = _currentResult.Count == 0 ? null : _currentResult.Peek(); - if (result is object) + var result = _currentResult.Count == 0 ? null : _currentResult.Peek(); + if (result is not object || !IsRelevant()) { - // Process the command line arguments for the Fsc task - if (e.SenderName?.Equals("Fsc", StringComparison.OrdinalIgnoreCase) == true - && !string.IsNullOrWhiteSpace(e.Message) - && _targetStack.Any(x => x.TargetName == "CoreCompile") - && result.CompilerCommand is null) - { - result.ProcessFscCommandLine(e.Message); - } + return; + } - // Process the command line arguments for the Csc task - if (e is TaskCommandLineEventArgs cmd - && string.Equals(cmd.TaskName, "Csc", StringComparison.OrdinalIgnoreCase)) - { - result.ProcessCscCommandLine(cmd.CommandLine, _targetStack.Any(x => x.TargetName == "CoreCompile")); - } + // Process the command line arguments for the Fsc task + if (e.SenderName?.Equals("Fsc", StringComparison.OrdinalIgnoreCase) == true + && !string.IsNullOrWhiteSpace(e.Message) + && _targetStack.Any(x => x.TargetName == "CoreCompile") + && result.CompilerCommand is null) + { + result.ProcessFscCommandLine(e.Message); + } - if (e is TaskCommandLineEventArgs cmdVbc && - string.Equals(cmdVbc.TaskName, "Vbc", StringComparison.OrdinalIgnoreCase)) - { - result.ProcessVbcCommandLine(cmdVbc.CommandLine); - } + // Process the command line arguments for the Csc task + if (e is TaskCommandLineEventArgs cmd + && string.Equals(cmd.TaskName, "Csc", StringComparison.OrdinalIgnoreCase)) + { + result.ProcessCscCommandLine(cmd.CommandLine, _targetStack.Any(x => x.TargetName == "CoreCompile")); } + + if (e is TaskCommandLineEventArgs cmdVbc && + string.Equals(cmdVbc.TaskName, "Vbc", StringComparison.OrdinalIgnoreCase)) + { + result.ProcessVbcCommandLine(cmdVbc.CommandLine); + } + + bool IsRelevant() => string.IsNullOrEmpty(result.Command) || AnalyzerManager.NormalizePath(e.ProjectFile) == _projectFilePath; + } private void BuildFinished(object sender, BuildFinishedEventArgs e) diff --git a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs index b5a1aa18..ee84e12c 100644 --- a/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs +++ b/tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs @@ -224,6 +224,29 @@ public void WpfControlLibraryGetsSourceFiles() }.ShouldBeSubsetOf(sourceFiles.Select(x => Path.GetFileName(x)), log.ToString()); } + [Test] + [Platform("win")] + public void AzureFunctionSourceFiles() + { + // Given + StringWriter log = new StringWriter(); + IProjectAnalyzer analyzer = GetProjectAnalyzer(@"AzureFunctionProject\AzureFunctionProject.csproj", log); + + // When + IAnalyzerResults results = analyzer.Build(); + + // Then + IReadOnlyList sourceFiles = results.SingleOrDefault()?.SourceFiles; + sourceFiles.ShouldNotBeNull(log.ToString()); + new[] + { + "Program", + "TestFunction", + "AssemblyAttributes", + "AssemblyInfo" + }.ShouldBeSubsetOf(sourceFiles.Select(x => Path.GetFileName(x).Split('.').TakeLast(2).First()), log.ToString()); + } + [Test] public void MultiTargetingBuildAllTargetFrameworksGetsSourceFiles() { diff --git a/tests/projects/AzureFunctionProject/AzureFunctionProject.csproj b/tests/projects/AzureFunctionProject/AzureFunctionProject.csproj new file mode 100644 index 00000000..d1c5ea0b --- /dev/null +++ b/tests/projects/AzureFunctionProject/AzureFunctionProject.csproj @@ -0,0 +1,20 @@ + + + net6.0 + Exe + v4 + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + diff --git a/tests/projects/AzureFunctionProject/Program.cs b/tests/projects/AzureFunctionProject/Program.cs new file mode 100644 index 00000000..c83d88e1 --- /dev/null +++ b/tests/projects/AzureFunctionProject/Program.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.Hosting; + +namespace AzureFunctionProject; + +public class Program +{ + public static void Main() + { + var host = new HostBuilder() + .ConfigureServices(_ => + {}) + .Build(); + + host.Run(); + } +} \ No newline at end of file diff --git a/tests/projects/AzureFunctionProject/TestFunction.cs b/tests/projects/AzureFunctionProject/TestFunction.cs new file mode 100644 index 00000000..68d39b83 --- /dev/null +++ b/tests/projects/AzureFunctionProject/TestFunction.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.Azure.WebJobs; +using Microsoft.Extensions.Logging; + +namespace AzureFunctionProject; + +public class TestFunction +{ + [FunctionName(nameof(TestFunction))] + public async Task Run([CosmosDBTrigger( + databaseName: "databaseName", + collectionName: "collectionName", + ConnectionStringSetting = "", + LeaseCollectionName = "leases")]string input, + ILogger log) + { + if (input != null) + { + log.LogInformation("Document modified"); + } + } +} \ No newline at end of file diff --git a/tests/projects/AzureFunctionProject/host.json b/tests/projects/AzureFunctionProject/host.json new file mode 100644 index 00000000..beb2e402 --- /dev/null +++ b/tests/projects/AzureFunctionProject/host.json @@ -0,0 +1,11 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + } +} \ No newline at end of file diff --git a/tests/projects/AzureFunctionProject/local.settings.json b/tests/projects/AzureFunctionProject/local.settings.json new file mode 100644 index 00000000..30386e36 --- /dev/null +++ b/tests/projects/AzureFunctionProject/local.settings.json @@ -0,0 +1,7 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "", + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated" + } +} \ No newline at end of file From 6b24c6bae3c839439b7a7c5398e0f7221a525fe8 Mon Sep 17 00:00:00 2001 From: Pablo Monteiro Date: Sun, 8 Sep 2024 02:24:27 -0300 Subject: [PATCH 4/5] fix: updating MSBuildStructuredLog to compatibility version 18 --- src/Buildalyzer/Buildalyzer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Buildalyzer/Buildalyzer.csproj b/src/Buildalyzer/Buildalyzer.csproj index ad2674cb..49dd8961 100644 --- a/src/Buildalyzer/Buildalyzer.csproj +++ b/src/Buildalyzer/Buildalyzer.csproj @@ -17,7 +17,7 @@ - + From 5c55d2cd7b17a6630275d3bb91ffb7a1465a430a Mon Sep 17 00:00:00 2001 From: Pablo Monteiro Date: Sun, 8 Sep 2024 02:31:32 -0300 Subject: [PATCH 5/5] fix: azure devops pipe --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0f07943b..b18bf17c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,7 +5,7 @@ trigger: - '*' branches: include: - - main + - release/* pool: vmImage: 'ubuntu-latest'