From 78e08b58356e695b8cdb34bf5cc39942cba2d243 Mon Sep 17 00:00:00 2001 From: IBRAHIM NADA Date: Thu, 17 Oct 2024 12:20:21 +0300 Subject: [PATCH 01/25] adding MetadataReportsGenerator --- global.json | 4 +- .../Emitter.cs | 5 +- .../MetadataReportsGenerator.cs | 145 ++++++++++++++++++ .../Microsoft.Gen.MetadataExtractor.csproj | 46 ++++++ .../MetricsReportsGenerator.cs | 37 ++--- .../MetricsReportsHelpers.cs | 31 ++++ .../Microsoft.Extensions.AuditReports.csproj | 7 +- .../Microsoft.Extensions.AuditReports.props | 11 +- 8 files changed, 251 insertions(+), 35 deletions(-) create mode 100644 src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs create mode 100644 src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj create mode 100644 src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs diff --git a/global.json b/global.json index 23bae65d43c..f4c86c40c44 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "9.0.100-rtm.24479.2" + "version": "9.0.100-rc.2.24474.11" }, "tools": { - "dotnet": "9.0.100-rtm.24479.2", + "dotnet": "9.0.0-rc.2.24474.3", "runtimes": { "dotnet": [ "8.0.0", diff --git a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs index 999f8f39d03..5318a4a797b 100644 --- a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs +++ b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs @@ -21,11 +21,12 @@ public Emitter() } [SuppressMessage("Performance", "LA0002:Use 'Microsoft.Extensions.Text.NumericExtensions.ToInvariantString' for improved performance", Justification = "Can't use that in a generator")] - public string Emit(IReadOnlyCollection classifiedTypes, string assemblyName) + public string Emit(IReadOnlyCollection classifiedTypes, string assemblyName, bool includeName = true) { OutObject(() => { - OutNameValue("Name", assemblyName); + if (includeName) + OutNameValue("Name", assemblyName); OutArray("Types", () => { diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs new file mode 100644 index 00000000000..32e29871760 --- /dev/null +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -0,0 +1,145 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Composition; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.Gen; +using Microsoft.Gen.ComplianceReports; +using Microsoft.Gen.MetricsReports; +using Microsoft.Gen.Shared; +using Microsoft.Shared.DiagnosticIds; + + +namespace Microsoft.Gen.MetadataExtractor; + +/// +/// Generates reports for compliance & metrics annotations. +/// +[Generator] +public sealed class MetadataReportsGenerator : ISourceGenerator +{ + private const string GenerateMetadataMSBuildProperty = "build_property.GenerateMetadataReport"; + private const string ReportOutputPathMSBuildProperty = "build_property.MetadataReportOutputPath"; + private const string FallbackFileName = "MetadataReport.json"; + private readonly string _fileName; + + public void Initialize(GeneratorInitializationContext context) + { + context.RegisterForSyntaxNotifications(TypeDeclarationSyntaxReceiver.Create); + context.RegisterForSyntaxNotifications(ClassDeclarationSyntaxReceiver.Create); + } + + public MetadataReportsGenerator() + : this(FallbackFileName) + { + } + + internal MetadataReportsGenerator(string reportFileName) + { + _fileName = reportFileName; + } + + public void Execute(GeneratorExecutionContext context) + { + context.CancellationToken.ThrowIfCancellationRequested(); + if (!GeneratorUtilities.ShouldGenerateReport(context, GenerateMetadataMSBuildProperty)) + return; + + if ((context.SyntaxReceiver is not TypeDeclarationSyntaxReceiver || ((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver).TypeDeclarations.Count == 0) + && + (context.SyntaxReceiver is not ClassDeclarationSyntaxReceiver || ((ClassDeclarationSyntaxReceiver)context.SyntaxReceiver).ClassDeclarations.Count == 0)) + { + // nothing to do yet + return; + } + + if (!SymbolLoader.TryLoad(context.Compilation, out var symbolHolder)) + { + // Not eligible compilation + return; + } + + var options = context.AnalyzerConfigOptions.GlobalOptions; + var path = GeneratorUtilities.TryRetrieveOptionsValue(options, ReportOutputPathMSBuildProperty, out var reportOutputPath) + ? reportOutputPath! + : GeneratorUtilities.GetDefaultReportOutputPath(options); + if (string.IsNullOrWhiteSpace(path)) + { + // Report diagnostic: + var diagnostic = new DiagnosticDescriptor( + DiagnosticIds.AuditReports.AUDREPGEN000, + "MetricsReports generator couldn't resolve output path for the report. It won't be generated.", + "Both and MSBuild properties are not set. The report won't be generated.", + nameof(DiagnosticIds.AuditReports), + DiagnosticSeverity.Info, + isEnabledByDefault: true, + helpLinkUri: string.Format(CultureInfo.InvariantCulture, DiagnosticIds.UrlFormat, DiagnosticIds.AuditReports.AUDREPGEN000)); + + context.ReportDiagnostic(Diagnostic.Create(diagnostic, location: null)); + return; + } + + (string metricReport, string complianceReport) metadataReport = (string.Empty, string.Empty); + if ((((ClassDeclarationSyntaxReceiver)context.SyntaxReceiver)?.ClassDeclarations?.Count ?? 0) > 0) + { + metadataReport.metricReport = HandleMetricReportGeneration(context, (ClassDeclarationSyntaxReceiver)context.SyntaxReceiver); + } + + + if ((((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver)?.TypeDeclarations?.Count ?? 0) > 0) + { + metadataReport.complianceReport = HandleComplianceReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); + } + + + string combinedReport = "{ \"name\": " + context.Compilation.AssemblyName! + "," + + " \"metricReport\": " + + metadataReport.metricReport + + ", \"complianceReport\": " + + metadataReport.complianceReport + " }"; + +#pragma warning disable RS1035 // Do not use APIs banned for analyzers + File.WriteAllText(Path.Combine(path, _fileName), combinedReport, Encoding.UTF8); +#pragma warning restore RS1035 // Do not use APIs banned for analyzers + + } + + private string HandleMetricReportGeneration(GeneratorExecutionContext context, ClassDeclarationSyntaxReceiver receiver) + { + var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); + var meteringClasses = meteringParser.GetMetricClasses(receiver.ClassDeclarations); + + if (meteringClasses.Count == 0) + { + return string.Empty; + } + + _ = context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(ReportOutputPathMSBuildProperty, out var rootNamespace); + var reportedMetrics = MetricsReportsHelpers.MapToCommonModel(meteringClasses, rootNamespace); + var emitter = new MetricDefinitionEmitter(); + var report = emitter.GenerateReport(reportedMetrics, context.CancellationToken); + return report; + } + private string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) + { + _ = SymbolLoader.TryLoad(context.Compilation, out var symbolHolder); + var parser = new Parser(context.Compilation, symbolHolder!, context.CancellationToken); + var classifiedTypes = parser.GetClassifiedTypes(receiver.TypeDeclarations); + if (classifiedTypes.Count == 0) + { + // nothing to do + return string.Empty; + } + + var emitter = new Emitter(); + string report = emitter.Emit(classifiedTypes, context.Compilation.AssemblyName!, false); + + return report; + } +} diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj b/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj new file mode 100644 index 00000000000..5ecd4323e49 --- /dev/null +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj @@ -0,0 +1,46 @@ + + + Microsoft.Gen.MetadataExtractor + Produces compliance and metrics reports based on data classification annotations in the code. + Fundamentals + + + + cs + true + true + + + + normal + 98 + 85 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs index bc5df1036d1..aa364ad4b7f 100644 --- a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs @@ -50,14 +50,7 @@ public void Execute(GeneratorExecutionContext context) return; } - var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); - - var meteringClasses = meteringParser.GetMetricClasses(receiver.ClassDeclarations); - if (meteringClasses.Count == 0) - { - return; - } var options = context.AnalyzerConfigOptions.GlobalOptions; @@ -82,10 +75,19 @@ public void Execute(GeneratorExecutionContext context) return; } + var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); + var meteringClasses = meteringParser.GetMetricClasses(receiver.ClassDeclarations); + + if (meteringClasses.Count == 0) + { + return; + } + + _ = options.TryGetValue(RootNamespace, out var rootNamespace); + var reportedMetrics = MetricsReportsHelpers.MapToCommonModel(meteringClasses, rootNamespace); var emitter = new MetricDefinitionEmitter(); - var reportedMetrics = MapToCommonModel(meteringClasses, rootNamespace); var report = emitter.GenerateReport(reportedMetrics, context.CancellationToken); // File IO has been marked as banned for use in analyzers, and an alternate should be used instead @@ -96,22 +98,5 @@ public void Execute(GeneratorExecutionContext context) #pragma warning restore RS1035 // Do not use APIs banned for analyzers } - private static ReportedMetricClass[] MapToCommonModel(IReadOnlyList meteringClasses, string? rootNamespace) - { - var reportedMetrics = meteringClasses - .Select(meteringClass => new ReportedMetricClass( - Name: meteringClass.Name, - RootNamespace: rootNamespace ?? meteringClass.Namespace, - Constraints: meteringClass.Constraints, - Modifiers: meteringClass.Modifiers, - Methods: meteringClass.Methods.Select(meteringMethod => new ReportedMetricMethod( - MetricName: meteringMethod.MetricName ?? "(Missing Name)", - Summary: meteringMethod.XmlDefinition ?? "(Missing Summary)", - Kind: meteringMethod.InstrumentKind, - Dimensions: meteringMethod.TagKeys, - DimensionsDescriptions: meteringMethod.TagDescriptionDictionary)) - .ToArray())); - - return reportedMetrics.ToArray(); - } + } diff --git a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs new file mode 100644 index 00000000000..6ebd0053b3a --- /dev/null +++ b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Gen.Metrics.Model; + +namespace Microsoft.Gen.MetricsReports; +internal static class MetricsReportsHelpers +{ + internal static ReportedMetricClass[] MapToCommonModel(IReadOnlyList meteringClasses, string? rootNamespace) + { + var reportedMetrics = meteringClasses + .Select(meteringClass => new ReportedMetricClass( + Name: meteringClass.Name, + RootNamespace: rootNamespace ?? meteringClass.Namespace, + Constraints: meteringClass.Constraints, + Modifiers: meteringClass.Modifiers, + Methods: meteringClass.Methods.Select(meteringMethod => new ReportedMetricMethod( + MetricName: meteringMethod.MetricName ?? "(Missing Name)", + Summary: meteringMethod.XmlDefinition ?? "(Missing Summary)", + Kind: meteringMethod.InstrumentKind, + Dimensions: meteringMethod.TagKeys, + DimensionsDescriptions: meteringMethod.TagDescriptionDictionary)) + .ToArray())); + + return reportedMetrics.ToArray(); + } +} diff --git a/src/Packages/Microsoft.Extensions.AuditReports/Microsoft.Extensions.AuditReports.csproj b/src/Packages/Microsoft.Extensions.AuditReports/Microsoft.Extensions.AuditReports.csproj index e9a08ab521d..b579d8acb1b 100644 --- a/src/Packages/Microsoft.Extensions.AuditReports/Microsoft.Extensions.AuditReports.csproj +++ b/src/Packages/Microsoft.Extensions.AuditReports/Microsoft.Extensions.AuditReports.csproj @@ -14,13 +14,14 @@ n/a + - - + + - + diff --git a/src/Packages/Microsoft.Extensions.AuditReports/buildTransitive/Microsoft.Extensions.AuditReports.props b/src/Packages/Microsoft.Extensions.AuditReports/buildTransitive/Microsoft.Extensions.AuditReports.props index 978d52a35ea..b791bf81860 100644 --- a/src/Packages/Microsoft.Extensions.AuditReports/buildTransitive/Microsoft.Extensions.AuditReports.props +++ b/src/Packages/Microsoft.Extensions.AuditReports/buildTransitive/Microsoft.Extensions.AuditReports.props @@ -9,11 +9,18 @@ true + + false + true + + + + + - - + From 51d6362832d3c8bd01acded249d66b06a8de7c4a Mon Sep 17 00:00:00 2001 From: IBRAHIM NADA Date: Thu, 17 Oct 2024 12:44:57 +0300 Subject: [PATCH 02/25] fix format --- .../MetadataReportsGenerator.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index 32e29871760..455fd64d9bf 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -86,6 +86,7 @@ public void Execute(GeneratorExecutionContext context) } (string metricReport, string complianceReport) metadataReport = (string.Empty, string.Empty); + if ((((ClassDeclarationSyntaxReceiver)context.SyntaxReceiver)?.ClassDeclarations?.Count ?? 0) > 0) { metadataReport.metricReport = HandleMetricReportGeneration(context, (ClassDeclarationSyntaxReceiver)context.SyntaxReceiver); @@ -100,9 +101,9 @@ public void Execute(GeneratorExecutionContext context) string combinedReport = "{ \"name\": " + context.Compilation.AssemblyName! + "," + " \"metricReport\": " - + metadataReport.metricReport + + (string.IsNullOrEmpty(metadataReport.metricReport) ? "{}" : metadataReport.metricReport) + ", \"complianceReport\": " - + metadataReport.complianceReport + " }"; + + (string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport) + " }"; #pragma warning disable RS1035 // Do not use APIs banned for analyzers File.WriteAllText(Path.Combine(path, _fileName), combinedReport, Encoding.UTF8); @@ -110,7 +111,7 @@ public void Execute(GeneratorExecutionContext context) } - private string HandleMetricReportGeneration(GeneratorExecutionContext context, ClassDeclarationSyntaxReceiver receiver) + private static string HandleMetricReportGeneration(GeneratorExecutionContext context, ClassDeclarationSyntaxReceiver receiver) { var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); var meteringClasses = meteringParser.GetMetricClasses(receiver.ClassDeclarations); @@ -126,7 +127,7 @@ private string HandleMetricReportGeneration(GeneratorExecutionContext context, C var report = emitter.GenerateReport(reportedMetrics, context.CancellationToken); return report; } - private string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) + private static string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { _ = SymbolLoader.TryLoad(context.Compilation, out var symbolHolder); var parser = new Parser(context.Compilation, symbolHolder!, context.CancellationToken); From 37bf450d293aab5da835681b5d3baecac4fde79f Mon Sep 17 00:00:00 2001 From: IBRAHIM NADA Date: Thu, 17 Oct 2024 13:05:03 +0300 Subject: [PATCH 03/25] fix refs --- .../Microsoft.Gen.MetadataExtractor.csproj | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj b/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj index 5ecd4323e49..f5a55f07534 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj @@ -21,24 +21,33 @@ - - - - + + + + + + + + + + + + + - + - + From 9f3cb7db3beeb187e2d5114422e1f3a07bc68bd3 Mon Sep 17 00:00:00 2001 From: IBRAHIM NADA Date: Thu, 17 Oct 2024 13:19:13 +0300 Subject: [PATCH 04/25] revert dotnet version --- global.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index f4c86c40c44..23bae65d43c 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "9.0.100-rc.2.24474.11" + "version": "9.0.100-rtm.24479.2" }, "tools": { - "dotnet": "9.0.0-rc.2.24474.3", + "dotnet": "9.0.100-rtm.24479.2", "runtimes": { "dotnet": [ "8.0.0", From d4485471ac2e1350a48589425258d830d2360cb7 Mon Sep 17 00:00:00 2001 From: IBRAHIM NADA Date: Thu, 17 Oct 2024 13:52:52 +0300 Subject: [PATCH 05/25] remove unneeded using spaces --- .../MetricsReportsGenerator.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs index aa364ad4b7f..0f2e9937d2b 100644 --- a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsGenerator.cs @@ -1,14 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Gen.Metrics.Model; using Microsoft.Gen.Shared; using Microsoft.Shared.DiagnosticIds; @@ -21,7 +17,6 @@ public class MetricsReportsGenerator : ISourceGenerator private const string RootNamespace = "build_property.rootnamespace"; private const string ReportOutputPath = "build_property.MetricsReportOutputPath"; private const string FileName = "MetricsReport.json"; - private readonly string _fileName; public MetricsReportsGenerator() @@ -42,7 +37,6 @@ public void Initialize(GeneratorInitializationContext context) public void Execute(GeneratorExecutionContext context) { context.CancellationToken.ThrowIfCancellationRequested(); - if (context.SyntaxReceiver is not ClassDeclarationSyntaxReceiver receiver || receiver.ClassDeclarations.Count == 0 || !GeneratorUtilities.ShouldGenerateReport(context, GenerateMetricDefinitionReport)) @@ -50,8 +44,6 @@ public void Execute(GeneratorExecutionContext context) return; } - - var options = context.AnalyzerConfigOptions.GlobalOptions; var path = GeneratorUtilities.TryRetrieveOptionsValue(options, ReportOutputPath, out var reportOutputPath) @@ -69,23 +61,18 @@ public void Execute(GeneratorExecutionContext context) DiagnosticSeverity.Info, isEnabledByDefault: true, helpLinkUri: string.Format(CultureInfo.InvariantCulture, DiagnosticIds.UrlFormat, DiagnosticIds.AuditReports.AUDREPGEN000)); - context.ReportDiagnostic(Diagnostic.Create(diagnostic, location: null)); - return; } var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); var meteringClasses = meteringParser.GetMetricClasses(receiver.ClassDeclarations); - if (meteringClasses.Count == 0) { return; } - _ = options.TryGetValue(RootNamespace, out var rootNamespace); - var reportedMetrics = MetricsReportsHelpers.MapToCommonModel(meteringClasses, rootNamespace); var emitter = new MetricDefinitionEmitter(); var report = emitter.GenerateReport(reportedMetrics, context.CancellationToken); @@ -97,6 +84,4 @@ public void Execute(GeneratorExecutionContext context) File.WriteAllText(Path.Combine(path, _fileName), report, Encoding.UTF8); #pragma warning restore RS1035 // Do not use APIs banned for analyzers } - - } From 235aa181ab64ea356acbff2eee2112d179935db9 Mon Sep 17 00:00:00 2001 From: IBRAHIM NADA Date: Thu, 17 Oct 2024 14:29:22 +0300 Subject: [PATCH 06/25] remove un needed usings --- src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs | 2 ++ .../Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs index 5318a4a797b..cf5ac7272b8 100644 --- a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs +++ b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs @@ -26,7 +26,9 @@ public string Emit(IReadOnlyCollection classifiedTypes, string a OutObject(() => { if (includeName) + { OutNameValue("Name", assemblyName); + } OutArray("Types", () => { diff --git a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs index 6ebd0053b3a..ee610c0c032 100644 --- a/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs +++ b/src/Generators/Microsoft.Gen.MetricsReports/MetricsReportsHelpers.cs @@ -1,10 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Microsoft.Gen.Metrics.Model; namespace Microsoft.Gen.MetricsReports; From 54b2eaea195d068000b799bc91d2883ee28cad72 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 18:08:05 +0300 Subject: [PATCH 07/25] manual testing --- .../MetadataReportsGenerator.cs | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index 455fd64d9bf..ddc8e027b26 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -32,7 +32,6 @@ public sealed class MetadataReportsGenerator : ISourceGenerator public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(TypeDeclarationSyntaxReceiver.Create); - context.RegisterForSyntaxNotifications(ClassDeclarationSyntaxReceiver.Create); } public MetadataReportsGenerator() @@ -40,7 +39,7 @@ public MetadataReportsGenerator() { } - internal MetadataReportsGenerator(string reportFileName) + public MetadataReportsGenerator(string reportFileName) { _fileName = reportFileName; } @@ -51,19 +50,12 @@ public void Execute(GeneratorExecutionContext context) if (!GeneratorUtilities.ShouldGenerateReport(context, GenerateMetadataMSBuildProperty)) return; - if ((context.SyntaxReceiver is not TypeDeclarationSyntaxReceiver || ((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver).TypeDeclarations.Count == 0) - && - (context.SyntaxReceiver is not ClassDeclarationSyntaxReceiver || ((ClassDeclarationSyntaxReceiver)context.SyntaxReceiver).ClassDeclarations.Count == 0)) + if ((context.SyntaxReceiver is not TypeDeclarationSyntaxReceiver || ((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver).TypeDeclarations.Count == 0)) { // nothing to do yet return; } - if (!SymbolLoader.TryLoad(context.Compilation, out var symbolHolder)) - { - // Not eligible compilation - return; - } var options = context.AnalyzerConfigOptions.GlobalOptions; var path = GeneratorUtilities.TryRetrieveOptionsValue(options, ReportOutputPathMSBuildProperty, out var reportOutputPath) @@ -86,18 +78,8 @@ public void Execute(GeneratorExecutionContext context) } (string metricReport, string complianceReport) metadataReport = (string.Empty, string.Empty); - - if ((((ClassDeclarationSyntaxReceiver)context.SyntaxReceiver)?.ClassDeclarations?.Count ?? 0) > 0) - { - metadataReport.metricReport = HandleMetricReportGeneration(context, (ClassDeclarationSyntaxReceiver)context.SyntaxReceiver); - } - - - if ((((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver)?.TypeDeclarations?.Count ?? 0) > 0) - { - metadataReport.complianceReport = HandleComplianceReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); - } - + metadataReport.metricReport = HandleMetricReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); + metadataReport.complianceReport = HandleComplianceReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); string combinedReport = "{ \"name\": " + context.Compilation.AssemblyName! + "," + " \"metricReport\": " @@ -111,10 +93,10 @@ public void Execute(GeneratorExecutionContext context) } - private static string HandleMetricReportGeneration(GeneratorExecutionContext context, ClassDeclarationSyntaxReceiver receiver) + private static string HandleMetricReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); - var meteringClasses = meteringParser.GetMetricClasses(receiver.ClassDeclarations); + var meteringClasses = meteringParser.GetMetricClasses(receiver.TypeDeclarations); if (meteringClasses.Count == 0) { @@ -129,7 +111,10 @@ private static string HandleMetricReportGeneration(GeneratorExecutionContext con } private static string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { - _ = SymbolLoader.TryLoad(context.Compilation, out var symbolHolder); + if (!SymbolLoader.TryLoad(context.Compilation, out var symbolHolder)) + { + return string.Empty; + } var parser = new Parser(context.Compilation, symbolHolder!, context.CancellationToken); var classifiedTypes = parser.GetClassifiedTypes(receiver.TypeDeclarations); if (classifiedTypes.Count == 0) From 4581b209b485c3e251007e2502e8752602a7fdfc Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 19:15:08 +0300 Subject: [PATCH 08/25] adding test project --- .../Microsoft.Gen.MetadataExtractor.csproj | 4 ++- ...ft.Gen.MetadataExtractor.Unit.Tests.csproj | 33 +++++++++++++++++ ...ft.Gen.MetadataExtractor.Unit.Tests.csproj | 35 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj b/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj index f5a55f07534..a30f7e1eba4 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/Microsoft.Gen.MetadataExtractor.csproj @@ -51,5 +51,7 @@ - + + + diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj new file mode 100644 index 00000000000..34bfc75d1f1 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj @@ -0,0 +1,33 @@ + + + Microsoft.Gen.MetadataExtractor.Test + Unit tests for Microsoft.Gen.MetadataExtractor. + + + + true + + + + + + + TestClasses\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + GoldenReports\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + + + + + + + + + diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj new file mode 100644 index 00000000000..ec4289ec748 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj @@ -0,0 +1,35 @@ + + + Microsoft.Gen.MetadataExtractor.Test + Unit tests for Microsoft.Gen.MetadataExtractor. + + + + true + + + + + + + TestClasses\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + GoldenReports\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + + + + + + + + + + + From 2eadb5c01083a0d0abc55124addd1dad30561433 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 19:55:14 +0300 Subject: [PATCH 09/25] fix order for tests --- .../MetadataReportsGenerator.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index ddc8e027b26..f9a8696a5f3 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -81,11 +81,11 @@ public void Execute(GeneratorExecutionContext context) metadataReport.metricReport = HandleMetricReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); metadataReport.complianceReport = HandleComplianceReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); - string combinedReport = "{ \"name\": " + context.Compilation.AssemblyName! + "," + - " \"metricReport\": " - + (string.IsNullOrEmpty(metadataReport.metricReport) ? "{}" : metadataReport.metricReport) - + ", \"complianceReport\": " - + (string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport) + " }"; + string combinedReport = "{ \"Name\": " + context.Compilation.AssemblyName! + +", \"ComplianceReport\": " + + (string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport) + " }" + + " \"MetricReport\": " + + (string.IsNullOrEmpty(metadataReport.metricReport) ? "[]" : metadataReport.metricReport); #pragma warning disable RS1035 // Do not use APIs banned for analyzers File.WriteAllText(Path.Combine(path, _fileName), combinedReport, Encoding.UTF8); From 34a9f7e6f48b7259fd253f2f4d330749eb6a847a Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 19:55:21 +0300 Subject: [PATCH 10/25] adding test classes --- .../GoldenReports/Basic.json | 120 +++++++++ .../GoldenReports/Inheritance.json | 65 +++++ .../GoldenReports/LogMethod.json | 35 +++ .../MeterAttributedWithXmlDescriptions.json | 40 +++ ...tedWithXmlDescriptions_RecordProperty.json | 233 ++++++++++++++++++ ...mensionsAttributedWithXmlDescriptions.json | 43 ++++ .../GoldenReports/RecordProperty.json | 203 +++++++++++++++ .../TestClasses/Basic.cs | 34 +++ .../TestClasses/Inheritance.cs | 21 ++ .../TestClasses/LogMethod.cs | 12 + .../MeterAttributedWithXmlDescriptions.cs | 54 ++++ ...DimensionsAttributedWithXmlDescriptions.cs | 118 +++++++++ .../TestClasses/RecordProperty.cs | 40 +++ .../Unit/GeneratorTests.cs | 222 +++++++++++++++++ 14 files changed, 1240 insertions(+) create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Basic.cs create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Inheritance.cs create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/LogMethod.cs create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions.cs create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions.cs create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/RecordProperty.cs create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json new file mode 100644 index 00000000000..034679c47a9 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json @@ -0,0 +1,120 @@ + +{ + "Name": "test.dll", + "ComplianceReport": {"Types": [ + { + "Name": "Test.Basic", + "Members": [ + { + "Name": "F0", + "Type": "int", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F1", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C3", + "Notes": "Note 2" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "27", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "30" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "33", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "33" + } + ] + } + ] + } + ]}, + "MetricReport":[] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json new file mode 100644 index 00000000000..4d0b8277043 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json @@ -0,0 +1,65 @@ + +{ + "Name": "test.dll", + "ComplianceReport":{ + "Types": [ + { + "Name": "Test.Base", + "Members": [ + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2" + } + ] + } + ] + }, + { + "Name": "Test.Inherited", + "Members": [ + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2" + }, + { + "Name": "C3" + } + ] + } + ] + } + ]}, + "MetricReport":[] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json new file mode 100644 index 00000000000..2a428f255b5 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json @@ -0,0 +1,35 @@ + +{ + "Name": "test.dll", + "ComplianceReport":{"Types": [ + { + "Name": "Test.LogMethod", + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "11" + } + ] + } + ] + } + ]} + ,"MetricReport":[] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json new file mode 100644 index 00000000000..7a9fddfc843 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json @@ -0,0 +1,40 @@ +{ + "Name": "test.dll", + "ComplianceReport":{}, + "MetricReport":[ + { + "TestClasses": + [ + { + "TestClasses": + [ + { + "MetricName": "CounterWithDescription", + "MetricDescription": "CounterWithDescription description.", + "InstrumentName": "Counter" + }, + { + "MetricName": "HistogramWithDescription", + "MetricDescription": "HistogramWithDescription description.", + "InstrumentName": "Histogram" + }, + { + "MetricName": "HistogramWithWrongDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram" + }, + { + "MetricName": "ConstDescribedCounter", + "MetricDescription": "CreateConstDescribedCounter description.", + "InstrumentName": "Counter", + "Dimensions": { + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." + } + } + ] + } + ] + } + ] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json new file mode 100644 index 00000000000..ea1c80621c3 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json @@ -0,0 +1,233 @@ +{ + "Name": "test.dll", + "ComplianceReport":{ + "Types": [ + { + "Name": "Test.DerivedRecordProperty", + "Members": [ + { + "Name": "EqualityContract", + "Type": "System.Type", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "23", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 2" + }, + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ] + }, + { + "Name": "Test.RecordProperty", + "Members": [ + { + "Name": "F0", + "Type": "string", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "F2", + "Type": "int", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C3" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "29", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "29" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "32", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "32" + } + ] + } + ] + } + ]}, + "MetricReport":[ + { + "TestClasses": + [ + { + "MetricName": "CounterWithDescription", + "MetricDescription": "CounterWithDescription description.", + "InstrumentName": "Counter" + }, + { + "MetricName": "HistogramWithDescription", + "MetricDescription": "HistogramWithDescription description.", + "InstrumentName": "Histogram" + }, + { + "MetricName": "HistogramWithWrongDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram" + }, + { + "MetricName": "ConstDescribedCounter", + "MetricDescription": "CreateConstDescribedCounter description.", + "InstrumentName": "Counter", + "Dimensions": { + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." + } + } + ] + } + ] + +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json new file mode 100644 index 00000000000..3ebb55eac92 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json @@ -0,0 +1,43 @@ +{ + "Name": "test.dll", + "ComplianceReport":{}, + "MetricReport":[ + { + "TestClasses": + [ + { + "MetricName": "DescribedDimensionCounter", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "Dimension1": "Dimension1 description.", + "Dim1": "" + } + }, + { + "MetricName": "DescribedDimensionHistogram", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram", + "Dimensions": { + "Dimension2": "Dimension2 description.", + "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." + } + }, + { + "MetricName": "MyStrongTypeMetricWithDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "AnotherDimension": "Gets or sets anotherDimension.", + "MetricEnum": "Gets or sets MetricEnum.", + "Enum2": "Gets or sets MetricEnum2.", + "Dim2": "Gets or sets Dim2.", + "dim2FromAttribute": "Gets or sets SomeDim.", + "Dim4Struct": "Gets or sets Dim4Struct.", + "Dim5FromAttribute": "Gets or sets Dim5Struct." + } + } + ] + } + ] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json new file mode 100644 index 00000000000..e69e844feb5 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json @@ -0,0 +1,203 @@ + +{ + "Name": "test.dll", + "ComplianceReport":{ + "Types": [ + { + "Name": "Test.DerivedRecordProperty", + "Members": [ + { + "Name": "EqualityContract", + "Type": "System.Type", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "23", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 2" + }, + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ] + }, + { + "Name": "Test.RecordProperty", + "Members": [ + { + "Name": "F0", + "Type": "string", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "F2", + "Type": "int", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C3" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "29", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "29" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "32", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "32" + } + ] + } + ] + } + ]}, + "MetricReport":[] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Basic.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Basic.cs new file mode 100644 index 00000000000..a2dce688280 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Basic.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; + +namespace Test; + +interface IFoo +{ + [C4] + public int P0 { get; } +} + +[C1] +public class Basic : IFoo +{ + [C2(Notes = "Note 1")] + public int F0; + + [C2(Notes = null!)] + public int F1; + + [C3(Notes = "Note 2")] + public int P0 { get; } + + [C3] + public int P1 { get; } + + [LoggerMessage("Hello {user}")] + public void LogHello([C2(Notes = "Note 3")] string user, int port); + + [LoggerMessage("World {user}")] + public void LogWorld([C2] string user, int port); +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Inheritance.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Inheritance.cs new file mode 100644 index 00000000000..8c06e7682a1 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/Inheritance.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; + +namespace Test; + +public class Base +{ + [C1] + public int P0 { get; } + + [C2] + public virtual int P1 { get; } +} + +public class Inherited : Base +{ + [C3] + public override int P1 { get; } +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/LogMethod.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/LogMethod.cs new file mode 100644 index 00000000000..543f086b431 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/LogMethod.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; + +namespace Test; + +public class LogMethod +{ + [LoggerMessage("Hello {user}")] + public void LogHello([C2(Notes = "Note 3")] string user, int port); +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions.cs new file mode 100644 index 00000000000..0ab35cdcea1 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Metrics; +using Microsoft.Extensions.Diagnostics.Metrics; + +namespace TestClasses +{ + [SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "For testing emitter for classes with description for metrics.")] + internal static partial class MeterAttributedWithXmlDescriptions + { + /// + /// InClassDim description. + /// + private const string InClassDimensionName = "InClassDim"; + + /// + /// CounterWithDescription description. + /// + /// + /// + [Counter] + public static partial CounterWithDescription CreateDescribedCounter(Meter meter); + + /// + /// HistogramWithDescription description. + /// + /// + /// + [Histogram] + public static partial HistogramWithDescription CreateDescribedHistogram(Meter meter); + + /// no xml tags + [Histogram] + public static partial HistogramWithWrongDescription CreateWrongDescribedHistogram(Meter meter); + + /// + /// CreateConstDescribedCounter description. + /// + /// + /// + [Counter(MetricConstants.DimWithXmlComment, InClassDimensionName)] + public static partial ConstDescribedCounter CreateConstDescribedCounter(Meter meter); + } + + internal static class MetricConstants + { + /// + /// Dim4 description. + /// + public const string DimWithXmlComment = "Dim4"; + } +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions.cs new file mode 100644 index 00000000000..3777e60d353 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions.cs @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Metrics; +using Microsoft.Extensions.Diagnostics.Metrics; + +namespace TestClasses +{ + [SuppressMessage("Usage", "CA1801:Review unused parameters", + Justification = "For testing emitter for classes with description for metrics.")] + Justification = "Metrics generator tests")] + internal static partial class MeterDimensionsAttributedWithXmlDescriptions + { + public const string Dim1 = "Dim1"; + + [Counter(DescriptedDimensions.Dimension1, Dim1)] + public static partial DescribedDimensionCounter CreatePublicCounter(Meter meter); + + /// + /// DimensionDefinedInMetricClass description. + /// + public const string DimensionDefinedInMetricClass = "DimensionDefinedInMetricClass"; + + [Histogram(DescriptedDimensions.Dimension2, DimensionDefinedInMetricClass)] + public static partial DescribedDimensionHistogram CreatePublicHistogram(Meter meter); + + [Counter(typeof(DimensionForStrongTypes), Name = "MyStrongTypeMetricWithDescription")] + public static partial StrongTypeCounterWithDescriptedDimension CreateStrongTypeCounterWithDescribedDimensions(Meter meter); + } + +#pragma warning disable SA1402 // File may only contain a single type + + /// + /// DescriptedDimensions class description. + /// + internal static class DescriptedDimensions + { + /// + /// Dimension1 description. + /// + public const string Dimension1 = "Dimension1"; + + /// + /// Dimension2 description. + /// + public const string Dimension2 = "Dimension2"; + + /// + /// Dimension3 description. + /// + public const string Dimension3 = "Dimension3"; + } + + public class DimensionForStrongTypes + { + /// + /// Gets or sets anotherDimension. + /// + public string? AnotherDimension { get; set; } + + /// + /// Gets or sets MetricEnum. + /// + public MetricOperations MetricEnum { get; set; } + + /// + /// Gets or sets MetricEnum2. + /// + [TagName("Enum2")] + public MetricOperations MetricEnum2 { get; set; } + + /// + /// Gets or sets ChildDimensionsClass. + /// + public ChildClassDimensionForStrongTypes? ChildDimensionsClass { get; set; } + + /// + /// Gets or sets ChildDimensionsStruct. + /// + public DimensionForStrongTypesDimensionsStruct ChildDimensionsStruct { get; set; } + } + + public enum MetricOperations + { + Unknown = 0, + Operation1 = 1, + } + + public class ChildClassDimensionForStrongTypes + { + /// + /// Gets or sets Dim2. + /// + public string? Dim2 { get; set; } + + /// + /// Gets or sets SomeDim. + /// + [TagName("dim2FromAttribute")] + public string? SomeDim; + } + + public struct DimensionForStrongTypesDimensionsStruct + { + /// + /// Gets or sets Dim4Struct. + /// + public string Dim4Struct { get; set; } + + /// + /// Gets or sets Dim5Struct. + /// + [TagName("Dim5FromAttribute")] + public string Dim5Struct { get; set; } + } +#pragma warning restore SA1402 // File may only contain a single type +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/RecordProperty.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/RecordProperty.cs new file mode 100644 index 00000000000..b38940ed8bf --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/RecordProperty.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; + +namespace Test; + +interface IBar +{ + [C4] + public int P0 { get; } +} + +public record RecordProperty([C2] string F0, string F1, [C3] int F2) : IBar +{ + [C2(Notes = "Note 1")] + public int F3; + + [C2(Notes = null!)] + public int F4; + + [C3(Notes = "Note 3")] + public int P0 { get; }; + + [C3] + public int P1 { get; }; + + [LoggerMessage("Hello {user}")] + public void LogHello([C3(Notes = "Note 3")] string user, int port); + + [LoggerMessage("World {user}")] + public void LogWorld([C2] string user, int port); +} + +[C1] +public record DerivedRecordProperty : RecordProperty +{ + [C2(Notes = "Note 2")] + public override int P0 { get; }; +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs new file mode 100644 index 00000000000..64a80887d57 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -0,0 +1,222 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Logging; +using Microsoft.Gen.Shared; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Gen.MetadataExtractor.Unit.Tests; + +public class GeneratorTests(ITestOutputHelper output) +{ + private const string ReportFilename = "MetricsReport.json"; + private const string TestTaxonomy = @" + using Microsoft.Extensions.Compliance.Classification; + + public sealed class C1Attribute : DataClassificationAttribute + { + public C1Attribute(new DataClassification(""TAX"", 1)) { } + } + + public sealed class C2Attribute : DataClassificationAttribute + { + public C2Attribute(new DataClassification(""TAX"", 2)) { } + } + + public sealed class C3Attribute : DataClassificationAttribute + { + public C3Attribute(new DataClassification(""TAX"", 4)) { } + } + + public sealed class C4Attribute : DataClassificationAttribute + { + public C4Attribute(new DataClassification(""TAX"", 8)) { } + } + "; + + [Fact] + public void GeneratorShouldNotDoAnythingIfGeneralExecutionContextDoesNotHaveClassDeclarationSyntaxReceiver() + { + GeneratorExecutionContext defaultGeneralExecutionContext = default; + new MetadataReportsGenerator().Execute(defaultGeneralExecutionContext); + + Assert.Null(defaultGeneralExecutionContext.SyntaxReceiver); + } + + [Theory] + [CombinatorialData] + public async Task TestAll(bool useExplicitReportPath) + { + Dictionary? options = useExplicitReportPath + ? new() { ["build_property.MetricsReportOutputPath"] = Directory.GetCurrentDirectory() } + : null; + + foreach (var inputFile in Directory.GetFiles("TestClasses")) + { + var stem = Path.GetFileNameWithoutExtension(inputFile); + var goldenFileName = Path.ChangeExtension(stem, ".json"); + var goldenReportPath = Path.Combine("GoldenReports", goldenFileName); + + var generatedReportPath = Path.Combine(Directory.GetCurrentDirectory(), ReportFilename); + + if (File.Exists(goldenReportPath)) + { + var d = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); + Assert.Empty(d); + + var golden = await File.ReadAllTextAsync(goldenReportPath); + var generated = await File.ReadAllTextAsync(generatedReportPath); + + if (golden != generated) + { + output.WriteLine($"MISMATCH: golden report {goldenReportPath}, generated {generatedReportPath}"); + output.WriteLine("----"); + output.WriteLine("golden:"); + output.WriteLine(golden); + output.WriteLine("----"); + output.WriteLine("generated:"); + output.WriteLine(generated); + output.WriteLine("----"); + } + + File.Delete(generatedReportPath); + Assert.Equal(golden, generated); + } + else + { + // generate the golden file if it doesn't already exist + output.WriteLine($"Generating golden report: {goldenReportPath}"); + _ = await RunGenerator(await File.ReadAllTextAsync(inputFile), options, reportFileName: goldenFileName); + } + } + } + + [Fact] + public async Task ShouldNot_Generate_WhenDisabledViaConfig() + { + var inputFile = Directory.GetFiles("TestClasses").First(); + var options = new Dictionary + { + ["build_property.GenerateMetricsReport"] = bool.FalseString, + ["build_property.MetricsReportOutputPath"] = Path.GetTempPath() + }; + + var d = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); + Assert.Empty(d); + Assert.False(File.Exists(Path.Combine(Path.GetTempPath(), ReportFilename))); + } + + [Theory] + [CombinatorialData] + public async Task Should_EmitWarning_WhenPathUnavailable(bool isReportPathProvided) + { + var inputFile = Directory.GetFiles("TestClasses").First(); + var options = new Dictionary + { + ["build_property.outputpath"] = string.Empty + }; + + if (isReportPathProvided) + { + options.Add("build_property.MetricsReportOutputPath", string.Empty); + } + + var diags = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); + var diag = Assert.Single(diags); + Assert.Equal("AUDREPGEN000", diag.Id); + Assert.Equal(DiagnosticSeverity.Info, diag.Severity); + } + + [Fact] + public async Task Should_UseProjectDir_WhenOutputPathIsRelative() + { + var projectDir = Path.GetTempPath(); + var outputPath = Guid.NewGuid().ToString(); + var fullReportPath = Path.Combine(projectDir, outputPath); + Directory.CreateDirectory(fullReportPath); + + try + { + var inputFile = Directory.GetFiles("TestClasses").First(); + var options = new Dictionary + { + ["build_property.projectdir"] = projectDir, + ["build_property.outputpath"] = outputPath + }; + + var diags = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); + Assert.Empty(diags); + Assert.True(File.Exists(Path.Combine(fullReportPath, ReportFilename))); + } + finally + { + Directory.Delete(fullReportPath, recursive: true); + } + } + + private static async Task> RunGenerator( + string code, + Dictionary? analyzerOptions = null, + CancellationToken cancellationToken = default, + string? reportFileName = null) + { + Assembly[] refs = + [ + Assembly.GetAssembly(typeof(Meter))!, + Assembly.GetAssembly(typeof(CounterAttribute))!, + Assembly.GetAssembly(typeof(HistogramAttribute))!, + Assembly.GetAssembly(typeof(GaugeAttribute))!, + Assembly.GetAssembly(typeof(ILogger))!, + Assembly.GetAssembly(typeof(LoggerMessageAttribute))!, + Assembly.GetAssembly(typeof(Extensions.Compliance.Classification.DataClassification))!, + ]; + + var generator = reportFileName is null + ? new MetadataReportsGenerator() + : new MetadataReportsGenerator(reportFileName); + + var (d, _) = await RoslynTestUtils.RunGenerator( + generator, + refs, + new[] { code , TestTaxonomy }, + new OptionsProvider(analyzerOptions), + includeBaseReferences: true, + cancellationToken: cancellationToken).ConfigureAwait(false); + + return d; + } + + private sealed class Options : AnalyzerConfigOptions + { + private readonly Dictionary _options; + + public Options(Dictionary? analyzerOptions) + { + _options = analyzerOptions ?? []; + _options.TryAdd("build_property.GenerateMetadataReport", bool.TrueString); + _options.TryAdd("build_property.MetadataReportOutputPath", Directory.GetCurrentDirectory()); + } + + public override bool TryGetValue(string key, out string value) + => _options.TryGetValue(key, out value!); + } + + private sealed class OptionsProvider(Dictionary? analyzerOptions) : AnalyzerConfigOptionsProvider + { + public override AnalyzerConfigOptions GlobalOptions => new Options(analyzerOptions); + public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) => throw new NotSupportedException(); + public override AnalyzerConfigOptions GetOptions(AdditionalText textFile) => throw new NotSupportedException(); + } +} From 12f8a24eb831a27ee347ccea89d2bde6d2a64f82 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 19:58:05 +0300 Subject: [PATCH 11/25] extra testing class --- ...tributedWithXmlDescriptions_LogMethod.json | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json new file mode 100644 index 00000000000..660fa814dc4 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json @@ -0,0 +1,72 @@ +{ + "Name": "test.dll", + "ComplianceReport":{"Types": [ + { + "Name": "Test.LogMethod", + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "11" + } + ] + } + ] + } +]}, + "MetricReport":[ + { + "TestClasses": + [ + { + "MetricName": "DescribedDimensionCounter", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "Dimension1": "Dimension1 description.", + "Dim1": "" + } + }, + { + "MetricName": "DescribedDimensionHistogram", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram", + "Dimensions": { + "Dimension2": "Dimension2 description.", + "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." + } + }, + { + "MetricName": "MyStrongTypeMetricWithDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "AnotherDimension": "Gets or sets anotherDimension.", + "MetricEnum": "Gets or sets MetricEnum.", + "Enum2": "Gets or sets MetricEnum2.", + "Dim2": "Gets or sets Dim2.", + "dim2FromAttribute": "Gets or sets SomeDim.", + "Dim4Struct": "Gets or sets Dim4Struct.", + "Dim5FromAttribute": "Gets or sets Dim5Struct." + } + } + ] + } + ] +} From fff7be2bb62b130b85c07dc5f63cea1c8adff135 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 20:45:52 +0300 Subject: [PATCH 12/25] adding test methods --- .../GoldenReports/Basic.json | 235 +++++++++--------- .../GoldenReports/Inheritance.json | 9 +- .../GoldenReports/LogMethod.json | 10 +- ...mensionsAttributedWithXmlDescriptions.json | 70 +++--- ...AttributedWithXmlDescriptions_LogMethod.cs | 129 ++++++++++ .../Unit/GeneratorTests.cs | 24 +- 6 files changed, 299 insertions(+), 178 deletions(-) create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.cs diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json index 034679c47a9..fb76379b234 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json @@ -1,120 +1,121 @@ - { - "Name": "test.dll", - "ComplianceReport": {"Types": [ - { - "Name": "Test.Basic", - "Members": [ - { - "Name": "F0", - "Type": "int", - "File": "src-0.cs", - "Line": "18", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, - { - "Name": "F1", - "Type": "int", - "File": "src-0.cs", - "Line": "21", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "11", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C3", - "Notes": "Note 2" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "27", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C3" - } - ] - } - ], - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "30", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "30" - } - ] - }, - { - "Name": "LogWorld", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "33", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "33" - } - ] - } + "Name": "test.dll", + "ComplianceReport": { + "Types": [ + { + "Name": "Test.Basic", + "Members": [ + { + "Name": "F0", + "Type": "int", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 1" + } ] - } - ]}, - "MetricReport":[] + }, + { + "Name": "F1", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C3", + "Notes": "Note 2" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "27", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "30" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "33", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "33" + } + ] + } + ] + } + ] + }, + "MetricReport": [] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json index 4d0b8277043..66c2213995d 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json @@ -1,7 +1,5 @@ - +{ "Name": "test.dll", "ComplianceReport": { - "Name": "test.dll", - "ComplianceReport":{ "Types": [ { "Name": "Test.Base", @@ -60,6 +58,5 @@ } ] } - ]}, - "MetricReport":[] -} + ] +} , "MetricReport": [] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json index 2a428f255b5..93a684313d6 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json @@ -1,7 +1,6 @@ - +{ "Name": "test.dll", "ComplianceReport": { - "Name": "test.dll", - "ComplianceReport":{"Types": [ + "Types": [ { "Name": "Test.LogMethod", "Logging Methods": [ @@ -30,6 +29,5 @@ } ] } - ]} - ,"MetricReport":[] -} + ] +} , "MetricReport": [] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json index 3ebb55eac92..04f5f8ec331 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json @@ -1,43 +1,31 @@ -{ - "Name": "test.dll", - "ComplianceReport":{}, - "MetricReport":[ - { - "TestClasses": - [ - { - "MetricName": "DescribedDimensionCounter", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "Dimension1": "Dimension1 description.", - "Dim1": "" - } - }, - { - "MetricName": "DescribedDimensionHistogram", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram", - "Dimensions": { - "Dimension2": "Dimension2 description.", - "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." - } - }, - { - "MetricName": "MyStrongTypeMetricWithDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "AnotherDimension": "Gets or sets anotherDimension.", - "MetricEnum": "Gets or sets MetricEnum.", - "Enum2": "Gets or sets MetricEnum2.", - "Dim2": "Gets or sets Dim2.", - "dim2FromAttribute": "Gets or sets SomeDim.", - "Dim4Struct": "Gets or sets Dim4Struct.", - "Dim5FromAttribute": "Gets or sets Dim5Struct." - } +{ "Name": "test.dll", "ComplianceReport": {} , "MetricReport": [ + { + "C:\Users\ibrra\source\repos\extensions\artifacts\bin\Microsoft.Gen.MetadataExtractor.Unit.Tests\Debug\net9.0": + [ + { + "MetricName": "CounterWithDescription", + "MetricDescription": "CounterWithDescription description.", + "InstrumentName": "Counter" + }, + { + "MetricName": "HistogramWithDescription", + "MetricDescription": "HistogramWithDescription description.", + "InstrumentName": "Histogram" + }, + { + "MetricName": "HistogramWithWrongDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram" + }, + { + "MetricName": "ConstDescribedCounter", + "MetricDescription": "CreateConstDescribedCounter description.", + "InstrumentName": "Counter", + "Dimensions": { + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." } - ] - } + } ] -} + } + ] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.cs new file mode 100644 index 00000000000..faf6044bd9a --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.cs @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Metrics; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Logging; + +namespace Test{ + +public class LogMethod +{ + [LoggerMessage("Hello {user}")] + public void LogHello([C2(Notes = "Note 3")] string user, int port); +} +} + + +namespace TestClasses +{ + [SuppressMessage("Usage", "CA1801:Review unused parameters", + Justification = "For testing emitter for classes with description for metrics.")] + Justification = "Metrics generator tests")] + internal static partial class MeterDimensionsAttributedWithXmlDescriptions + { + public const string Dim1 = "Dim1"; + + [Counter(DescriptedDimensions.Dimension1, Dim1)] + public static partial DescribedDimensionCounter CreatePublicCounter(Meter meter); + + /// + /// DimensionDefinedInMetricClass description. + /// + public const string DimensionDefinedInMetricClass = "DimensionDefinedInMetricClass"; + + [Histogram(DescriptedDimensions.Dimension2, DimensionDefinedInMetricClass)] + public static partial DescribedDimensionHistogram CreatePublicHistogram(Meter meter); + + [Counter(typeof(DimensionForStrongTypes), Name = "MyStrongTypeMetricWithDescription")] + public static partial StrongTypeCounterWithDescriptedDimension CreateStrongTypeCounterWithDescribedDimensions(Meter meter); + } + +#pragma warning disable SA1402 // File may only contain a single type + + /// + /// DescriptedDimensions class description. + /// + internal static class DescriptedDimensions + { + /// + /// Dimension1 description. + /// + public const string Dimension1 = "Dimension1"; + + /// + /// Dimension2 description. + /// + public const string Dimension2 = "Dimension2"; + + /// + /// Dimension3 description. + /// + public const string Dimension3 = "Dimension3"; + } + + public class DimensionForStrongTypes + { + /// + /// Gets or sets anotherDimension. + /// + public string? AnotherDimension { get; set; } + + /// + /// Gets or sets MetricEnum. + /// + public MetricOperations MetricEnum { get; set; } + + /// + /// Gets or sets MetricEnum2. + /// + [TagName("Enum2")] + public MetricOperations MetricEnum2 { get; set; } + + /// + /// Gets or sets ChildDimensionsClass. + /// + public ChildClassDimensionForStrongTypes? ChildDimensionsClass { get; set; } + + /// + /// Gets or sets ChildDimensionsStruct. + /// + public DimensionForStrongTypesDimensionsStruct ChildDimensionsStruct { get; set; } + } + + public enum MetricOperations + { + Unknown = 0, + Operation1 = 1, + } + + public class ChildClassDimensionForStrongTypes + { + /// + /// Gets or sets Dim2. + /// + public string? Dim2 { get; set; } + + /// + /// Gets or sets SomeDim. + /// + [TagName("dim2FromAttribute")] + public string? SomeDim; + } + + public struct DimensionForStrongTypesDimensionsStruct + { + /// + /// Gets or sets Dim4Struct. + /// + public string Dim4Struct { get; set; } + + /// + /// Gets or sets Dim5Struct. + /// + [TagName("Dim5FromAttribute")] + public string Dim5Struct { get; set; } + } +#pragma warning restore SA1402 // File may only contain a single type +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index 64a80887d57..bc9fbe61565 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -21,7 +22,7 @@ namespace Microsoft.Gen.MetadataExtractor.Unit.Tests; public class GeneratorTests(ITestOutputHelper output) { - private const string ReportFilename = "MetricsReport.json"; + private const string ReportFilename = "MetadataReport.json"; private const string TestTaxonomy = @" using Microsoft.Extensions.Compliance.Classification; @@ -60,7 +61,7 @@ public void GeneratorShouldNotDoAnythingIfGeneralExecutionContextDoesNotHaveClas public async Task TestAll(bool useExplicitReportPath) { Dictionary? options = useExplicitReportPath - ? new() { ["build_property.MetricsReportOutputPath"] = Directory.GetCurrentDirectory() } + ? new() { ["build_property.MetadataReportOutputPath"] = Directory.GetCurrentDirectory() } : null; foreach (var inputFile in Directory.GetFiles("TestClasses")) @@ -92,6 +93,13 @@ public async Task TestAll(bool useExplicitReportPath) } File.Delete(generatedReportPath); + + golden = Regex.Replace(golden, @"\s+", ""); + generated = Regex.Replace(generated, @"\s+", ""); + + golden = golden.Replace("\r\n", "\n"); + generated = generated.Replace("\r\n", "\n"); + Assert.Equal(golden, generated); } else @@ -109,8 +117,8 @@ public async Task ShouldNot_Generate_WhenDisabledViaConfig() var inputFile = Directory.GetFiles("TestClasses").First(); var options = new Dictionary { - ["build_property.GenerateMetricsReport"] = bool.FalseString, - ["build_property.MetricsReportOutputPath"] = Path.GetTempPath() + ["build_property.GenerateMetadataReport"] = bool.FalseString, + ["build_property.MetadataReportOutputPath"] = Path.GetTempPath() }; var d = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); @@ -125,12 +133,12 @@ public async Task Should_EmitWarning_WhenPathUnavailable(bool isReportPathProvid var inputFile = Directory.GetFiles("TestClasses").First(); var options = new Dictionary { - ["build_property.outputpath"] = string.Empty + ["build_property.MetadataReportOutputPath"] = string.Empty }; if (isReportPathProvided) { - options.Add("build_property.MetricsReportOutputPath", string.Empty); + options.Add("build_property.MetadataReportOutputPath", string.Empty); } var diags = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); @@ -153,7 +161,7 @@ public async Task Should_UseProjectDir_WhenOutputPathIsRelative() var options = new Dictionary { ["build_property.projectdir"] = projectDir, - ["build_property.outputpath"] = outputPath + ["build_property.MetadataReportOutputPath"] = outputPath }; var diags = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); @@ -190,7 +198,7 @@ private static async Task> RunGenerator( var (d, _) = await RoslynTestUtils.RunGenerator( generator, refs, - new[] { code , TestTaxonomy }, + new[] { code, TestTaxonomy }, new OptionsProvider(analyzerOptions), includeBaseReferences: true, cancellationToken: cancellationToken).ConfigureAwait(false); From a9bf590ebac35ebe4101d3b817417aed7e89b546 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 20:46:04 +0300 Subject: [PATCH 13/25] methods --- .../MetadataReportsGenerator.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index f9a8696a5f3..cab4fc4ba18 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -67,7 +67,7 @@ public void Execute(GeneratorExecutionContext context) var diagnostic = new DiagnosticDescriptor( DiagnosticIds.AuditReports.AUDREPGEN000, "MetricsReports generator couldn't resolve output path for the report. It won't be generated.", - "Both and MSBuild properties are not set. The report won't be generated.", + "Both and MSBuild properties are not set. The report won't be generated.", nameof(DiagnosticIds.AuditReports), DiagnosticSeverity.Info, isEnabledByDefault: true, @@ -81,11 +81,11 @@ public void Execute(GeneratorExecutionContext context) metadataReport.metricReport = HandleMetricReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); metadataReport.complianceReport = HandleComplianceReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); - string combinedReport = "{ \"Name\": " + context.Compilation.AssemblyName! - +", \"ComplianceReport\": " - + (string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport) + " }" + string combinedReport = "{ \"Name\": \"" + context.Compilation.AssemblyName! + + "\", \"ComplianceReport\": " + + (string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport) + " ," + " \"MetricReport\": " - + (string.IsNullOrEmpty(metadataReport.metricReport) ? "[]" : metadataReport.metricReport); + + (string.IsNullOrEmpty(metadataReport.metricReport) ? "[]" : metadataReport.metricReport) + " }"; #pragma warning disable RS1035 // Do not use APIs banned for analyzers File.WriteAllText(Path.Combine(path, _fileName), combinedReport, Encoding.UTF8); From 6709e787a18a9a72129935d184e2c02e04304874 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 21:29:59 +0300 Subject: [PATCH 14/25] adding testng methods --- .../MetadataReportsGenerator.cs | 3 +- .../MeterAttributedWithXmlDescriptions.json | 38 +- ...tedWithXmlDescriptions_RecordProperty.json | 409 +++++++++--------- ...mensionsAttributedWithXmlDescriptions.json | 73 ++-- ...tributedWithXmlDescriptions_LogMethod.json | 127 +++--- .../GoldenReports/RecordProperty.json | 396 ++++++++--------- ...butedWithXmlDescriptions_RecordProperty.cs | 92 ++++ .../Unit/GeneratorTests.cs | 3 +- 8 files changed, 620 insertions(+), 521 deletions(-) create mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions_RecordProperty.cs diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index cab4fc4ba18..22b4b57e11c 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -26,6 +26,7 @@ public sealed class MetadataReportsGenerator : ISourceGenerator { private const string GenerateMetadataMSBuildProperty = "build_property.GenerateMetadataReport"; private const string ReportOutputPathMSBuildProperty = "build_property.MetadataReportOutputPath"; + private const string RootNamespace = "build_property.rootnamespace"; private const string FallbackFileName = "MetadataReport.json"; private readonly string _fileName; @@ -103,7 +104,7 @@ private static string HandleMetricReportGeneration(GeneratorExecutionContext con return string.Empty; } - _ = context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(ReportOutputPathMSBuildProperty, out var rootNamespace); + _ = context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(RootNamespace, out var rootNamespace); var reportedMetrics = MetricsReportsHelpers.MapToCommonModel(meteringClasses, rootNamespace); var emitter = new MetricDefinitionEmitter(); var report = emitter.GenerateReport(reportedMetrics, context.CancellationToken); diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json index 7a9fddfc843..d7e07d80257 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json @@ -1,40 +1,34 @@ { "Name": "test.dll", - "ComplianceReport":{}, - "MetricReport":[ + "ComplianceReport": {}, + "MetricReport": [ { - "TestClasses": - [ - { - "TestClasses": - [ - { + "TestClasses": [ + { "MetricName": "CounterWithDescription", "MetricDescription": "CounterWithDescription description.", "InstrumentName": "Counter" - }, - { + }, + { "MetricName": "HistogramWithDescription", "MetricDescription": "HistogramWithDescription description.", "InstrumentName": "Histogram" - }, - { + }, + { "MetricName": "HistogramWithWrongDescription", "MetricDescription": "(Missing Summary)", "InstrumentName": "Histogram" - }, - { + }, + { "MetricName": "ConstDescribedCounter", "MetricDescription": "CreateConstDescribedCounter description.", "InstrumentName": "Counter", "Dimensions": { - "Dim4": "Dim4 description.", - "InClassDim": "InClassDim description." - } - } - ] - } - ] + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." + } + } + ] } - ] + ] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json index ea1c80621c3..aa2017f23e2 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json @@ -1,233 +1,232 @@ { "Name": "test.dll", - "ComplianceReport":{ - "Types": [ + "ComplianceReport": { + "Types": [ { - "Name": "Test.DerivedRecordProperty", - "Members": [ - { - "Name": "EqualityContract", - "Type": "System.Type", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C1" - } - ] - }, + "Name": "Test.DerivedRecordProperty", + "Members": [ + { + "Name": "EqualityContract", + "Type": "System.Type", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "24", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "27", + "Classifications": [ { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "17", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] + "Name": "C1" }, { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "20", - "Classifications": [ - { - "Name": "C2" - } - ] + "Name": "C2", + "Notes": "Note 2" }, { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "23", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2", - "Notes": "Note 2" - }, - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] + "Name": "C3", + "Notes": "Note 3" }, { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "26", - "Classifications": [ - { - "Name": "C3" - } - ] + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C3" } - ] + ] + } + ] }, { - "Name": "Test.RecordProperty", - "Members": [ - { - "Name": "F0", - "Type": "string", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C2" - } - ] - }, + "Name": "Test.RecordProperty", + "Members": [ + { + "Name": "F0", + "Type": "string", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ { - "Name": "F2", - "Type": "int", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C3" - } - ] - }, + "Name": "C2" + } + ] + }, + { + "Name": "F2", + "Type": "int", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "17", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, + "Name": "C3" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "24", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "15", + "Classifications": [ { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "20", - "Classifications": [ - { - "Name": "C2" - } - ] + "Name": "C3", + "Notes": "Note 3" }, { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "11", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "33", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + } + ] }, { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "26", - "Classifications": [ - { - "Name": "C3" - } - ] + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "33" } - ], - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "29", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "29" - } - ] + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "36", + "Classifications": [ + { + "Name": "C2" + } + ] }, { - "Name": "LogWorld", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "32", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "32" - } - ] + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "36" } - ] + ] + } + ] } - ]}, - "MetricReport":[ + ] + }, + "MetricReport": [ { - "TestClasses": - [ - { - "MetricName": "CounterWithDescription", - "MetricDescription": "CounterWithDescription description.", - "InstrumentName": "Counter" - }, - { - "MetricName": "HistogramWithDescription", - "MetricDescription": "HistogramWithDescription description.", - "InstrumentName": "Histogram" - }, - { - "MetricName": "HistogramWithWrongDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram" - }, - { - "MetricName": "ConstDescribedCounter", - "MetricDescription": "CreateConstDescribedCounter description.", - "InstrumentName": "Counter", - "Dimensions": { - "Dim4": "Dim4 description.", - "InClassDim": "InClassDim description." - } - } - ] + "TestClasses": [ + { + "MetricName": "CounterWithDescription", + "MetricDescription": "CounterWithDescription description.", + "InstrumentName": "Counter" + }, + { + "MetricName": "HistogramWithDescription", + "MetricDescription": "HistogramWithDescription description.", + "InstrumentName": "Histogram" + }, + { + "MetricName": "HistogramWithWrongDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram" + }, + { + "MetricName": "ConstDescribedCounter", + "MetricDescription": "CreateConstDescribedCounter description.", + "InstrumentName": "Counter", + "Dimensions": { + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." + } + } + ] } - ] - + ] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json index 04f5f8ec331..d89fed4735d 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json @@ -1,31 +1,42 @@ -{ "Name": "test.dll", "ComplianceReport": {} , "MetricReport": [ - { - "C:\Users\ibrra\source\repos\extensions\artifacts\bin\Microsoft.Gen.MetadataExtractor.Unit.Tests\Debug\net9.0": - [ - { - "MetricName": "CounterWithDescription", - "MetricDescription": "CounterWithDescription description.", - "InstrumentName": "Counter" - }, - { - "MetricName": "HistogramWithDescription", - "MetricDescription": "HistogramWithDescription description.", - "InstrumentName": "Histogram" - }, - { - "MetricName": "HistogramWithWrongDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram" - }, - { - "MetricName": "ConstDescribedCounter", - "MetricDescription": "CreateConstDescribedCounter description.", - "InstrumentName": "Counter", - "Dimensions": { - "Dim4": "Dim4 description.", - "InClassDim": "InClassDim description." - } - } - ] - } - ] } +{ + "Name": "test.dll", + "ComplianceReport": {}, + "MetricReport": [ + { + "TestClasses": [ + { + "MetricName": "DescribedDimensionCounter", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "Dimension1": "Dimension1 description.", + "Dim1": "" + } + }, + { + "MetricName": "DescribedDimensionHistogram", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram", + "Dimensions": { + "Dimension2": "Dimension2 description.", + "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." + } + }, + { + "MetricName": "MyStrongTypeMetricWithDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "AnotherDimension": "Gets or sets anotherDimension.", + "MetricEnum": "Gets or sets MetricEnum.", + "Enum2": "Gets or sets MetricEnum2.", + "Dim2": "Gets or sets Dim2.", + "dim2FromAttribute": "Gets or sets SomeDim.", + "Dim4Struct": "Gets or sets Dim4Struct.", + "Dim5FromAttribute": "Gets or sets Dim5Struct." + } + } + ] + } + ] +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json index 660fa814dc4..c713a05d34f 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json @@ -1,72 +1,73 @@ { "Name": "test.dll", - "ComplianceReport":{"Types": [ - { + "ComplianceReport": { + "Types": [ + { "Name": "Test.LogMethod", "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "11", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "11" - } + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } ] - } + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "14" + } + ] + } ] - } -]}, - "MetricReport":[ + } + ] + }, + "MetricReport": [ { - "TestClasses": - [ - { - "MetricName": "DescribedDimensionCounter", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "Dimension1": "Dimension1 description.", - "Dim1": "" - } - }, - { - "MetricName": "DescribedDimensionHistogram", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram", - "Dimensions": { - "Dimension2": "Dimension2 description.", - "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." - } - }, - { - "MetricName": "MyStrongTypeMetricWithDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "AnotherDimension": "Gets or sets anotherDimension.", - "MetricEnum": "Gets or sets MetricEnum.", - "Enum2": "Gets or sets MetricEnum2.", - "Dim2": "Gets or sets Dim2.", - "dim2FromAttribute": "Gets or sets SomeDim.", - "Dim4Struct": "Gets or sets Dim4Struct.", - "Dim5FromAttribute": "Gets or sets Dim5Struct." - } - } - ] + "TestClasses": [ + { + "MetricName": "DescribedDimensionCounter", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "Dimension1": "Dimension1 description.", + "Dim1": "" + } + }, + { + "MetricName": "DescribedDimensionHistogram", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram", + "Dimensions": { + "Dimension2": "Dimension2 description.", + "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." + } + }, + { + "MetricName": "MyStrongTypeMetricWithDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "AnotherDimension": "Gets or sets anotherDimension.", + "MetricEnum": "Gets or sets MetricEnum.", + "MetricEnum2": "Gets or sets MetricEnum2.", + "Dim2": "Gets or sets Dim2.", + "SomeDim": "Gets or sets SomeDim.", + "Dim4Struct": "Gets or sets Dim4Struct.", + "Dim5Struct": "Gets or sets Dim5Struct." + } + } + ] } - ] + ] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json index e69e844feb5..bd03c28dcd1 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json @@ -1,203 +1,203 @@ - { - "Name": "test.dll", - "ComplianceReport":{ + "Name": "test.dll", + "ComplianceReport": { "Types": [ - { - "Name": "Test.DerivedRecordProperty", - "Members": [ - { - "Name": "EqualityContract", - "Type": "System.Type", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C1" - } - ] - }, - { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "17", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, - { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "20", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "23", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2", - "Notes": "Note 2" - }, - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "26", - "Classifications": [ - { - "Name": "C3" - } - ] - } + { + "Name": "Test.DerivedRecordProperty", + "Members": [ + { + "Name": "EqualityContract", + "Type": "System.Type", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C1" + } ] - }, - { - "Name": "Test.RecordProperty", - "Members": [ - { - "Name": "F0", - "Type": "string", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "F2", - "Type": "int", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C3" - } - ] - }, - { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "17", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, - { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "20", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "11", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "26", - "Classifications": [ - { - "Name": "C3" - } - ] - } - ], - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "29", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "29" - } - ] - }, - { - "Name": "LogWorld", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "32", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "32" - } - ] - } + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } ] - } - ]}, - "MetricReport":[] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "23", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 2" + }, + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ] + }, + { + "Name": "Test.RecordProperty", + "Members": [ + { + "Name": "F0", + "Type": "string", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "F2", + "Type": "int", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C3" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "29", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "29" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "32", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "32" + } + ] + } + ] + } + ] + }, + "MetricReport": [] } diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions_RecordProperty.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions_RecordProperty.cs new file mode 100644 index 00000000000..424309b82b0 --- /dev/null +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/TestClasses/MeterAttributedWithXmlDescriptions_RecordProperty.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Metrics; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Logging; + + +namespace Test{ + +interface IBar +{ + [C4] + public int P0 { get; } +} + +public record RecordProperty([C2] string F0, string F1, [C3] int F2) : IBar +{ + [C2(Notes = "Note 1")] + public int F3; + + [C2(Notes = null!)] + public int F4; + + [C3(Notes = "Note 3")] + public int P0 { get; }; + + [C3] + public int P1 { get; }; + + [LoggerMessage("Hello {user}")] + public void LogHello([C3(Notes = "Note 3")] string user, int port); + + [LoggerMessage("World {user}")] + public void LogWorld([C2] string user, int port); +} + +[C1] +public record DerivedRecordProperty : RecordProperty +{ + [C2(Notes = "Note 2")] + public override int P0 { get; }; +} +} +namespace TestClasses +{ + [SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "For testing emitter for classes with description for metrics.")] + internal static partial class MeterAttributedWithXmlDescriptions + { + /// + /// InClassDim description. + /// + private const string InClassDimensionName = "InClassDim"; + + /// + /// CounterWithDescription description. + /// + /// + /// + [Counter] + public static partial CounterWithDescription CreateDescribedCounter(Meter meter); + + /// + /// HistogramWithDescription description. + /// + /// + /// + [Histogram] + public static partial HistogramWithDescription CreateDescribedHistogram(Meter meter); + + /// no xml tags + [Histogram] + public static partial HistogramWithWrongDescription CreateWrongDescribedHistogram(Meter meter); + + /// + /// CreateConstDescribedCounter description. + /// + /// + /// + [Counter(MetricConstants.DimWithXmlComment, InClassDimensionName)] + public static partial ConstDescribedCounter CreateConstDescribedCounter(Meter meter); + } + + internal static class MetricConstants + { + /// + /// Dim4 description. + /// + public const string DimWithXmlComment = "Dim4"; + } +} diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index bc9fbe61565..2d4c1910bc4 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -118,7 +118,8 @@ public async Task ShouldNot_Generate_WhenDisabledViaConfig() var options = new Dictionary { ["build_property.GenerateMetadataReport"] = bool.FalseString, - ["build_property.MetadataReportOutputPath"] = Path.GetTempPath() + ["build_property.MetadataReportOutputPath"] = Path.GetTempPath(), + ["build_property.rootnamespace"] = "TestClasses" }; var d = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); From b72031dafa00b86769405a5cabf841731323d09c Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 21:46:07 +0300 Subject: [PATCH 15/25] adding tests --- .../Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index 2d4c1910bc4..43e4545f046 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -134,7 +134,7 @@ public async Task Should_EmitWarning_WhenPathUnavailable(bool isReportPathProvid var inputFile = Directory.GetFiles("TestClasses").First(); var options = new Dictionary { - ["build_property.MetadataReportOutputPath"] = string.Empty + ["build_property.outputpath"] = string.Empty }; if (isReportPathProvided) @@ -162,7 +162,7 @@ public async Task Should_UseProjectDir_WhenOutputPathIsRelative() var options = new Dictionary { ["build_property.projectdir"] = projectDir, - ["build_property.MetadataReportOutputPath"] = outputPath + ["build_property.MetadataReportOutputPath"] = fullReportPath }; var diags = await RunGenerator(await File.ReadAllTextAsync(inputFile), options); @@ -215,7 +215,7 @@ public Options(Dictionary? analyzerOptions) { _options = analyzerOptions ?? []; _options.TryAdd("build_property.GenerateMetadataReport", bool.TrueString); - _options.TryAdd("build_property.MetadataReportOutputPath", Directory.GetCurrentDirectory()); + // _options.TryAdd("build_property.MetadataReportOutputPath", Directory.GetCurrentDirectory()); } public override bool TryGetValue(string key, out string value) From e3158553d6f314347aa6e35bf13c0cd90ecf3bb8 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 22:00:09 +0300 Subject: [PATCH 16/25] finshing tests --- .../MetadataReportsGenerator.cs | 8 ++++++-- .../Unit/GeneratorTests.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index 22b4b57e11c..9a4340955e6 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -48,8 +48,13 @@ public MetadataReportsGenerator(string reportFileName) public void Execute(GeneratorExecutionContext context) { context.CancellationToken.ThrowIfCancellationRequested(); - if (!GeneratorUtilities.ShouldGenerateReport(context, GenerateMetadataMSBuildProperty)) + + if (context.SyntaxReceiver is not TypeDeclarationSyntaxReceiver || + ((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver).TypeDeclarations.Count == 0 || + !GeneratorUtilities.ShouldGenerateReport(context, GenerateMetadataMSBuildProperty)) + { return; + } if ((context.SyntaxReceiver is not TypeDeclarationSyntaxReceiver || ((TypeDeclarationSyntaxReceiver)context.SyntaxReceiver).TypeDeclarations.Count == 0)) { @@ -57,7 +62,6 @@ public void Execute(GeneratorExecutionContext context) return; } - var options = context.AnalyzerConfigOptions.GlobalOptions; var path = GeneratorUtilities.TryRetrieveOptionsValue(options, ReportOutputPathMSBuildProperty, out var reportOutputPath) ? reportOutputPath! diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index 43e4545f046..aa2fda5a1f3 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -215,7 +215,7 @@ public Options(Dictionary? analyzerOptions) { _options = analyzerOptions ?? []; _options.TryAdd("build_property.GenerateMetadataReport", bool.TrueString); - // _options.TryAdd("build_property.MetadataReportOutputPath", Directory.GetCurrentDirectory()); + _options.TryAdd("build_property.outputpath", Directory.GetCurrentDirectory()); } public override bool TryGetValue(string key, out string value) From 0e635526294b646db91565b0b8a917c0783a1d5e Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 22:28:46 +0300 Subject: [PATCH 17/25] remove duplication --- ...ft.Gen.MetadataExtractor.Unit.Tests.csproj | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj deleted file mode 100644 index ec4289ec748..00000000000 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/Microsoft.Gen.MetadataExtractor.Unit.Tests/Microsoft.Gen.MetadataExtractor.Unit.Tests.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - Microsoft.Gen.MetadataExtractor.Test - Unit tests for Microsoft.Gen.MetadataExtractor. - - - - true - - - - - - - TestClasses\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - - GoldenReports\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - - - - - - - - - - - - From ff82288784e52caaedd1ea2121405d85ddf7c972 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Thu, 17 Oct 2024 22:45:17 +0300 Subject: [PATCH 18/25] multi blanlines removed --- .../MetadataReportsGenerator.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index 9a4340955e6..7950be55cd1 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -1,21 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Composition; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using Microsoft.CodeAnalysis; -using Microsoft.Gen; using Microsoft.Gen.ComplianceReports; using Microsoft.Gen.MetricsReports; using Microsoft.Gen.Shared; using Microsoft.Shared.DiagnosticIds; - namespace Microsoft.Gen.MetadataExtractor; /// @@ -114,12 +108,14 @@ private static string HandleMetricReportGeneration(GeneratorExecutionContext con var report = emitter.GenerateReport(reportedMetrics, context.CancellationToken); return report; } + private static string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { if (!SymbolLoader.TryLoad(context.Compilation, out var symbolHolder)) { return string.Empty; } + var parser = new Parser(context.Compilation, symbolHolder!, context.CancellationToken); var classifiedTypes = parser.GetClassifiedTypes(receiver.TypeDeclarations); if (classifiedTypes.Count == 0) From bfbab5bc1e58d935b54c0ca2a9b69ee4ed1d1774 Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 07:45:39 +0300 Subject: [PATCH 19/25] fixing format --- .../Emitter.cs | 1 + .../MetadataReportsGenerator.cs | 27 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs index cf5ac7272b8..55e235d1e87 100644 --- a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs +++ b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs @@ -25,6 +25,7 @@ public string Emit(IReadOnlyCollection classifiedTypes, string a { OutObject(() => { + // this is only for not displaying a name as part of ComplianceReport properties,it should be at the root of the report, defaulted to true for beackward compatibility if (includeName) { OutNameValue("Name", assemblyName); diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index 7950be55cd1..199698bc256 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -80,18 +80,27 @@ public void Execute(GeneratorExecutionContext context) metadataReport.metricReport = HandleMetricReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); metadataReport.complianceReport = HandleComplianceReportGeneration(context, (TypeDeclarationSyntaxReceiver)context.SyntaxReceiver); - string combinedReport = "{ \"Name\": \"" + context.Compilation.AssemblyName! - + "\", \"ComplianceReport\": " - + (string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport) + " ," - + " \"MetricReport\": " - + (string.IsNullOrEmpty(metadataReport.metricReport) ? "[]" : metadataReport.metricReport) + " }"; + StringBuilder reportStringBuilder = new StringBuilder() + .Append("{ \"Name\": \"") + .Append(context.Compilation.AssemblyName!) + .Append("\", \"ComplianceReport\": ") + .Append((string.IsNullOrEmpty(metadataReport.complianceReport) ? "{}" : metadataReport.complianceReport)) + .Append(" ,") + .Append(" \"MetricReport\": ") + .Append((string.IsNullOrEmpty(metadataReport.metricReport) ? "[]" : metadataReport.metricReport) + " }"); #pragma warning disable RS1035 // Do not use APIs banned for analyzers - File.WriteAllText(Path.Combine(path, _fileName), combinedReport, Encoding.UTF8); + File.WriteAllText(Path.Combine(path, _fileName), reportStringBuilder.ToString(), Encoding.UTF8); #pragma warning restore RS1035 // Do not use APIs banned for analyzers } + /// + /// used to generate the report for metrics annotations. + /// + /// The GeneratorExecutionContext. + /// The TypeDeclarationSyntaxReceiver. + /// string report as json or String.Empty. private static string HandleMetricReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { var meteringParser = new Metrics.Parser(context.Compilation, context.ReportDiagnostic, context.CancellationToken); @@ -109,6 +118,12 @@ private static string HandleMetricReportGeneration(GeneratorExecutionContext con return report; } + /// + /// used to generate the report for compliance annotations. + /// + /// The GeneratorExecutionContext. + /// The TypeDeclarationSyntaxReceiver. + /// string report as json or String.Empty. private static string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { if (!SymbolLoader.TryLoad(context.Compilation, out var symbolHolder)) From 7a6abb60580dc3c3731d2d280c0b35e0d98acbaa Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 08:29:21 +0300 Subject: [PATCH 20/25] add comments --- src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs index 55e235d1e87..2e8b63dcae7 100644 --- a/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs +++ b/src/Generators/Microsoft.Gen.ComplianceReports/Emitter.cs @@ -21,7 +21,7 @@ public Emitter() } [SuppressMessage("Performance", "LA0002:Use 'Microsoft.Extensions.Text.NumericExtensions.ToInvariantString' for improved performance", Justification = "Can't use that in a generator")] - public string Emit(IReadOnlyCollection classifiedTypes, string assemblyName, bool includeName = true) + public string Emit(IReadOnlyCollection classifiedTypes, string assemblyName, bool includeName = true) // show or hide assemblyName in the report,defaulted to true. { OutObject(() => { From 197bdb99bca177bfd898d53c4489f7a116d7952b Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 08:46:02 +0300 Subject: [PATCH 21/25] adding comment for methods --- .../MetadataReportsGenerator.cs | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index 199698bc256..eb6d3fedde5 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -24,21 +24,37 @@ public sealed class MetadataReportsGenerator : ISourceGenerator private const string FallbackFileName = "MetadataReport.json"; private readonly string _fileName; - public void Initialize(GeneratorInitializationContext context) - { - context.RegisterForSyntaxNotifications(TypeDeclarationSyntaxReceiver.Create); - } + /// + /// Initializes a new instance of the class. + /// public MetadataReportsGenerator() : this(FallbackFileName) { } + /// + /// Initializes a new instance of the class. + /// + /// The report file name. public MetadataReportsGenerator(string reportFileName) { _fileName = reportFileName; } + /// + /// Initializes the generator. + /// + /// The generator initialization context. + public void Initialize(GeneratorInitializationContext context) + { + context.RegisterForSyntaxNotifications(TypeDeclarationSyntaxReceiver.Create); + } + + /// + /// Generates reports for compliance & metrics annotations. + /// + /// The generator execution context. public void Execute(GeneratorExecutionContext context) { context.CancellationToken.ThrowIfCancellationRequested(); @@ -98,8 +114,8 @@ public void Execute(GeneratorExecutionContext context) /// /// used to generate the report for metrics annotations. /// - /// The GeneratorExecutionContext. - /// The TypeDeclarationSyntaxReceiver. + /// The generator execution context. + /// The typeDeclaration syntax receiver. /// string report as json or String.Empty. private static string HandleMetricReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { @@ -121,8 +137,8 @@ private static string HandleMetricReportGeneration(GeneratorExecutionContext con /// /// used to generate the report for compliance annotations. /// - /// The GeneratorExecutionContext. - /// The TypeDeclarationSyntaxReceiver. + /// The generator execution context. + /// The type declaration syntax receiver. /// string report as json or String.Empty. private static string HandleComplianceReportGeneration(GeneratorExecutionContext context, TypeDeclarationSyntaxReceiver receiver) { From b08ad678a85029a3694000edb97521a66445e82a Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 08:58:12 +0300 Subject: [PATCH 22/25] remove multi lines --- .../Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs index eb6d3fedde5..8471e9d1cc3 100644 --- a/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs +++ b/src/Generators/Microsoft.Gen.MetadataExtractor/MetadataReportsGenerator.cs @@ -24,7 +24,6 @@ public sealed class MetadataReportsGenerator : ISourceGenerator private const string FallbackFileName = "MetadataReport.json"; private readonly string _fileName; - /// /// Initializes a new instance of the class. /// From da8a021f96ecc27eb63ff4ea005dfe4c9296420e Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 11:47:36 +0300 Subject: [PATCH 23/25] run tests & adding comments --- .../GoldenReports/Basic.json | 231 +++++---- .../GoldenReports/Inheritance.json | 4 +- .../GoldenReports/LogMethod.json | 4 +- .../MeterAttributedWithXmlDescriptions.json | 59 ++- ...tedWithXmlDescriptions_RecordProperty.json | 448 +++++++++--------- ...mensionsAttributedWithXmlDescriptions.json | 75 ++- ...tributedWithXmlDescriptions_LogMethod.json | 132 +++--- .../GoldenReports/RecordProperty.json | 393 ++++++++------- .../Unit/GeneratorTests.cs | 6 - 9 files changed, 665 insertions(+), 687 deletions(-) diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json index fb76379b234..2e9867dc658 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Basic.json @@ -1,121 +1,118 @@ +{ "Name": "test.dll", "ComplianceReport": { - "Name": "test.dll", - "ComplianceReport": { "Types": [ - { - "Name": "Test.Basic", - "Members": [ - { - "Name": "F0", - "Type": "int", - "File": "src-0.cs", - "Line": "18", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2", - "Notes": "Note 1" - } + { + "Name": "Test.Basic", + "Members": [ + { + "Name": "F0", + "Type": "int", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F1", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C3", + "Notes": "Note 2" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "27", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "30" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "33", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "33" + } + ] + } ] - }, - { - "Name": "F1", - "Type": "int", - "File": "src-0.cs", - "Line": "21", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "11", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C3", - "Notes": "Note 2" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "27", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C3" - } - ] - } - ], - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "30", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "30" - } - ] - }, - { - "Name": "LogWorld", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "33", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "33" - } - ] - } - ] - } + } ] - }, - "MetricReport": [] -} +} , "MetricReport": [] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json index 66c2213995d..084f52598d5 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/Inheritance.json @@ -1,4 +1,4 @@ -{ "Name": "test.dll", "ComplianceReport": +{ "Name": "test.dll", "ComplianceReport": { "Types": [ { @@ -59,4 +59,4 @@ ] } ] -} , "MetricReport": [] } +} , "MetricReport": [] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json index 93a684313d6..8f14aa9c92f 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/LogMethod.json @@ -1,4 +1,4 @@ -{ "Name": "test.dll", "ComplianceReport": +{ "Name": "test.dll", "ComplianceReport": { "Types": [ { @@ -30,4 +30,4 @@ ] } ] -} , "MetricReport": [] } +} , "MetricReport": [] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json index d7e07d80257..c89592c2bf7 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions.json @@ -1,34 +1,31 @@ -{ - "Name": "test.dll", - "ComplianceReport": {}, - "MetricReport": [ +{ "Name": "test.dll", "ComplianceReport": {} , "MetricReport": [ + { + "TestClasses": + [ { - "TestClasses": [ - { - "MetricName": "CounterWithDescription", - "MetricDescription": "CounterWithDescription description.", - "InstrumentName": "Counter" - }, - { - "MetricName": "HistogramWithDescription", - "MetricDescription": "HistogramWithDescription description.", - "InstrumentName": "Histogram" - }, - { - "MetricName": "HistogramWithWrongDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram" - }, - { - "MetricName": "ConstDescribedCounter", - "MetricDescription": "CreateConstDescribedCounter description.", - "InstrumentName": "Counter", - "Dimensions": { - "Dim4": "Dim4 description.", - "InClassDim": "InClassDim description." - } - } - ] + "MetricName": "CounterWithDescription", + "MetricDescription": "CounterWithDescription description.", + "InstrumentName": "Counter" + }, + { + "MetricName": "HistogramWithDescription", + "MetricDescription": "HistogramWithDescription description.", + "InstrumentName": "Histogram" + }, + { + "MetricName": "HistogramWithWrongDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram" + }, + { + "MetricName": "ConstDescribedCounter", + "MetricDescription": "CreateConstDescribedCounter description.", + "InstrumentName": "Counter", + "Dimensions": { + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." + } } ] -} + } +] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json index aa2017f23e2..270a4b1d979 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterAttributedWithXmlDescriptions_RecordProperty.json @@ -1,232 +1,230 @@ -{ - "Name": "test.dll", - "ComplianceReport": { +{ "Name": "test.dll", "ComplianceReport": +{ "Types": [ - { - "Name": "Test.DerivedRecordProperty", - "Members": [ - { - "Name": "EqualityContract", - "Type": "System.Type", - "File": "src-0.cs", - "Line": "18", - "Classifications": [ - { - "Name": "C1" - } - ] - }, - { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "21", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, - { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "24", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "27", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2", - "Notes": "Note 2" - }, - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "30", - "Classifications": [ - { - "Name": "C3" - } - ] - } - ] - }, - { - "Name": "Test.RecordProperty", - "Members": [ - { - "Name": "F0", - "Type": "string", - "File": "src-0.cs", - "Line": "18", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "F2", - "Type": "int", - "File": "src-0.cs", - "Line": "18", - "Classifications": [ - { - "Name": "C3" - } - ] - }, - { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "21", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, - { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "24", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "15", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "30", - "Classifications": [ - { - "Name": "C3" - } - ] - } - ], - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "33", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "33" - } - ] - }, - { - "Name": "LogWorld", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "36", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "36" - } - ] - } - ] - } - ] - }, - "MetricReport": [ - { - "TestClasses": [ - { - "MetricName": "CounterWithDescription", - "MetricDescription": "CounterWithDescription description.", - "InstrumentName": "Counter" - }, { - "MetricName": "HistogramWithDescription", - "MetricDescription": "HistogramWithDescription description.", - "InstrumentName": "Histogram" - }, - { - "MetricName": "HistogramWithWrongDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram" + "Name": "Test.DerivedRecordProperty", + "Members": [ + { + "Name": "EqualityContract", + "Type": "System.Type", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "24", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "27", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 2" + }, + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ] }, { - "MetricName": "ConstDescribedCounter", - "MetricDescription": "CreateConstDescribedCounter description.", - "InstrumentName": "Counter", - "Dimensions": { - "Dim4": "Dim4 description.", - "InClassDim": "InClassDim description." - } + "Name": "Test.RecordProperty", + "Members": [ + { + "Name": "F0", + "Type": "string", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "F2", + "Type": "int", + "File": "src-0.cs", + "Line": "18", + "Classifications": [ + { + "Name": "C3" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "21", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "24", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "15", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "30", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "33", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "33" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "36", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "36" + } + ] + } + ] } - ] + ] +} , "MetricReport": [ + { + "TestClasses": + [ + { + "MetricName": "CounterWithDescription", + "MetricDescription": "CounterWithDescription description.", + "InstrumentName": "Counter" + }, + { + "MetricName": "HistogramWithDescription", + "MetricDescription": "HistogramWithDescription description.", + "InstrumentName": "Histogram" + }, + { + "MetricName": "HistogramWithWrongDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram" + }, + { + "MetricName": "ConstDescribedCounter", + "MetricDescription": "CreateConstDescribedCounter description.", + "InstrumentName": "Counter", + "Dimensions": { + "Dim4": "Dim4 description.", + "InClassDim": "InClassDim description." + } } ] -} + } +] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json index d89fed4735d..3c58e7c0670 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions.json @@ -1,42 +1,39 @@ -{ - "Name": "test.dll", - "ComplianceReport": {}, - "MetricReport": [ +{ "Name": "test.dll", "ComplianceReport": {} , "MetricReport": [ + { + "TestClasses": + [ { - "TestClasses": [ - { - "MetricName": "DescribedDimensionCounter", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "Dimension1": "Dimension1 description.", - "Dim1": "" - } - }, - { - "MetricName": "DescribedDimensionHistogram", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram", - "Dimensions": { - "Dimension2": "Dimension2 description.", - "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." - } - }, - { - "MetricName": "MyStrongTypeMetricWithDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "AnotherDimension": "Gets or sets anotherDimension.", - "MetricEnum": "Gets or sets MetricEnum.", - "Enum2": "Gets or sets MetricEnum2.", - "Dim2": "Gets or sets Dim2.", - "dim2FromAttribute": "Gets or sets SomeDim.", - "Dim4Struct": "Gets or sets Dim4Struct.", - "Dim5FromAttribute": "Gets or sets Dim5Struct." - } - } - ] + "MetricName": "DescribedDimensionCounter", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "Dimension1": "Dimension1 description.", + "Dim1": "" + } + }, + { + "MetricName": "DescribedDimensionHistogram", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram", + "Dimensions": { + "Dimension2": "Dimension2 description.", + "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." + } + }, + { + "MetricName": "MyStrongTypeMetricWithDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "AnotherDimension": "Gets or sets anotherDimension.", + "MetricEnum": "Gets or sets MetricEnum.", + "Enum2": "Gets or sets MetricEnum2.", + "Dim2": "Gets or sets Dim2.", + "dim2FromAttribute": "Gets or sets SomeDim.", + "Dim4Struct": "Gets or sets Dim4Struct.", + "Dim5FromAttribute": "Gets or sets Dim5Struct." + } } ] -} + } +] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json index c713a05d34f..021cf13caa6 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/MeterDimensionsAttributedWithXmlDescriptions_LogMethod.json @@ -1,73 +1,71 @@ -{ - "Name": "test.dll", - "ComplianceReport": { +{ "Name": "test.dll", "ComplianceReport": +{ "Types": [ - { - "Name": "Test.LogMethod", - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "14" - } + { + "Name": "Test.LogMethod", + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "14" + } + ] + } ] - } - ] - } + } ] - }, - "MetricReport": [ +} , "MetricReport": [ + { + "TestClasses": + [ { - "TestClasses": [ - { - "MetricName": "DescribedDimensionCounter", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "Dimension1": "Dimension1 description.", - "Dim1": "" - } - }, - { - "MetricName": "DescribedDimensionHistogram", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Histogram", - "Dimensions": { - "Dimension2": "Dimension2 description.", - "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." - } - }, - { - "MetricName": "MyStrongTypeMetricWithDescription", - "MetricDescription": "(Missing Summary)", - "InstrumentName": "Counter", - "Dimensions": { - "AnotherDimension": "Gets or sets anotherDimension.", - "MetricEnum": "Gets or sets MetricEnum.", - "MetricEnum2": "Gets or sets MetricEnum2.", - "Dim2": "Gets or sets Dim2.", - "SomeDim": "Gets or sets SomeDim.", - "Dim4Struct": "Gets or sets Dim4Struct.", - "Dim5Struct": "Gets or sets Dim5Struct." - } - } - ] + "MetricName": "DescribedDimensionCounter", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "Dimension1": "Dimension1 description.", + "Dim1": "" + } + }, + { + "MetricName": "DescribedDimensionHistogram", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Histogram", + "Dimensions": { + "Dimension2": "Dimension2 description.", + "DimensionDefinedInMetricClass": "DimensionDefinedInMetricClass description." + } + }, + { + "MetricName": "MyStrongTypeMetricWithDescription", + "MetricDescription": "(Missing Summary)", + "InstrumentName": "Counter", + "Dimensions": { + "AnotherDimension": "Gets or sets anotherDimension.", + "MetricEnum": "Gets or sets MetricEnum.", + "MetricEnum2": "Gets or sets MetricEnum2.", + "Dim2": "Gets or sets Dim2.", + "SomeDim": "Gets or sets SomeDim.", + "Dim4Struct": "Gets or sets Dim4Struct.", + "Dim5Struct": "Gets or sets Dim5Struct." + } } ] -} + } +] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json index bd03c28dcd1..7e78ce5d2ad 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/GoldenReports/RecordProperty.json @@ -1,203 +1,200 @@ +{ "Name": "test.dll", "ComplianceReport": { - "Name": "test.dll", - "ComplianceReport": { "Types": [ - { - "Name": "Test.DerivedRecordProperty", - "Members": [ - { - "Name": "EqualityContract", - "Type": "System.Type", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C1" - } + { + "Name": "Test.DerivedRecordProperty", + "Members": [ + { + "Name": "EqualityContract", + "Type": "System.Type", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C1" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "23", + "Classifications": [ + { + "Name": "C1" + }, + { + "Name": "C2", + "Notes": "Note 2" + }, + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } ] - }, - { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "17", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } + }, + { + "Name": "Test.RecordProperty", + "Members": [ + { + "Name": "F0", + "Type": "string", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "F2", + "Type": "int", + "File": "src-0.cs", + "Line": "14", + "Classifications": [ + { + "Name": "C3" + } + ] + }, + { + "Name": "F3", + "Type": "int", + "File": "src-0.cs", + "Line": "17", + "Classifications": [ + { + "Name": "C2", + "Notes": "Note 1" + } + ] + }, + { + "Name": "F4", + "Type": "int", + "File": "src-0.cs", + "Line": "20", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "P0", + "Type": "int", + "File": "src-0.cs", + "Line": "11", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + }, + { + "Name": "C4" + } + ] + }, + { + "Name": "P1", + "Type": "int", + "File": "src-0.cs", + "Line": "26", + "Classifications": [ + { + "Name": "C3" + } + ] + } + ], + "Logging Methods": [ + { + "Name": "LogHello", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "29", + "Classifications": [ + { + "Name": "C3", + "Notes": "Note 3" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "29" + } + ] + }, + { + "Name": "LogWorld", + "Parameters": [ + { + "Name": "user", + "Type": "string", + "File": "src-0.cs", + "Line": "32", + "Classifications": [ + { + "Name": "C2" + } + ] + }, + { + "Name": "port", + "Type": "int", + "File": "src-0.cs", + "Line": "32" + } + ] + } ] - }, - { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "20", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "23", - "Classifications": [ - { - "Name": "C1" - }, - { - "Name": "C2", - "Notes": "Note 2" - }, - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "26", - "Classifications": [ - { - "Name": "C3" - } - ] - } - ] - }, - { - "Name": "Test.RecordProperty", - "Members": [ - { - "Name": "F0", - "Type": "string", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "F2", - "Type": "int", - "File": "src-0.cs", - "Line": "14", - "Classifications": [ - { - "Name": "C3" - } - ] - }, - { - "Name": "F3", - "Type": "int", - "File": "src-0.cs", - "Line": "17", - "Classifications": [ - { - "Name": "C2", - "Notes": "Note 1" - } - ] - }, - { - "Name": "F4", - "Type": "int", - "File": "src-0.cs", - "Line": "20", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "P0", - "Type": "int", - "File": "src-0.cs", - "Line": "11", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - }, - { - "Name": "C4" - } - ] - }, - { - "Name": "P1", - "Type": "int", - "File": "src-0.cs", - "Line": "26", - "Classifications": [ - { - "Name": "C3" - } - ] - } - ], - "Logging Methods": [ - { - "Name": "LogHello", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "29", - "Classifications": [ - { - "Name": "C3", - "Notes": "Note 3" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "29" - } - ] - }, - { - "Name": "LogWorld", - "Parameters": [ - { - "Name": "user", - "Type": "string", - "File": "src-0.cs", - "Line": "32", - "Classifications": [ - { - "Name": "C2" - } - ] - }, - { - "Name": "port", - "Type": "int", - "File": "src-0.cs", - "Line": "32" - } - ] - } - ] - } + } ] - }, - "MetricReport": [] -} +} , "MetricReport": [] } \ No newline at end of file diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index aa2fda5a1f3..96b05cc3d94 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -94,12 +94,6 @@ public async Task TestAll(bool useExplicitReportPath) File.Delete(generatedReportPath); - golden = Regex.Replace(golden, @"\s+", ""); - generated = Regex.Replace(generated, @"\s+", ""); - - golden = golden.Replace("\r\n", "\n"); - generated = generated.Replace("\r\n", "\n"); - Assert.Equal(golden, generated); } else From 61d77671057d368bc0c0873b601a0223887e286f Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 11:47:59 +0300 Subject: [PATCH 24/25] adding comments --- .../Unit/GeneratorTests.cs | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index 96b05cc3d94..3d722777a90 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Reflection; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -20,6 +19,10 @@ namespace Microsoft.Gen.MetadataExtractor.Unit.Tests; +/// +/// Tests for the . +/// +/// The test output helper. public class GeneratorTests(ITestOutputHelper output) { private const string ReportFilename = "MetadataReport.json"; @@ -47,6 +50,9 @@ public C4Attribute(new DataClassification(""TAX"", 8)) { } } "; + /// + /// Generator should not do anything if general execution context does not have class declaration. + /// [Fact] public void GeneratorShouldNotDoAnythingIfGeneralExecutionContextDoesNotHaveClassDeclarationSyntaxReceiver() { @@ -56,6 +62,11 @@ public void GeneratorShouldNotDoAnythingIfGeneralExecutionContextDoesNotHaveClas Assert.Null(defaultGeneralExecutionContext.SyntaxReceiver); } + + /// + /// Tests Generations for both compliance & metric or both or none. + /// + /// The Use Explicit Report Path. [Theory] [CombinatorialData] public async Task TestAll(bool useExplicitReportPath) @@ -105,6 +116,9 @@ public async Task TestAll(bool useExplicitReportPath) } } + /// + /// Generator should not do anything if there are no class declarations. + /// [Fact] public async Task ShouldNot_Generate_WhenDisabledViaConfig() { @@ -121,6 +135,10 @@ public async Task ShouldNot_Generate_WhenDisabledViaConfig() Assert.False(File.Exists(Path.Combine(Path.GetTempPath(), ReportFilename))); } + /// + /// Generator should emit warning when path is not provided. + /// + /// If the report path is provided. [Theory] [CombinatorialData] public async Task Should_EmitWarning_WhenPathUnavailable(bool isReportPathProvided) @@ -142,6 +160,9 @@ public async Task Should_EmitWarning_WhenPathUnavailable(bool isReportPathProvid Assert.Equal(DiagnosticSeverity.Info, diag.Severity); } + /// + /// Generator should emit warning when path is not provided. + /// [Fact] public async Task Should_UseProjectDir_WhenOutputPathIsRelative() { @@ -169,6 +190,13 @@ public async Task Should_UseProjectDir_WhenOutputPathIsRelative() } } + /// + /// Runs the generator on the given code. + /// + /// The coded that the generation will be based-on. + /// The analyzer options. + /// The cancellation Token. + /// The report file name. private static async Task> RunGenerator( string code, Dictionary? analyzerOptions = null, @@ -201,6 +229,9 @@ private static async Task> RunGenerator( return d; } + /// + /// Options for the generator. + /// private sealed class Options : AnalyzerConfigOptions { private readonly Dictionary _options; @@ -216,6 +247,10 @@ public override bool TryGetValue(string key, out string value) => _options.TryGetValue(key, out value!); } + /// + /// Options provider for the generator. + /// + /// The analyzer options. private sealed class OptionsProvider(Dictionary? analyzerOptions) : AnalyzerConfigOptionsProvider { public override AnalyzerConfigOptions GlobalOptions => new Options(analyzerOptions); From 5c5f2e3ec1b57c5e584b12a5bef19998a7ba83af Mon Sep 17 00:00:00 2001 From: Ibrahim Nada Date: Fri, 18 Oct 2024 12:15:45 +0300 Subject: [PATCH 25/25] remove blanks --- .../Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs index 3d722777a90..5e7c749d426 100644 --- a/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs +++ b/test/Generators/Microsoft.Gen.MetadataExtractor/Unit/GeneratorTests.cs @@ -62,7 +62,6 @@ public void GeneratorShouldNotDoAnythingIfGeneralExecutionContextDoesNotHaveClas Assert.Null(defaultGeneralExecutionContext.SyntaxReceiver); } - /// /// Tests Generations for both compliance & metric or both or none. ///